void framebuffer_service(int fd, void *cookie)
{
    struct fbinfo fbinfo;
    unsigned int i;
    char buf[640];
    int fd_screencap,fb;
    int w, h, f;
    int fds[2];

    if (pipe(fds) < 0) goto done;

    pid_t pid = fork();
    if (pid < 0) goto done;

    if (pid == 0) {
        dup2(fds[1], STDOUT_FILENO);
        close(fds[0]);
        close(fds[1]);
    #if (0 == LCDC_CAPTURE)
        const char* command = "screencap";
        const char *args[2] = {command, NULL};
        execvp(command, (char**)args);
        exit(1);
    #else // #if (LCDC_CAPTURE)
        if ((fb=open("/system/bin/lcdc_screen_cap",O_RDONLY)) >= 0){
            close(fb);
            const char * command = "lcdc_screen_cap";
	    const char *args[2] = {command, NULL};
            execvp(command, (char**)args);
            exit(1);
    }
        else{
        lcdc_screen_cap();
        exit(0);
        }
    #endif
    }

    fd_screencap = fds[0];

    /* read w, h & format */
    if(readx(fd_screencap, &w, 4)) goto error;
    if(readx(fd_screencap, &h, 4)) goto error;
    if(readx(fd_screencap, &f, 4)) goto error;

    fbinfo.version = DDMS_RAWIMAGE_VERSION;
    /* see hardware/hardware.h */
    switch (f) {
        case 1: /* RGBA_8888 */
            fbinfo.bpp = 32;
            fbinfo.size = w * h * 4;
            fbinfo.width = w;
            fbinfo.height = h;
            fbinfo.red_offset = 0;
            fbinfo.red_length = 8;
            fbinfo.green_offset = 8;
            fbinfo.green_length = 8;
            fbinfo.blue_offset = 16;
            fbinfo.blue_length = 8;
            fbinfo.alpha_offset = 24;
            fbinfo.alpha_length = 8;
            break;
        case 2: /* RGBX_8888 */
            fbinfo.bpp = 32;
            fbinfo.size = w * h * 4;
            fbinfo.width = w;
            fbinfo.height = h;
            fbinfo.red_offset = 0;
            fbinfo.red_length = 8;
            fbinfo.green_offset = 8;
            fbinfo.green_length = 8;
            fbinfo.blue_offset = 16;
            fbinfo.blue_length = 8;
            fbinfo.alpha_offset = 24;
            fbinfo.alpha_length = 0;
            break;
        case 3: /* RGB_888 */
            fbinfo.bpp = 24;
            fbinfo.size = w * h * 3;
            fbinfo.width = w;
            fbinfo.height = h;
            fbinfo.red_offset = 0;
            fbinfo.red_length = 8;
            fbinfo.green_offset = 8;
            fbinfo.green_length = 8;
            fbinfo.blue_offset = 16;
            fbinfo.blue_length = 8;
            fbinfo.alpha_offset = 24;
            fbinfo.alpha_length = 0;
            break;
        case 4: /* RGB_565 */
            fbinfo.bpp = 16;
            fbinfo.size = w * h * 2;
            fbinfo.width = w;
            fbinfo.height = h;
            fbinfo.red_offset = 11;
            fbinfo.red_length = 5;
            fbinfo.green_offset = 5;
            fbinfo.green_length = 6;
            fbinfo.blue_offset = 0;
            fbinfo.blue_length = 5;
            fbinfo.alpha_offset = 0;
            fbinfo.alpha_length = 0;
            break;
        case 5: /* BGRA_8888 */
            fbinfo.bpp = 32;
            fbinfo.size = w * h * 4;
            fbinfo.width = w;
            fbinfo.height = h;
            fbinfo.red_offset = 16;
            fbinfo.red_length = 8;
            fbinfo.green_offset = 8;
            fbinfo.green_length = 8;
            fbinfo.blue_offset = 0;
            fbinfo.blue_length = 8;
            fbinfo.alpha_offset = 24;
            fbinfo.alpha_length = 8;
           break;
        default:
            goto done;
    }

    /* write header */
    if(writex(fd, &fbinfo, sizeof(fbinfo))) goto error;

    /* write data */
    for(i = 0; i < fbinfo.size; i += sizeof(buf)) {
      if ((fbinfo.size - i) < sizeof(buf)) {
        break;
      }    	
      if(readx(fd_screencap, buf, sizeof(buf))) goto error;
      if(writex(fd, buf, sizeof(buf))) goto error;
    }
    if(readx(fd_screencap, buf, fbinfo.size % sizeof(buf))) goto error;
    if(writex(fd, buf, fbinfo.size % sizeof(buf))) goto error;

done:
    TEMP_FAILURE_RETRY(waitpid(pid, NULL, 0));
     goto close_fd;

error:
      /*Alternatively, closes fds should also assure lcdc_screen_cap not block by wrting pipe*/
     if(0 == kill(pid, SIGTERM)){
        XLOGI("[ADB] Sent SIGTERM to process %d\n", pid);
     }else{
        XLOGE("[ADB] Failed to send SIGTERM to process %d, errno=%s\n",pid, strerror(errno));
        /*Note that even parent process failed to send signal,
        child process(lcdc_screen_cap) should still exit normally*/
     }
     goto close_fd;

close_fd:
    close(fds[0]);
    close(fds[1]);
    close(fd);
}
예제 #2
0
void framebuffer_service(int fd, void *cookie)
{
    struct fbinfo fbinfo;
    unsigned int i;
    char buf[640];
    int fd_screencap,fb;
    int w, h, f;
    int fds[2];

    if (pipe(fds) < 0) goto done;

    pid_t pid = fork();
    if (pid < 0) goto done;

    if (pid == 0) {
        dup2(fds[1], STDOUT_FILENO);
        close(fds[0]);
        close(fds[1]);
    #if (0 == LCDC_CAPTURE)
        const char* command = "screencap";
        const char *args[2] = {command, NULL};
        execvp(command, (char**)args);
        exit(1);
    #else // #if (LCDC_CAPTURE)
        if ((fb=open("/system/bin/lcdc_screen_cap",O_RDONLY)) >= 0){
            close(fb);
            const char * command = "lcdc_screen_cap";
	    const char *args[2] = {command, NULL};
            execvp(command, (char**)args);
            exit(1);
    }
        else{
        lcdc_screen_cap();
        exit(0);
        }
    #endif
    }

    fd_screencap = fds[0];

    /* read w, h & format */
    if(readx(fd_screencap, &w, 4)) goto done;
    if(readx(fd_screencap, &h, 4)) goto done;
    if(readx(fd_screencap, &f, 4)) goto done;

    fbinfo.version = DDMS_RAWIMAGE_VERSION;
    /* see hardware/hardware.h */
    switch (f) {
        case 1: /* RGBA_8888 */
            fbinfo.bpp = 32;
            fbinfo.size = w * h * 4;
            fbinfo.width = w;
            fbinfo.height = h;
            fbinfo.red_offset = 0;
            fbinfo.red_length = 8;
            fbinfo.green_offset = 8;
            fbinfo.green_length = 8;
            fbinfo.blue_offset = 16;
            fbinfo.blue_length = 8;
            fbinfo.alpha_offset = 24;
            fbinfo.alpha_length = 8;
            break;
        case 2: /* RGBX_8888 */
            fbinfo.bpp = 32;
            fbinfo.size = w * h * 4;
            fbinfo.width = w;
            fbinfo.height = h;
            fbinfo.red_offset = 0;
            fbinfo.red_length = 8;
            fbinfo.green_offset = 8;
            fbinfo.green_length = 8;
            fbinfo.blue_offset = 16;
            fbinfo.blue_length = 8;
            fbinfo.alpha_offset = 24;
            fbinfo.alpha_length = 0;
            break;
        case 3: /* RGB_888 */
            fbinfo.bpp = 24;
            fbinfo.size = w * h * 3;
            fbinfo.width = w;
            fbinfo.height = h;
            fbinfo.red_offset = 0;
            fbinfo.red_length = 8;
            fbinfo.green_offset = 8;
            fbinfo.green_length = 8;
            fbinfo.blue_offset = 16;
            fbinfo.blue_length = 8;
            fbinfo.alpha_offset = 24;
            fbinfo.alpha_length = 0;
            break;
        case 4: /* RGB_565 */
            fbinfo.bpp = 16;
            fbinfo.size = w * h * 2;
            fbinfo.width = w;
            fbinfo.height = h;
            fbinfo.red_offset = 11;
            fbinfo.red_length = 5;
            fbinfo.green_offset = 5;
            fbinfo.green_length = 6;
            fbinfo.blue_offset = 0;
            fbinfo.blue_length = 5;
            fbinfo.alpha_offset = 0;
            fbinfo.alpha_length = 0;
            break;
        case 5: /* BGRA_8888 */
            fbinfo.bpp = 32;
            fbinfo.size = w * h * 4;
            fbinfo.width = w;
            fbinfo.height = h;
            fbinfo.red_offset = 16;
            fbinfo.red_length = 8;
            fbinfo.green_offset = 8;
            fbinfo.green_length = 8;
            fbinfo.blue_offset = 0;
            fbinfo.blue_length = 8;
            fbinfo.alpha_offset = 24;
            fbinfo.alpha_length = 8;
           break;
        default:
            goto done;
    }

    /* write header */
    if(writex(fd, &fbinfo, sizeof(fbinfo))) goto done;

    /* write data */
    for(i = 0; i < fbinfo.size; i += sizeof(buf)) {
      if(readx(fd_screencap, buf, sizeof(buf))) goto done;
      if(writex(fd, buf, sizeof(buf))) goto done;
    }
    if(readx(fd_screencap, buf, fbinfo.size % sizeof(buf))) goto done;
    if(writex(fd, buf, fbinfo.size % sizeof(buf))) goto done;

done:
    TEMP_FAILURE_RETRY(waitpid(pid, NULL, 0));

    close(fds[0]);
    close(fds[1]);
    close(fd);
}