blob: 906dc9577a9efc34048904943992beb8134c0f00 [file] [log] [blame]
b.liue9582032025-04-17 19:18:16 +08001/*
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 <stdlib.h>
18#include <stdio.h>
19#include <unistd.h>
20#include <string.h>
21#include <fcntl.h>
22#include <errno.h>
23#include <sys/types.h>
24#include <sys/wait.h>
25
26#include "fdevent.h"
27#include "adb.h"
28
29#include <linux/fb.h>
30#include <sys/ioctl.h>
31#include <sys/mman.h>
32
33#ifndef TEMP_FAILURE_RETRY
34/* Used to retry syscalls that can return EINTR. */
35#define TEMP_FAILURE_RETRY(exp) ({ \
36 typeof (exp) _rc; \
37 do { \
38 _rc = (exp); \
39 } while (_rc == -1 && errno == EINTR); \
40 _rc; })
41#endif
42
43/* TODO:
44** - sync with vsync to avoid tearing
45*/
46/* This version number defines the format of the fbinfo struct.
47 It must match versioning in ddms where this data is consumed. */
48#define DDMS_RAWIMAGE_VERSION 1
49struct fbinfo {
50 unsigned int version;
51 unsigned int bpp;
52 unsigned int size;
53 unsigned int width;
54 unsigned int height;
55 unsigned int red_offset;
56 unsigned int red_length;
57 unsigned int blue_offset;
58 unsigned int blue_length;
59 unsigned int green_offset;
60 unsigned int green_length;
61 unsigned int alpha_offset;
62 unsigned int alpha_length;
63} __attribute__((packed));
64
65void framebuffer_service(int fd, void *cookie)
66{
67 struct fbinfo fbinfo;
68 unsigned int i, bsize;
69 char buf[640];
70 int fd_screencap;
71 int w, h, f;
72 int fds[2];
73
74 if (pipe2(fds, O_CLOEXEC) < 0) goto pipefail;
75
76 pid_t pid = fork();
77 if (pid < 0) goto done;
78
79 if (pid == 0) {
80 dup2(fds[1], STDOUT_FILENO);
81 close(fds[0]);
82 close(fds[1]);
83 const char* command = "screencap";
84 const char *args[2] = {command, NULL};
85 execvp(command, (char**)args);
86 exit(1);
87 }
88
89 fd_screencap = fds[0];
90
91 /* read w, h & format */
92 if(readx(fd_screencap, &w, 4)) goto done;
93 if(readx(fd_screencap, &h, 4)) goto done;
94 if(readx(fd_screencap, &f, 4)) goto done;
95
96 fbinfo.version = DDMS_RAWIMAGE_VERSION;
97 /* see hardware/hardware.h */
98 switch (f) {
99 case 1: /* RGBA_8888 */
100 fbinfo.bpp = 32;
101 fbinfo.size = w * h * 4;
102 fbinfo.width = w;
103 fbinfo.height = h;
104 fbinfo.red_offset = 0;
105 fbinfo.red_length = 8;
106 fbinfo.green_offset = 8;
107 fbinfo.green_length = 8;
108 fbinfo.blue_offset = 16;
109 fbinfo.blue_length = 8;
110 fbinfo.alpha_offset = 24;
111 fbinfo.alpha_length = 8;
112 break;
113 case 2: /* RGBX_8888 */
114 fbinfo.bpp = 32;
115 fbinfo.size = w * h * 4;
116 fbinfo.width = w;
117 fbinfo.height = h;
118 fbinfo.red_offset = 0;
119 fbinfo.red_length = 8;
120 fbinfo.green_offset = 8;
121 fbinfo.green_length = 8;
122 fbinfo.blue_offset = 16;
123 fbinfo.blue_length = 8;
124 fbinfo.alpha_offset = 24;
125 fbinfo.alpha_length = 0;
126 break;
127 case 3: /* RGB_888 */
128 fbinfo.bpp = 24;
129 fbinfo.size = w * h * 3;
130 fbinfo.width = w;
131 fbinfo.height = h;
132 fbinfo.red_offset = 0;
133 fbinfo.red_length = 8;
134 fbinfo.green_offset = 8;
135 fbinfo.green_length = 8;
136 fbinfo.blue_offset = 16;
137 fbinfo.blue_length = 8;
138 fbinfo.alpha_offset = 24;
139 fbinfo.alpha_length = 0;
140 break;
141 case 4: /* RGB_565 */
142 fbinfo.bpp = 16;
143 fbinfo.size = w * h * 2;
144 fbinfo.width = w;
145 fbinfo.height = h;
146 fbinfo.red_offset = 11;
147 fbinfo.red_length = 5;
148 fbinfo.green_offset = 5;
149 fbinfo.green_length = 6;
150 fbinfo.blue_offset = 0;
151 fbinfo.blue_length = 5;
152 fbinfo.alpha_offset = 0;
153 fbinfo.alpha_length = 0;
154 break;
155 case 5: /* BGRA_8888 */
156 fbinfo.bpp = 32;
157 fbinfo.size = w * h * 4;
158 fbinfo.width = w;
159 fbinfo.height = h;
160 fbinfo.red_offset = 16;
161 fbinfo.red_length = 8;
162 fbinfo.green_offset = 8;
163 fbinfo.green_length = 8;
164 fbinfo.blue_offset = 0;
165 fbinfo.blue_length = 8;
166 fbinfo.alpha_offset = 24;
167 fbinfo.alpha_length = 8;
168 break;
169 default:
170 goto done;
171 }
172
173 /* write header */
174 if(writex(fd, &fbinfo, sizeof(fbinfo))) goto done;
175
176 /* write data */
177 for(i = 0; i < fbinfo.size; i += bsize) {
178 bsize = sizeof(buf);
179 if (i + bsize > fbinfo.size)
180 bsize = fbinfo.size - i;
181 if(readx(fd_screencap, buf, bsize)) goto done;
182 if(writex(fd, buf, bsize)) goto done;
183 }
184
185done:
186 TEMP_FAILURE_RETRY(waitpid(pid, NULL, 0));
187
188 close(fds[0]);
189 close(fds[1]);
190pipefail:
191 close(fd);
192}