• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright (C) 2011 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 #include <signal.h>
13 #include <unistd.h>
14 #include <string.h>
15 #include <sys/time.h>
16 #include <errno.h>
17 #include <fcntl.h>
18 #ifdef _WIN32
19 #include <process.h>
20 #endif
21 
22 #include <SDL.h>
23 #include <SDL_syswm.h>
24 
25 #include "console.h"
26 
27 #include "android/avd/util.h"
28 #include "android/utils/debug.h"
29 #include "android/utils/path.h"
30 #include "android/utils/bufprint.h"
31 #include "android/utils/dirscanner.h"
32 #include "android/main-common.h"
33 #include "android/globals.h"
34 #include "android/resource.h"
35 #include "android/user-config.h"
36 #include "android/qemulator.h"
37 #include "android/display.h"
38 #include "android/skin/image.h"
39 #include "android/skin/trackball.h"
40 #include "android/skin/keyboard.h"
41 #include "android/skin/file.h"
42 #include "android/skin/window.h"
43 
44 
45 
46 /***********************************************************************/
47 /***********************************************************************/
48 /*****                                                             *****/
49 /*****            U T I L I T Y   R O U T I N E S                  *****/
50 /*****                                                             *****/
51 /***********************************************************************/
52 /***********************************************************************/
53 
54 #define  D(...)  do {  if (VERBOSE_CHECK(init)) dprint(__VA_ARGS__); } while (0)
55 
56 /***  CONFIGURATION
57  ***/
58 
59 static AUserConfig*  userConfig;
60 
61 void
user_config_init(void)62 user_config_init( void )
63 {
64     userConfig = auserConfig_new( android_avdInfo );
65 }
66 
67 /* only call this function on normal exits, so that ^C doesn't save the configuration */
68 void
user_config_done(void)69 user_config_done( void )
70 {
71     int  win_x, win_y;
72 
73     if (!userConfig) {
74         D("no user configuration?");
75         return;
76     }
77 
78     SDL_WM_GetPos( &win_x, &win_y );
79     auserConfig_setWindowPos(userConfig, win_x, win_y);
80     auserConfig_save(userConfig);
81 }
82 
83 void
user_config_get_window_pos(int * window_x,int * window_y)84 user_config_get_window_pos( int *window_x, int *window_y )
85 {
86     *window_x = *window_y = 10;
87 
88     if (userConfig)
89         auserConfig_getWindowPos(userConfig, window_x, window_y);
90 }
91 
convertBytesToMB(uint64_t size)92 unsigned convertBytesToMB( uint64_t  size )
93 {
94     if (size == 0)
95         return 0;
96 
97     size = (size + ONE_MB-1) >> 20;
98     if (size > UINT_MAX)
99         size = UINT_MAX;
100 
101     return (unsigned) size;
102 }
103 
convertMBToBytes(unsigned megaBytes)104 uint64_t convertMBToBytes( unsigned  megaBytes )
105 {
106     return ((uint64_t)megaBytes << 20);
107 }
108 
109 
110 /***********************************************************************/
111 /***********************************************************************/
112 /*****                                                             *****/
113 /*****            K E Y S E T   R O U T I N E S                    *****/
114 /*****                                                             *****/
115 /***********************************************************************/
116 /***********************************************************************/
117 
118 #define  KEYSET_FILE    "default.keyset"
119 
120 SkinKeyset*  android_keyset = NULL;
121 
122 static int
load_keyset(const char * path)123 load_keyset(const char*  path)
124 {
125     if (path_can_read(path)) {
126         AConfig*  root = aconfig_node("","");
127         if (!aconfig_load_file(root, path)) {
128             android_keyset = skin_keyset_new(root);
129             if (android_keyset != NULL) {
130                 D( "keyset loaded from: %s", path);
131                 return 0;
132             }
133         }
134     }
135     return -1;
136 }
137 
138 void
parse_keyset(const char * keyset,AndroidOptions * opts)139 parse_keyset(const char*  keyset, AndroidOptions*  opts)
140 {
141     char   kname[MAX_PATH];
142     char   temp[MAX_PATH];
143     char*  p;
144     char*  end;
145 
146     /* append .keyset suffix if needed */
147     if (strchr(keyset, '.') == NULL) {
148         p   =  kname;
149         end = p + sizeof(kname);
150         p   = bufprint(p, end, "%s.keyset", keyset);
151         if (p >= end) {
152             derror( "keyset name too long: '%s'\n", keyset);
153             exit(1);
154         }
155         keyset = kname;
156     }
157 
158     /* look for a the keyset file */
159     p   = temp;
160     end = p + sizeof(temp);
161     p = bufprint_config_file(p, end, keyset);
162     if (p < end && load_keyset(temp) == 0)
163         return;
164 
165     p = temp;
166     p = bufprint(p, end, "%s" PATH_SEP "keysets" PATH_SEP "%s", opts->sysdir, keyset);
167     if (p < end && load_keyset(temp) == 0)
168         return;
169 
170     p = temp;
171     p = bufprint_app_dir(p, end);
172     p = bufprint(p, end, PATH_SEP "keysets" PATH_SEP "%s", keyset);
173     if (p < end && load_keyset(temp) == 0)
174         return;
175 
176     return;
177 }
178 
179 void
write_default_keyset(void)180 write_default_keyset( void )
181 {
182     char   path[MAX_PATH];
183 
184     bufprint_config_file( path, path+sizeof(path), KEYSET_FILE );
185 
186     /* only write if there is no file here */
187     if ( !path_exists(path) ) {
188         int          fd = open( path, O_WRONLY | O_CREAT, 0666 );
189         int          ret;
190         const char*  ks = skin_keyset_get_default();
191 
192 
193         D( "writing default keyset file to %s", path );
194 
195         if (fd < 0) {
196             D( "%s: could not create file: %s", __FUNCTION__, strerror(errno) );
197             return;
198         }
199         CHECKED(ret, write(fd, ks, strlen(ks)));
200         close(fd);
201     }
202 }
203 
204 
205 
206 /***********************************************************************/
207 /***********************************************************************/
208 /*****                                                             *****/
209 /*****            S D L   S U P P O R T                            *****/
210 /*****                                                             *****/
211 /***********************************************************************/
212 /***********************************************************************/
213 
214 void *readpng(const unsigned char*  base, size_t  size, unsigned *_width, unsigned *_height);
215 
216 #ifdef CONFIG_DARWIN
217 #  define  ANDROID_ICON_PNG  "android_icon_256.png"
218 #else
219 #  define  ANDROID_ICON_PNG  "android_icon_16.png"
220 #endif
221 
222 static void
sdl_set_window_icon(void)223 sdl_set_window_icon( void )
224 {
225     static int  window_icon_set;
226 
227     if (!window_icon_set)
228     {
229 #ifdef _WIN32
230         HANDLE         handle = GetModuleHandle( NULL );
231         HICON          icon   = LoadIcon( handle, MAKEINTRESOURCE(1) );
232         SDL_SysWMinfo  wminfo;
233 
234         SDL_GetWMInfo(&wminfo);
235 
236         SetClassLongPtr( wminfo.window, GCLP_HICON, (LONG)icon );
237 #else  /* !_WIN32 */
238         unsigned              icon_w, icon_h;
239         size_t                icon_bytes;
240         const unsigned char*  icon_data;
241         void*                 icon_pixels;
242 
243         window_icon_set = 1;
244 
245         icon_data = android_icon_find( ANDROID_ICON_PNG, &icon_bytes );
246         if ( !icon_data )
247             return;
248 
249         icon_pixels = readpng( icon_data, icon_bytes, &icon_w, &icon_h );
250         if ( !icon_pixels )
251             return;
252 
253        /* the data is loaded into memory as RGBA bytes by libpng. we want to manage
254         * the values as 32-bit ARGB pixels, so swap the bytes accordingly depending
255         * on our CPU endianess
256         */
257         {
258             unsigned*  d     = icon_pixels;
259             unsigned*  d_end = d + icon_w*icon_h;
260 
261             for ( ; d < d_end; d++ ) {
262                 unsigned  pix = d[0];
263 #if HOST_WORDS_BIGENDIAN
264                 /* R,G,B,A read as RGBA => ARGB */
265                 pix = ((pix >> 8) & 0xffffff) | (pix << 24);
266 #else
267                 /* R,G,B,A read as ABGR => ARGB */
268                 pix = (pix & 0xff00ff00) | ((pix >> 16) & 0xff) | ((pix & 0xff) << 16);
269 #endif
270                 d[0] = pix;
271             }
272         }
273 
274         SDL_Surface* icon = sdl_surface_from_argb32( icon_pixels, icon_w, icon_h );
275         if (icon != NULL) {
276             SDL_WM_SetIcon(icon, NULL);
277             SDL_FreeSurface(icon);
278             free( icon_pixels );
279         }
280 #endif  /* !_WIN32 */
281     }
282 }
283 
284 /***********************************************************************/
285 /***********************************************************************/
286 /*****                                                             *****/
287 /*****            S K I N   S U P P O R T                          *****/
288 /*****                                                             *****/
289 /***********************************************************************/
290 /***********************************************************************/
291 
292 const char*  skin_network_speed = NULL;
293 const char*  skin_network_delay = NULL;
294 
295 
sdl_at_exit(void)296 static void sdl_at_exit(void)
297 {
298     user_config_done();
299     qemulator_done(qemulator_get());
300     SDL_Quit();
301 }
302 
303 
sdl_display_init(DisplayState * ds,int full_screen,int no_frame)304 void sdl_display_init(DisplayState *ds, int full_screen, int  no_frame)
305 {
306     QEmulator*    emulator = qemulator_get();
307     SkinDisplay*  disp     = skin_layout_get_display(emulator->layout);
308     int           width, height;
309     char          buf[128];
310 
311     if (disp->rotation & 1) {
312         width  = disp->rect.size.h;
313         height = disp->rect.size.w;
314     } else {
315         width  = disp->rect.size.w;
316         height = disp->rect.size.h;
317     }
318 
319     snprintf(buf, sizeof buf, "width=%d,height=%d", width, height);
320 #if !defined(CONFIG_STANDALONE_UI) && !defined(CONFIG_STANDALONE_CORE)
321     android_display_init(ds, qframebuffer_fifo_get());
322 #endif
323 }
324 
325 typedef struct part_properties part_properties;
326 struct part_properties {
327     const char*      name;
328     int              width;
329     int              height;
330     part_properties* next;
331 };
332 
333 part_properties*
read_all_part_properties(AConfig * parts)334 read_all_part_properties(AConfig* parts)
335 {
336     part_properties* head = NULL;
337     part_properties* prev = NULL;
338 
339     AConfig *node = parts->first_child;
340     while (node) {
341         part_properties* t = calloc(1, sizeof(part_properties));
342         t->name = node->name;
343 
344         AConfig* bg = aconfig_find(node, "background");
345         if (bg != NULL) {
346             t->width = aconfig_int(bg, "width", 0);
347             t->height = aconfig_int(bg, "height", 0);
348         }
349 
350         if (prev == NULL) {
351             head = t;
352         } else {
353             prev->next = t;
354         }
355         prev = t;
356         node = node->next;
357     }
358 
359     return head;
360 }
361 
362 void
free_all_part_properties(part_properties * head)363 free_all_part_properties(part_properties* head)
364 {
365     part_properties* prev = head;
366     while (head) {
367         prev = head;
368         head = head->next;
369         free(prev);
370     }
371 }
372 
373 part_properties*
get_part_properties(part_properties * allparts,char * partname)374 get_part_properties(part_properties* allparts, char *partname)
375 {
376     part_properties* p;
377     for (p = allparts; p != NULL; p = p->next) {
378         if (!strcmp(partname, p->name))
379             return p;
380     }
381 
382     return NULL;
383 }
384 
385 void
add_parts_to_layout(AConfig * layout,char * parts[],int n_parts,part_properties * props,int xoffset,int x_margin,int y_margin)386 add_parts_to_layout(AConfig* layout,
387                     char* parts[],
388                     int n_parts,
389                     part_properties *props,
390                     int xoffset,
391                     int x_margin,
392                     int y_margin)
393 {
394     int     i;
395     int     y = 10;
396     char    tmp[512];
397     for (i = 0; i < n_parts; i++) {
398         part_properties *p = get_part_properties(props, parts[i]);
399         snprintf(tmp, sizeof tmp,
400             "part%d {\n \
401                 name %s\n \
402                 x %d\n \
403                 y %d\n \
404             }",
405             i + 2,  // layout already has the device part as part1, so start from part2
406             p->name,
407             xoffset + x_margin,
408             y
409             );
410         y += p->height + y_margin;
411         aconfig_load(layout, strdup(tmp));
412     }
413 }
414 
415 int
load_dynamic_skin(AndroidHwConfig * hwConfig,char ** skinDirPath,int width,int height,AConfig * root)416 load_dynamic_skin(AndroidHwConfig* hwConfig,
417                   char**           skinDirPath,
418                   int              width,
419                   int              height,
420                   AConfig*         root)
421 {
422     char      tmp[1024];
423     AConfig*  node;
424     int       i;
425     int       max_part_width;
426     char      fromEnv;
427     char*     sdkRoot = path_getSdkRoot(&fromEnv);
428 
429     if (sdkRoot == NULL) {
430         dwarning("Unable to locate sdk root. Will not use dynamic skin.");
431         return 0;
432     }
433 
434     snprintf(tmp, sizeof(tmp), "%s/tools/lib/emulator/skins/dynamic/", sdkRoot);
435     free(sdkRoot);
436 
437     if (!path_exists(tmp))
438         return 0;
439 
440     *skinDirPath = strdup(tmp);
441     snprintf(tmp, sizeof(tmp), "%s/layout", *skinDirPath);
442     D("trying to load skin file '%s'", tmp);
443 
444     if(aconfig_load_file(root, tmp) < 0) {
445         dwarning("could not load skin file '%s', won't use a skin\n", tmp);
446         return 0;
447     }
448 
449     /* Fix the width and height specified for the "device" part in the layout */
450     node = aconfig_find(root, "parts");
451     if (node != NULL) {
452         node = aconfig_find(node, "device");
453         if (node != NULL) {
454             node = aconfig_find(node, "display");
455             if (node != NULL) {
456                 snprintf(tmp, sizeof tmp, "%d", width);
457                 aconfig_set(node, "width", strdup(tmp));
458                 snprintf(tmp, sizeof tmp, "%d", height);
459                 aconfig_set(node, "height", strdup(tmp));
460             }
461         }
462     }
463 
464     /* The dynamic layout declares all the parts that are available statically
465        in the layout file. Now we need to dynamically generate the
466        appropriate layout based on the hardware config */
467 
468     part_properties* props = read_all_part_properties(aconfig_find(root, "parts"));
469 
470     const int N_PARTS = 4;
471     char* parts[N_PARTS];
472     parts[0] = "basic_controls";
473     parts[1] = hwConfig->hw_mainKeys ? "hwkeys_on" : "hwkeys_off";
474     parts[2] = hwConfig->hw_dPad ? "dpad_on" : "dpad_off";
475     parts[3] = hwConfig->hw_keyboard ? "keyboard_on" : "keyboard_off";
476 
477     for (i = 0, max_part_width = 0; i < N_PARTS; i++) {
478         part_properties *p = get_part_properties(props, parts[i]);
479         if (p != NULL && p->width > max_part_width)
480                 max_part_width = p->width;
481     }
482 
483     int x_margin = 10;
484     int y_margin = 10;
485     snprintf(tmp, sizeof tmp,
486             "layouts {\n \
487                 portrait {\n \
488                     width %d\n \
489                     height %d\n \
490                     color 0x404040\n \
491                     event EV_SW:0:1\n \
492                     part1 {\n name device\n x 0\n y 0\n}\n \
493                 }\n \
494                 landscape {\n \
495                     width %d\n \
496                     height %d\n \
497                     color 0x404040\n \
498                     event EV_SW:0:0\n \
499                     dpad-rotation 3\n \
500                     part1 {\n name device\n x 0\n y %d\n rotation 3\n }\n \
501                     }\n \
502                 }\n \
503              }\n",
504             width  + max_part_width + 2 * x_margin,
505             height,
506             height + max_part_width + 2 * x_margin,
507             width,
508             width);
509     aconfig_load(root, strdup(tmp));
510 
511     /* Add parts to portrait orientation */
512     node = aconfig_find(root, "layouts");
513     if (node != NULL) {
514         node = aconfig_find(node, "portrait");
515         if (node != NULL) {
516             add_parts_to_layout(node, parts, N_PARTS, props, width, x_margin, y_margin);
517         }
518     }
519 
520     /* Add parts to landscape orientation */
521     node = aconfig_find(root, "layouts");
522     if (node != NULL) {
523         node = aconfig_find(node, "landscape");
524         if (node != NULL) {
525             add_parts_to_layout(node, parts, N_PARTS, props, height, x_margin, y_margin);
526         }
527     }
528 
529     free_all_part_properties(props);
530 
531     return 1;
532 }
533 
534 /* list of skin aliases */
535 static const struct {
536     const char*  name;
537     const char*  alias;
538 } skin_aliases[] = {
539     { "QVGA-L", "320x240" },
540     { "QVGA-P", "240x320" },
541     { "HVGA-L", "480x320" },
542     { "HVGA-P", "320x480" },
543     { "QVGA", "320x240" },
544     { "HVGA", "320x480" },
545     { NULL, NULL }
546 };
547 
548 void
parse_skin_files(const char * skinDirPath,const char * skinName,AndroidOptions * opts,AndroidHwConfig * hwConfig,AConfig ** skinConfig,char ** skinPath)549 parse_skin_files(const char*      skinDirPath,
550                  const char*      skinName,
551                  AndroidOptions*  opts,
552                  AndroidHwConfig* hwConfig,
553                  AConfig*        *skinConfig,
554                  char*           *skinPath)
555 {
556     char      tmp[1024];
557     AConfig*  root;
558     const char* path = NULL;
559     AConfig*  n;
560 
561     root = aconfig_node("", "");
562 
563     if (skinName == NULL)
564         goto DEFAULT_SKIN;
565 
566     /* Support skin aliases like QVGA-H QVGA-P, etc...
567        But first we check if it's a directory that exist before applying
568        the alias */
569     int  checkAlias = 1;
570 
571     if (skinDirPath != NULL) {
572         bufprint(tmp, tmp+sizeof(tmp), "%s/%s", skinDirPath, skinName);
573         if (path_exists(tmp)) {
574             checkAlias = 0;
575         } else {
576             D("there is no '%s' skin in '%s'", skinName, skinDirPath);
577         }
578     }
579 
580     if (checkAlias) {
581         int  nn;
582 
583         for (nn = 0; ; nn++ ) {
584             const char*  skin_name  = skin_aliases[nn].name;
585             const char*  skin_alias = skin_aliases[nn].alias;
586 
587             if (!skin_name)
588                 break;
589 
590             if (!strcasecmp( skin_name, skinName )) {
591                 D("skin name '%s' aliased to '%s'", skinName, skin_alias);
592                 skinName = skin_alias;
593                 break;
594             }
595         }
596     }
597 
598     /* Magically support skins like "320x240" or "320x240x16" */
599     if(isdigit(skinName[0])) {
600         char *x = strchr(skinName, 'x');
601         if(x && isdigit(x[1])) {
602             int width = atoi(skinName);
603             int height = atoi(x+1);
604             int bpp   = 16;
605             char* y = strchr(x+1, 'x');
606             if (y && isdigit(y[1])) {
607                 bpp = atoi(y+1);
608             }
609 
610             if (opts->dynamic_skin) {
611                 char *dynamicSkinDirPath;
612                 if (load_dynamic_skin(hwConfig, &dynamicSkinDirPath, width, height, root)) {
613                     path = dynamicSkinDirPath;
614                     D("loaded dynamic skin width=%d height=%d bpp=%d\n", width, height, bpp);
615                     goto FOUND_SKIN;
616                 }
617             }
618 
619             snprintf(tmp, sizeof tmp,
620                     "display {\n  width %d\n  height %d\n bpp %d}\n",
621                     width, height,bpp);
622             aconfig_load(root, strdup(tmp));
623             path = ":";
624             D("found magic skin width=%d height=%d bpp=%d\n", width, height, bpp);
625             goto FOUND_SKIN;
626         }
627     }
628 
629     if (skinDirPath == NULL) {
630         derror("unknown skin name '%s'", skinName);
631         exit(1);
632     }
633 
634     snprintf(tmp, sizeof tmp, "%s/%s/layout", skinDirPath, skinName);
635     D("trying to load skin file '%s'", tmp);
636 
637     if(aconfig_load_file(root, tmp) < 0) {
638         dwarning("could not load skin file '%s', using built-in one\n",
639                  tmp);
640         goto DEFAULT_SKIN;
641     }
642 
643     snprintf(tmp, sizeof tmp, "%s/%s/", skinDirPath, skinName);
644     path = tmp;
645     goto FOUND_SKIN;
646 
647 FOUND_SKIN:
648     /* the default network speed and latency can now be specified by the device skin */
649     n = aconfig_find(root, "network");
650     if (n != NULL) {
651         skin_network_speed = aconfig_str(n, "speed", 0);
652         skin_network_delay = aconfig_str(n, "delay", 0);
653     }
654 
655     /* extract framebuffer information from the skin.
656      *
657      * for version 1 of the skin format, they are in the top-level
658      * 'display' element.
659      *
660      * for version 2 of the skin format, they are under parts.device.display
661      */
662     n = aconfig_find(root, "display");
663     if (n == NULL) {
664         n = aconfig_find(root, "parts");
665         if (n != NULL) {
666             n = aconfig_find(n, "device");
667             if (n != NULL) {
668                 n = aconfig_find(n, "display");
669             }
670         }
671     }
672 
673     if (n != NULL) {
674         int  width  = aconfig_int(n, "width", hwConfig->hw_lcd_width);
675         int  height = aconfig_int(n, "height", hwConfig->hw_lcd_height);
676         int  depth  = aconfig_int(n, "bpp", hwConfig->hw_lcd_depth);
677 
678         if (width > 0 && height > 0) {
679             /* The emulated framebuffer wants sizes that are multiples of 4 */
680             if (((width|height) & 3) != 0) {
681                 width  = (width+3) & ~3;
682                 height = (height+3) & ~3;
683                 D("adjusting LCD dimensions to (%dx%dx)", width, height);
684             }
685 
686             /* only depth values of 16 and 32 are correct. 16 is the default. */
687             if (depth != 32 && depth != 16) {
688                 depth = 16;
689                 D("adjusting LCD bit depth to %d", depth);
690             }
691 
692             hwConfig->hw_lcd_width  = width;
693             hwConfig->hw_lcd_height = height;
694             hwConfig->hw_lcd_depth  = depth;
695         }
696         else {
697             D("ignoring invalid skin LCD dimensions (%dx%dx%d)",
698               width, height, depth);
699         }
700     }
701 
702     *skinConfig = root;
703     *skinPath   = strdup(path);
704     return;
705 
706 DEFAULT_SKIN:
707     {
708         const unsigned char*  layout_base;
709         size_t                layout_size;
710         char*                 base;
711 
712         skinName = "<builtin>";
713 
714         layout_base = android_resource_find( "layout", &layout_size );
715         if (layout_base == NULL) {
716             fprintf(stderr, "Couldn't load builtin skin\n");
717             exit(1);
718         }
719         base = malloc( layout_size+1 );
720         memcpy( base, layout_base, layout_size );
721         base[layout_size] = 0;
722 
723         D("parsing built-in skin layout file (%d bytes)", (int)layout_size);
724         aconfig_load(root, base);
725         path = ":";
726     }
727     goto FOUND_SKIN;
728 }
729 
730 
731 void
init_sdl_ui(AConfig * skinConfig,const char * skinPath,AndroidOptions * opts)732 init_sdl_ui(AConfig*         skinConfig,
733             const char*      skinPath,
734             AndroidOptions*  opts)
735 {
736     int  win_x, win_y, flags;
737 
738     signal(SIGINT, SIG_DFL);
739 #ifndef _WIN32
740     signal(SIGQUIT, SIG_DFL);
741 #endif
742 
743     /* we're not a game, so allow the screensaver to run */
744     setenv("SDL_VIDEO_ALLOW_SCREENSAVER","1",1);
745 
746     flags = SDL_INIT_NOPARACHUTE;
747     if (!opts->no_window)
748         flags |= SDL_INIT_VIDEO;
749 
750     if(SDL_Init(flags)){
751         fprintf(stderr, "SDL init failure, reason is: %s\n", SDL_GetError() );
752         exit(1);
753     }
754 
755     if (!opts->no_window) {
756         SDL_EnableUNICODE(!opts->raw_keys);
757         SDL_EnableKeyRepeat(0,0);
758 
759         sdl_set_window_icon();
760     }
761     else
762     {
763 #ifndef _WIN32
764        /* prevent SIGTTIN and SIGTTOUT from stopping us. this is necessary to be
765         * able to run the emulator in the background (e.g. "emulator &").
766         * despite the fact that the emulator should not grab input or try to
767         * write to the output in normal cases, we're stopped on some systems
768         * (e.g. OS X)
769         */
770         signal(SIGTTIN, SIG_IGN);
771         signal(SIGTTOU, SIG_IGN);
772 #endif
773     }
774     atexit(sdl_at_exit);
775 
776     user_config_get_window_pos(&win_x, &win_y);
777 
778     if ( qemulator_init(qemulator_get(), skinConfig, skinPath, win_x, win_y, opts) < 0 ) {
779         fprintf(stderr, "### Error: could not load emulator skin from '%s'\n", skinPath);
780         exit(1);
781     }
782 
783     /* add an onion overlay image if needed */
784     if (opts->onion) {
785         SkinImage*  onion = skin_image_find_simple( opts->onion );
786         int         alpha, rotate;
787 
788         if ( opts->onion_alpha && 1 == sscanf( opts->onion_alpha, "%d", &alpha ) ) {
789             alpha = (256*alpha)/100;
790         } else
791             alpha = 128;
792 
793         if ( opts->onion_rotation && 1 == sscanf( opts->onion_rotation, "%d", &rotate ) ) {
794             rotate &= 3;
795         } else
796             rotate = SKIN_ROTATION_0;
797 
798         qemulator_get()->onion          = onion;
799         qemulator_get()->onion_alpha    = alpha;
800         qemulator_get()->onion_rotation = rotate;
801     }
802 }
803 
804 /* this function is used to perform auto-detection of the
805  * system directory in the case of a SDK installation.
806  *
807  * we want to deal with several historical usages, hence
808  * the slightly complicated logic.
809  *
810  * NOTE: the function returns the path to the directory
811  *       containing 'fileName'. this is *not* the full
812  *       path to 'fileName'.
813  */
814 static char*
_getSdkImagePath(const char * fileName)815 _getSdkImagePath( const char*  fileName )
816 {
817     char   temp[MAX_PATH];
818     char*  p   = temp;
819     char*  end = p + sizeof(temp);
820     char*  q;
821     char*  app;
822 
823     static const char* const  searchPaths[] = {
824         "",                                  /* program's directory */
825         "/lib/images",                       /* this is for SDK 1.0 */
826         "/../platforms/android-1.1/images",  /* this is for SDK 1.1 */
827         NULL
828     };
829 
830     app = bufprint_app_dir(temp, end);
831     if (app >= end)
832         return NULL;
833 
834     do {
835         int  nn;
836 
837         /* first search a few well-known paths */
838         for (nn = 0; searchPaths[nn] != NULL; nn++) {
839             p = bufprint(app, end, "%s", searchPaths[nn]);
840             q = bufprint(p, end, "/%s", fileName);
841             if (q < end && path_exists(temp)) {
842                 *p = 0;
843                 goto FOUND_IT;
844             }
845         }
846 
847         /* hmmm. let's assume that we are in a post-1.1 SDK
848          * scan ../platforms if it exists
849          */
850         p = bufprint(app, end, "/../platforms");
851         if (p < end) {
852             DirScanner*  scanner = dirScanner_new(temp);
853             if (scanner != NULL) {
854                 int          found = 0;
855                 const char*  subdir;
856 
857                 for (;;) {
858                     subdir = dirScanner_next(scanner);
859                     if (!subdir) break;
860 
861                     q = bufprint(p, end, "/%s/images/%s", subdir, fileName);
862                     if (q >= end || !path_exists(temp))
863                         continue;
864 
865                     found = 1;
866                     p = bufprint(p, end, "/%s/images", subdir);
867                     break;
868                 }
869                 dirScanner_free(scanner);
870                 if (found)
871                     break;
872             }
873         }
874 
875         /* I'm out of ideas */
876         return NULL;
877 
878     } while (0);
879 
880 FOUND_IT:
881     //D("image auto-detection: %s/%s", temp, fileName);
882     return android_strdup(temp);
883 }
884 
885 static char*
_getSdkImage(const char * path,const char * file)886 _getSdkImage( const char*  path, const char*  file )
887 {
888     char  temp[MAX_PATH];
889     char  *p = temp, *end = p + sizeof(temp);
890 
891     p = bufprint(temp, end, "%s/%s", path, file);
892     if (p >= end || !path_exists(temp))
893         return NULL;
894 
895     return android_strdup(temp);
896 }
897 
898 static char*
_getSdkSystemImage(const char * path,const char * optionName,const char * file)899 _getSdkSystemImage( const char*  path, const char*  optionName, const char*  file )
900 {
901     char*  image = _getSdkImage(path, file);
902 
903     if (image == NULL) {
904         derror("Your system directory is missing the '%s' image file.\n"
905                "Please specify one with the '%s <filepath>' option",
906                file, optionName);
907         exit(2);
908     }
909     return image;
910 }
911 
sanitizeOptions(AndroidOptions * opts)912 void sanitizeOptions( AndroidOptions* opts )
913 {
914     /* legacy support: we used to use -system <dir> and -image <file>
915      * instead of -sysdir <dir> and -system <file>, so handle this by checking
916      * whether the options point to directories or files.
917      */
918     if (opts->image != NULL) {
919         if (opts->system != NULL) {
920             if (opts->sysdir != NULL) {
921                 derror( "You can't use -sysdir, -system and -image at the same time.\n"
922                         "You should probably use '-sysdir <path> -system <file>'.\n" );
923                 exit(2);
924             }
925         }
926         dwarning( "Please note that -image is obsolete and that -system is now used to point\n"
927                   "to the system image. Next time, try using '-sysdir <path> -system <file>' instead.\n" );
928         opts->sysdir = opts->system;
929         opts->system = opts->image;
930         opts->image  = NULL;
931     }
932     else if (opts->system != NULL && path_is_dir(opts->system)) {
933         if (opts->sysdir != NULL) {
934             derror( "Option -system should now be followed by a file path, not a directory one.\n"
935                     "Please use '-sysdir <path>' to point to the system directory.\n" );
936             exit(1);
937         }
938         dwarning( "Please note that the -system option should now be used to point to the initial\n"
939                   "system image (like the obsolete -image option). To point to the system directory\n"
940                   "please now use '-sysdir <path>' instead.\n" );
941 
942         opts->sysdir = opts->system;
943         opts->system = NULL;
944     }
945 
946     if (opts->nojni) {
947         opts->no_jni = opts->nojni;
948         opts->nojni  = 0;
949     }
950 
951     if (opts->nocache) {
952         opts->no_cache = opts->nocache;
953         opts->nocache  = 0;
954     }
955 
956     if (opts->noaudio) {
957         opts->no_audio = opts->noaudio;
958         opts->noaudio  = 0;
959     }
960 
961     if (opts->noskin) {
962         opts->no_skin = opts->noskin;
963         opts->noskin  = 0;
964     }
965 
966     /* If -no-cache is used, ignore any -cache argument */
967     if (opts->no_cache) {
968         opts->cache = 0;
969     }
970 
971     /* the purpose of -no-audio is to disable sound output from the emulator,
972      * not to disable Audio emulation. So simply force the 'none' backends */
973     if (opts->no_audio)
974         opts->audio = "none";
975 
976     /* we don't accept -skindir without -skin now
977      * to simplify the autoconfig stuff with virtual devices
978      */
979     if (opts->no_skin) {
980         opts->skin    = "320x480";
981         opts->skindir = NULL;
982     }
983 
984     if (opts->skindir) {
985         if (!opts->skin) {
986             derror( "the -skindir <path> option requires a -skin <name> option");
987             exit(1);
988         }
989     }
990 
991     if (opts->bootchart) {
992         char*  end;
993         int    timeout = strtol(opts->bootchart, &end, 10);
994         if (timeout == 0)
995             opts->bootchart = NULL;
996         else if (timeout < 0 || timeout > 15*60) {
997             derror( "timeout specified for -bootchart option is invalid.\n"
998                     "please use integers between 1 and 900\n");
999             exit(1);
1000         }
1001     }
1002 }
1003 
createAVD(AndroidOptions * opts,int * inAndroidBuild)1004 AvdInfo* createAVD(AndroidOptions* opts, int* inAndroidBuild)
1005 {
1006     AvdInfo* ret = NULL;
1007     char   tmp[MAX_PATH];
1008     char*  tmpend = tmp + sizeof(tmp);
1009     char*  android_build_root = NULL;
1010     char*  android_build_out  = NULL;
1011 
1012     /* If no AVD name was given, try to find the top of the
1013      * Android build tree
1014      */
1015     if (opts->avd == NULL) {
1016         do {
1017             char*  out = getenv("ANDROID_PRODUCT_OUT");
1018 
1019             if (out == NULL || out[0] == 0)
1020                 break;
1021 
1022             if (!path_exists(out)) {
1023                 derror("Can't access ANDROID_PRODUCT_OUT as '%s'\n"
1024                     "You need to build the Android system before launching the emulator",
1025                     out);
1026                 exit(2);
1027             }
1028 
1029             android_build_root = getenv("ANDROID_BUILD_TOP");
1030             if (android_build_root == NULL || android_build_root[0] == 0)
1031                 break;
1032 
1033             if (!path_exists(android_build_root)) {
1034                 derror("Can't find the Android build root '%s'\n"
1035                     "Please check the definition of the ANDROID_BUILD_TOP variable.\n"
1036                     "It should point to the root of your source tree.\n",
1037                     android_build_root );
1038                 exit(2);
1039             }
1040             android_build_out = out;
1041             D( "found Android build root: %s", android_build_root );
1042             D( "found Android build out:  %s", android_build_out );
1043         } while (0);
1044     }
1045     /* if no virtual device name is given, and we're not in the
1046      * Android build system, we'll need to perform some auto-detection
1047      * magic :-)
1048      */
1049     if (opts->avd == NULL && !android_build_out)
1050     {
1051         char   dataDirIsSystem = 0;
1052 
1053         if (!opts->sysdir) {
1054             opts->sysdir = _getSdkImagePath("system.img");
1055             if (!opts->sysdir) {
1056                 derror(
1057                 "You did not specify a virtual device name, and the system\n"
1058                 "directory could not be found.\n\n"
1059                 "If you are an Android SDK user, please use '@<name>' or '-avd <name>'\n"
1060                 "to start a given virtual device (see -help-avd for details).\n\n"
1061 
1062                 "Otherwise, follow the instructions in -help-disk-images to start the emulator\n"
1063                 );
1064                 exit(2);
1065             }
1066             D("autoconfig: -sysdir %s", opts->sysdir);
1067         }
1068 
1069         if (!opts->system) {
1070             opts->system = _getSdkSystemImage(opts->sysdir, "-image", "system.img");
1071             D("autoconfig: -system %s", opts->system);
1072         }
1073 
1074         if (!opts->kernel) {
1075             opts->kernel = _getSdkSystemImage(opts->sysdir, "-kernel", "kernel-qemu");
1076             D("autoconfig: -kernel %s", opts->kernel);
1077         }
1078 
1079         if (!opts->ramdisk) {
1080             opts->ramdisk = _getSdkSystemImage(opts->sysdir, "-ramdisk", "ramdisk.img");
1081             D("autoconfig: -ramdisk %s", opts->ramdisk);
1082         }
1083 
1084         /* if no data directory is specified, use the system directory */
1085         if (!opts->datadir) {
1086             opts->datadir   = android_strdup(opts->sysdir);
1087             dataDirIsSystem = 1;
1088             D("autoconfig: -datadir %s", opts->sysdir);
1089         }
1090 
1091         if (!opts->data) {
1092             /* check for userdata-qemu.img in the data directory */
1093             bufprint(tmp, tmpend, "%s/userdata-qemu.img", opts->datadir);
1094             if (!path_exists(tmp)) {
1095                 derror(
1096                 "You did not provide the name of an Android Virtual Device\n"
1097                 "with the '-avd <name>' option. Read -help-avd for more information.\n\n"
1098 
1099                 "If you *really* want to *NOT* run an AVD, consider using '-data <file>'\n"
1100                 "to specify a data partition image file (I hope you know what you're doing).\n"
1101                 );
1102                 exit(2);
1103             }
1104 
1105             opts->data = android_strdup(tmp);
1106             D("autoconfig: -data %s", opts->data);
1107         }
1108 
1109         if (!opts->snapstorage && opts->datadir) {
1110             bufprint(tmp, tmpend, "%s/snapshots.img", opts->datadir);
1111             if (path_exists(tmp)) {
1112                 opts->snapstorage = android_strdup(tmp);
1113                 D("autoconfig: -snapstorage %s", opts->snapstorage);
1114             }
1115         }
1116     }
1117 
1118     /* setup the virtual device differently depending on whether
1119      * we are in the Android build system or not
1120      */
1121     if (opts->avd != NULL)
1122     {
1123         ret = avdInfo_new( opts->avd, android_avdParams );
1124         if (ret == NULL) {
1125             /* an error message has already been printed */
1126             dprint("could not find virtual device named '%s'", opts->avd);
1127             exit(1);
1128         }
1129     }
1130     else
1131     {
1132         if (!android_build_out) {
1133             android_build_out = android_build_root = opts->sysdir;
1134         }
1135         ret = avdInfo_newForAndroidBuild(
1136                             android_build_root,
1137                             android_build_out,
1138                             android_avdParams );
1139 
1140         if(ret == NULL) {
1141             D("could not start virtual device\n");
1142             exit(1);
1143         }
1144     }
1145 
1146     if (android_build_out) {
1147         *inAndroidBuild = 1;
1148     } else {
1149         *inAndroidBuild = 0;
1150     }
1151 
1152     return ret;
1153 }
1154 
1155 
1156 
1157 
1158 #ifdef CONFIG_STANDALONE_UI
1159 
1160 #include "android/protocol/core-connection.h"
1161 #include "android/protocol/fb-updates-impl.h"
1162 #include "android/protocol/user-events-proxy.h"
1163 #include "android/protocol/core-commands-proxy.h"
1164 #include "android/protocol/ui-commands-impl.h"
1165 #include "android/protocol/attach-ui-impl.h"
1166 
1167 /* Emulator's core port. */
1168 int android_base_port = 0;
1169 
1170 // Base console port
1171 #define CORE_BASE_PORT          5554
1172 
1173 // Maximum number of core porocesses running simultaneously on a machine.
1174 #define MAX_CORE_PROCS          16
1175 
1176 // Socket timeout in millisec (set to 5 seconds)
1177 #define CORE_PORT_TIMEOUT_MS    5000
1178 
1179 #include "android/async-console.h"
1180 
1181 typedef struct {
1182     LoopIo                 io[1];
1183     int                    port;
1184     int                    ok;
1185     AsyncConsoleConnector  connector[1];
1186 } CoreConsole;
1187 
1188 static void
coreconsole_io_func(void * opaque,int fd,unsigned events)1189 coreconsole_io_func(void* opaque, int fd, unsigned events)
1190 {
1191     CoreConsole* cc = opaque;
1192     AsyncStatus  status;
1193     status = asyncConsoleConnector_run(cc->connector);
1194     if (status == ASYNC_COMPLETE) {
1195         cc->ok = 1;
1196     }
1197 }
1198 
1199 static void
coreconsole_init(CoreConsole * cc,const SockAddress * address,Looper * looper)1200 coreconsole_init(CoreConsole* cc, const SockAddress* address, Looper* looper)
1201 {
1202     int fd = socket_create_inet(SOCKET_STREAM);
1203     AsyncStatus status;
1204     cc->port = sock_address_get_port(address);
1205     cc->ok   = 0;
1206     loopIo_init(cc->io, looper, fd, coreconsole_io_func, cc);
1207     if (fd >= 0) {
1208         status = asyncConsoleConnector_connect(cc->connector, address, cc->io);
1209         if (status == ASYNC_ERROR) {
1210             cc->ok = 0;
1211         }
1212     }
1213 }
1214 
1215 static void
coreconsole_done(CoreConsole * cc)1216 coreconsole_done(CoreConsole* cc)
1217 {
1218     socket_close(cc->io->fd);
1219     loopIo_done(cc->io);
1220 }
1221 
1222 /* List emulator core processes running on the given machine.
1223  * This routine is called from main() if -list-cores parameter is set in the
1224  * command line.
1225  * Param:
1226  *  host Value passed with -list-core parameter. Must be either "localhost", or
1227  *  an IP address of a machine where core processes must be enumerated.
1228  */
1229 static void
list_running_cores(const char * host)1230 list_running_cores(const char* host)
1231 {
1232     Looper*         looper;
1233     CoreConsole     cores[MAX_CORE_PROCS];
1234     SockAddress     address;
1235     int             nn, found;
1236 
1237     if (sock_address_init_resolve(&address, host, CORE_BASE_PORT, 0) < 0) {
1238         derror("Unable to resolve hostname %s: %s", host, errno_str);
1239         return;
1240     }
1241 
1242     looper = looper_newGeneric();
1243 
1244     for (nn = 0; nn < MAX_CORE_PROCS; nn++) {
1245         int port = CORE_BASE_PORT + nn*2;
1246         sock_address_set_port(&address, port);
1247         coreconsole_init(&cores[nn], &address, looper);
1248     }
1249 
1250     looper_runWithTimeout(looper, CORE_PORT_TIMEOUT_MS*2);
1251 
1252     found = 0;
1253     for (nn = 0; nn < MAX_CORE_PROCS; nn++) {
1254         int port = CORE_BASE_PORT + nn*2;
1255         if (cores[nn].ok) {
1256             if (found == 0) {
1257                 fprintf(stdout, "Running emulator core processes:\n");
1258             }
1259             fprintf(stdout, "Emulator console port %d\n", port);
1260             found++;
1261         }
1262         coreconsole_done(&cores[nn]);
1263     }
1264     looper_free(looper);
1265 
1266     if (found == 0) {
1267        fprintf(stdout, "There were no running emulator core processes found on %s.\n",
1268                host);
1269     }
1270 }
1271 
1272 /* Attaches starting UI to a running core process.
1273  * This routine is called from main() when -attach-core parameter is set,
1274  * indicating that this UI instance should attach to a running core, rather than
1275  * start a new core process.
1276  * Param:
1277  *  opts Android options containing non-NULL attach_core.
1278  * Return:
1279  *  0 on success, or -1 on failure.
1280  */
1281 static int
attach_to_core(AndroidOptions * opts)1282 attach_to_core(AndroidOptions* opts) {
1283     int iter;
1284     SockAddress console_socket;
1285     SockAddress** sockaddr_list;
1286     QEmulator* emulator;
1287 
1288     // Parse attach_core param extracting the host name, and the port name.
1289     char* console_address = strdup(opts->attach_core);
1290     char* host_name = console_address;
1291     char* port_num = strchr(console_address, ':');
1292     if (port_num == NULL) {
1293         // The host name is ommited, indicating the localhost
1294         host_name = "localhost";
1295         port_num = console_address;
1296     } else if (port_num == console_address) {
1297         // Invalid.
1298         derror("Invalid value %s for -attach-core parameter\n",
1299                opts->attach_core);
1300         return -1;
1301     } else {
1302         *port_num = '\0';
1303         port_num++;
1304         if (*port_num == '\0') {
1305             // Invalid.
1306             derror("Invalid value %s for -attach-core parameter\n",
1307                    opts->attach_core);
1308             return -1;
1309         }
1310     }
1311 
1312     /* Create socket address list for the given address, and pull appropriate
1313      * address to use for connection. Note that we're fine copying that address
1314      * out of the list, since INET and IN6 will entirely fit into SockAddress
1315      * structure. */
1316     sockaddr_list =
1317         sock_address_list_create(host_name, port_num, SOCKET_LIST_FORCE_INET);
1318     free(console_address);
1319     if (sockaddr_list == NULL) {
1320         derror("Unable to resolve address %s: %s\n",
1321                opts->attach_core, errno_str);
1322         return -1;
1323     }
1324     for (iter = 0; sockaddr_list[iter] != NULL; iter++) {
1325         if (sock_address_get_family(sockaddr_list[iter]) == SOCKET_INET ||
1326             sock_address_get_family(sockaddr_list[iter]) == SOCKET_IN6) {
1327             memcpy(&console_socket, sockaddr_list[iter], sizeof(SockAddress));
1328             break;
1329         }
1330     }
1331     if (sockaddr_list[iter] == NULL) {
1332         derror("Unable to resolve address %s. Note that 'port' parameter passed to -attach-core\n"
1333                "must be resolvable into an IP address.\n", opts->attach_core);
1334         sock_address_list_free(sockaddr_list);
1335         return -1;
1336     }
1337     sock_address_list_free(sockaddr_list);
1338 
1339     if (attachUiImpl_create(&console_socket)) {
1340         return -1;
1341     }
1342 
1343     // Save core's port, and set the title.
1344     android_base_port = sock_address_get_port(&console_socket);
1345     emulator = qemulator_get();
1346     qemulator_set_title(emulator);
1347 
1348     return 0;
1349 }
1350 
1351 
handle_ui_options(AndroidOptions * opts)1352 void handle_ui_options( AndroidOptions* opts )
1353 {
1354     // Lets see if user just wants to list core process.
1355     if (opts->list_cores) {
1356         fprintf(stdout, "Enumerating running core processes.\n");
1357         list_running_cores(opts->list_cores);
1358         exit(0);
1359     }
1360 }
1361 
attach_ui_to_core(AndroidOptions * opts)1362 int attach_ui_to_core( AndroidOptions* opts )
1363 {
1364     // Lets see if we're attaching to a running core process here.
1365     if (opts->attach_core) {
1366         if (attach_to_core(opts)) {
1367             return -1;
1368         }
1369         // Connect to the core's UI control services.
1370         if (coreCmdProxy_create(attachUiImpl_get_console_socket())) {
1371             return -1;
1372         }
1373         // Connect to the core's user events service.
1374         if (userEventsProxy_create(attachUiImpl_get_console_socket())) {
1375             return -1;
1376         }
1377     }
1378     return 0;
1379 }
1380 
1381 #else  /* !CONFIG_STANDALONE_UI */
1382 
handle_ui_options(AndroidOptions * opts)1383 void handle_ui_options( AndroidOptions* opts )
1384 {
1385     return;
1386 }
1387 
attach_ui_to_core(AndroidOptions * opts)1388 int attach_ui_to_core( AndroidOptions* opts )
1389 {
1390     return 0;
1391 }
1392 
1393 #endif /* CONFIG_STANDALONE_UI */
1394