1 /* 2 * Copyright (C) 2007 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include "framebuffer_service.h" 18 19 #include <errno.h> 20 #include <fcntl.h> 21 #include <linux/fb.h> 22 #include <stdio.h> 23 #include <stdlib.h> 24 #include <string.h> 25 #include <sys/ioctl.h> 26 #include <sys/mman.h> 27 #include <sys/types.h> 28 #include <sys/wait.h> 29 #include <unistd.h> 30 31 #include "sysdeps.h" 32 33 #include "adb.h" 34 #include "adb_io.h" 35 #include "adb_utils.h" 36 37 /* TODO: 38 ** - sync with vsync to avoid tearing 39 */ 40 /* This version number defines the format of the fbinfo struct. 41 It must match versioning in ddms where this data is consumed. */ 42 #define DDMS_RAWIMAGE_VERSION 2 43 struct fbinfo { 44 unsigned int version; 45 unsigned int bpp; 46 unsigned int colorSpace; 47 unsigned int size; 48 unsigned int width; 49 unsigned int height; 50 unsigned int red_offset; 51 unsigned int red_length; 52 unsigned int blue_offset; 53 unsigned int blue_length; 54 unsigned int green_offset; 55 unsigned int green_length; 56 unsigned int alpha_offset; 57 unsigned int alpha_length; 58 } __attribute__((packed)); 59 60 void framebuffer_service(unique_fd fd) { 61 struct fbinfo fbinfo; 62 unsigned int i, bsize; 63 char buf[640]; 64 int fd_screencap; 65 int w, h, f, c; 66 int fds[2]; 67 pid_t pid; 68 69 if (pipe2(fds, O_CLOEXEC) < 0) return; 70 71 pid = fork(); 72 if (pid < 0) goto done; 73 74 if (pid == 0) { 75 dup2(fds[1], STDOUT_FILENO); 76 adb_close(fds[0]); 77 adb_close(fds[1]); 78 const char* command = "screencap"; 79 const char *args[2] = {command, nullptr}; 80 execvp(command, (char**)args); 81 perror_exit("exec screencap failed"); 82 } 83 84 adb_close(fds[1]); 85 fd_screencap = fds[0]; 86 87 /* read w, h, format & color space */ 88 if(!ReadFdExactly(fd_screencap, &w, 4)) goto done; 89 if(!ReadFdExactly(fd_screencap, &h, 4)) goto done; 90 if(!ReadFdExactly(fd_screencap, &f, 4)) goto done; 91 if(!ReadFdExactly(fd_screencap, &c, 4)) goto done; 92 93 fbinfo.version = DDMS_RAWIMAGE_VERSION; 94 fbinfo.colorSpace = c; 95 /* see hardware/hardware.h */ 96 switch (f) { 97 case 1: /* RGBA_8888 */ 98 fbinfo.bpp = 32; 99 fbinfo.size = w * h * 4; 100 fbinfo.width = w; 101 fbinfo.height = h; 102 fbinfo.red_offset = 0; 103 fbinfo.red_length = 8; 104 fbinfo.green_offset = 8; 105 fbinfo.green_length = 8; 106 fbinfo.blue_offset = 16; 107 fbinfo.blue_length = 8; 108 fbinfo.alpha_offset = 24; 109 fbinfo.alpha_length = 8; 110 break; 111 case 2: /* RGBX_8888 */ 112 fbinfo.bpp = 32; 113 fbinfo.size = w * h * 4; 114 fbinfo.width = w; 115 fbinfo.height = h; 116 fbinfo.red_offset = 0; 117 fbinfo.red_length = 8; 118 fbinfo.green_offset = 8; 119 fbinfo.green_length = 8; 120 fbinfo.blue_offset = 16; 121 fbinfo.blue_length = 8; 122 fbinfo.alpha_offset = 24; 123 fbinfo.alpha_length = 0; 124 break; 125 case 3: /* RGB_888 */ 126 fbinfo.bpp = 24; 127 fbinfo.size = w * h * 3; 128 fbinfo.width = w; 129 fbinfo.height = h; 130 fbinfo.red_offset = 0; 131 fbinfo.red_length = 8; 132 fbinfo.green_offset = 8; 133 fbinfo.green_length = 8; 134 fbinfo.blue_offset = 16; 135 fbinfo.blue_length = 8; 136 fbinfo.alpha_offset = 24; 137 fbinfo.alpha_length = 0; 138 break; 139 case 4: /* RGB_565 */ 140 fbinfo.bpp = 16; 141 fbinfo.size = w * h * 2; 142 fbinfo.width = w; 143 fbinfo.height = h; 144 fbinfo.red_offset = 11; 145 fbinfo.red_length = 5; 146 fbinfo.green_offset = 5; 147 fbinfo.green_length = 6; 148 fbinfo.blue_offset = 0; 149 fbinfo.blue_length = 5; 150 fbinfo.alpha_offset = 0; 151 fbinfo.alpha_length = 0; 152 break; 153 case 5: /* BGRA_8888 */ 154 fbinfo.bpp = 32; 155 fbinfo.size = w * h * 4; 156 fbinfo.width = w; 157 fbinfo.height = h; 158 fbinfo.red_offset = 16; 159 fbinfo.red_length = 8; 160 fbinfo.green_offset = 8; 161 fbinfo.green_length = 8; 162 fbinfo.blue_offset = 0; 163 fbinfo.blue_length = 8; 164 fbinfo.alpha_offset = 24; 165 fbinfo.alpha_length = 8; 166 break; 167 default: 168 goto done; 169 } 170 171 /* write header */ 172 if (!WriteFdExactly(fd.get(), &fbinfo, sizeof(fbinfo))) goto done; 173 174 /* write data */ 175 for(i = 0; i < fbinfo.size; i += bsize) { 176 bsize = sizeof(buf); 177 if (i + bsize > fbinfo.size) 178 bsize = fbinfo.size - i; 179 if(!ReadFdExactly(fd_screencap, buf, bsize)) goto done; 180 if (!WriteFdExactly(fd.get(), buf, bsize)) goto done; 181 } 182 183 done: 184 adb_close(fds[0]); 185 186 TEMP_FAILURE_RETRY(waitpid(pid, nullptr, 0)); 187 } 188