• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright (C) 2010 The Android Open Source Project
2 **
3 ** This software is licensed under the terms of the GNU General Public
4 ** License version 2, as published by the Free Software Foundation, and
5 ** may be copied, distributed, and modified under those terms.
6 **
7 ** This program is distributed in the hope that it will be useful,
8 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
9 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10 ** GNU General Public License for more details.
11 */
12 
13 /*
14  * Contains UI-side framebuffer client that receives framebuffer updates
15  * from the core.
16  */
17 
18 #include "android/utils/system.h"
19 #include "android/utils/debug.h"
20 #include "android/utils/panic.h"
21 #include "android/sync-utils.h"
22 #include "android/protocol/core-connection.h"
23 #include "android/protocol/fb-updates.h"
24 #include "android/protocol/fb-updates-impl.h"
25 
26 /*Enumerates states for the client framebuffer update reader. */
27 typedef enum FbImplState {
28     /* The reader is waiting on update header. */
29     EXPECTS_HEADER,
30 
31     /* The reader is waiting on pixels. */
32     EXPECTS_PIXELS,
33 } FbImplState;
34 
35 /* Descriptor for the UI-side implementation of the "framebufer" service.
36  */
37 typedef struct FrameBufferImpl {
38     /* Framebuffer for this client. */
39     QFrameBuffer*   fb;
40 
41     /* Core connection instance for the framebuffer client. */
42     CoreConnection* core_connection;
43 
44     /* Current update header. */
45     FBUpdateMessage update_header;
46 
47     /* Reader's buffer. */
48     uint8_t*        reader_buffer;
49 
50     /* Offset in the reader's buffer where to read next chunk of data. */
51     size_t          reader_offset;
52 
53     /* Total number of bytes the reader expects to read. */
54     size_t          reader_bytes;
55 
56     /* Current state of the update reader. */
57     FbImplState     fb_state;
58 
59     /* Socket descriptor for the framebuffer client. */
60     int             sock;
61 
62     /* Custom i/o handler */
63     LoopIo          io[1];
64 
65     /* Number of bits used to encode single pixel. */
66     int             bits_per_pixel;
67 } FrameBufferImpl;
68 
69 /* One and the only FrameBufferImpl instance. */
70 static FrameBufferImpl _fbImpl;
71 
72 /*
73  * Updates a display rectangle.
74  * Param
75  *  fb - Framebuffer where to update the rectangle.
76  *  x, y, w, and h define rectangle to update.
77  *  bits_per_pixel define number of bits used to encode a single pixel.
78  *  pixels contains pixels for the rectangle. Buffer addressed by this parameter
79  *      must be eventually freed with free()
80  */
81 static void
_update_rect(QFrameBuffer * fb,uint16_t x,uint16_t y,uint16_t w,uint16_t h,uint8_t bits_per_pixel,uint8_t * pixels)82 _update_rect(QFrameBuffer* fb, uint16_t x, uint16_t y, uint16_t w, uint16_t h,
83              uint8_t bits_per_pixel, uint8_t* pixels)
84 {
85     if (fb != NULL) {
86         uint16_t n;
87         const uint8_t* src = pixels;
88         const uint16_t src_line_size = w * ((bits_per_pixel + 7) / 8);
89         uint8_t* dst  = (uint8_t*)fb->pixels + y * fb->pitch + x *
90                         fb->bytes_per_pixel;
91         for (n = 0; n < h; n++) {
92             memcpy(dst, src, src_line_size);
93             src += src_line_size;
94             dst += fb->pitch;
95         }
96         qframebuffer_update(fb, x, y, w, h);
97     }
98     free(pixels);
99 }
100 
101 /*
102  * Asynchronous I/O callback launched when framebuffer notifications are ready
103  * to be read.
104  * Param:
105  *  opaque - FrameBufferImpl instance.
106  */
107 static void
_fbUpdatesImpl_io_callback(void * opaque,int fd,unsigned events)108 _fbUpdatesImpl_io_callback(void* opaque, int fd, unsigned events)
109 {
110     FrameBufferImpl* fbi = opaque;
111     int  ret;
112 
113     // Read updates while they are immediately available.
114     for (;;) {
115         // Read next chunk of data.
116         ret = socket_recv(fbi->sock, fbi->reader_buffer + fbi->reader_offset,
117                           fbi->reader_bytes - fbi->reader_offset);
118         if (ret == 0) {
119             /* disconnection ! */
120             fbUpdatesImpl_destroy();
121             return;
122         }
123         if (ret < 0) {
124             if (errno == EINTR) {
125                 /* loop on EINTR */
126                 continue;
127             } else if (errno == EWOULDBLOCK || errno == EAGAIN) {
128                 // Chunk is not avalable at this point. Come back later.
129                 return;
130             }
131         }
132 
133         fbi->reader_offset += ret;
134         if (fbi->reader_offset != fbi->reader_bytes) {
135             // There are still some data left in the pipe.
136             continue;
137         }
138 
139         // All expected data has been read. Time to change the state.
140         if (fbi->fb_state == EXPECTS_HEADER) {
141             // Update header has been read. Prepare for the pixels.
142             fbi->fb_state = EXPECTS_PIXELS;
143             fbi->reader_offset = 0;
144             fbi->reader_bytes = fbi->update_header.w *
145                                       fbi->update_header.h *
146                                       (fbi->bits_per_pixel / 8);
147             fbi->reader_buffer = malloc(fbi->reader_bytes);
148             if (fbi->reader_buffer == NULL) {
149                 APANIC("Unable to allocate memory for framebuffer update\n");
150             }
151         } else {
152             // Pixels have been read. Prepare for the header.
153              uint8_t* pixels = fbi->reader_buffer;
154 
155             fbi->fb_state = EXPECTS_HEADER;
156             fbi->reader_offset = 0;
157             fbi->reader_bytes = sizeof(FBUpdateMessage);
158             fbi->reader_buffer = (uint8_t*)&fbi->update_header;
159 
160             // Perform the update. Note that pixels buffer must be freed there.
161             _update_rect(fbi->fb, fbi->update_header.x,
162                         fbi->update_header.y, fbi->update_header.w,
163                         fbi->update_header.h, fbi->bits_per_pixel,
164                         pixels);
165         }
166     }
167 }
168 
169 int
fbUpdatesImpl_create(SockAddress * console_socket,const char * protocol,QFrameBuffer * fb,Looper * looper)170 fbUpdatesImpl_create(SockAddress* console_socket,
171               const char* protocol,
172               QFrameBuffer* fb,
173               Looper* looper)
174 {
175     FrameBufferImpl* fbi = &_fbImpl;
176     char* handshake = NULL;
177     char switch_cmd[256];
178 
179     // Initialize descriptor.
180     fbi->fb = fb;
181     fbi->reader_buffer = (uint8_t*)&fbi->update_header;
182     fbi->reader_offset = 0;
183     fbi->reader_bytes = sizeof(FBUpdateMessage);
184 
185     // Connect to the framebuffer service.
186     snprintf(switch_cmd, sizeof(switch_cmd), "framebuffer %s", protocol);
187     fbi->core_connection =
188         core_connection_create_and_switch(console_socket, switch_cmd, &handshake);
189     if (fbi->core_connection == NULL) {
190         derror("Unable to connect to the framebuffer service: %s\n",
191                errno_str);
192         return -1;
193     }
194 
195     // We expect core framebuffer to return us bits per pixel property in
196     // the handshake message.
197     fbi->bits_per_pixel = 0;
198     if (handshake != NULL) {
199         char* bpp = strstr(handshake, "bitsperpixel=");
200         if (bpp != NULL) {
201             char* end;
202             bpp += strlen("bitsperpixel=");
203             end = strchr(bpp, ' ');
204             if (end == NULL) {
205                 end = bpp + strlen(bpp);
206             }
207             fbi->bits_per_pixel = strtol(bpp, &end, 0);
208         }
209     }
210     if (!fbi->bits_per_pixel) {
211         derror("Unexpected core framebuffer reply: %s\n"
212                "Bits per pixel property is not there, or is invalid\n",
213                handshake);
214         fbUpdatesImpl_destroy();
215         return -1;
216     }
217 
218     fbi->sock = core_connection_get_socket(fbi->core_connection);
219 
220     // At last setup read callback, and start receiving the updates.
221     loopIo_init(fbi->io, looper, fbi->sock,
222                 _fbUpdatesImpl_io_callback, &_fbImpl);
223     loopIo_wantRead(fbi->io);
224     {
225         // Force the core to send us entire framebuffer now, when we're prepared
226         // to receive it.
227         FBRequestHeader hd;
228         SyncSocket* sk = syncsocket_init(fbi->sock);
229 
230         hd.request_type = AFB_REQUEST_REFRESH;
231         syncsocket_start_write(sk);
232         syncsocket_write(sk, &hd, sizeof(hd), 5000);
233         syncsocket_stop_write(sk);
234         syncsocket_free(sk);
235     }
236 
237     fprintf(stdout, "framebuffer is now connected to the core at %s.",
238             sock_address_to_string(console_socket));
239     if (handshake != NULL) {
240         if (handshake[0] != '\0') {
241             fprintf(stdout, " Handshake: %s", handshake);
242         }
243         free(handshake);
244     }
245     fprintf(stdout, "\n");
246 
247     return 0;
248 }
249 
250 void
fbUpdatesImpl_destroy(void)251 fbUpdatesImpl_destroy(void)
252 {
253     FrameBufferImpl* fbi = &_fbImpl;
254 
255     if (fbi->core_connection != NULL) {
256         // Disable the reader callback.
257         loopIo_done(fbi->io);
258 
259         // Close framebuffer connection.
260         core_connection_close(fbi->core_connection);
261         core_connection_free(fbi->core_connection);
262         fbi->core_connection = NULL;
263     }
264 
265     fbi->fb = NULL;
266     if (fbi->reader_buffer != NULL &&
267         fbi->reader_buffer != (uint8_t*)&fbi->update_header) {
268         free(fbi->reader_buffer);
269         fbi->reader_buffer = (uint8_t*)&fbi->update_header;
270     }
271 }
272