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