• 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         SetClassLongPtr( wminfo.window, GCLP_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 = getenv("ANDROID_BUILD_TOP");
810             if (android_build_root == NULL || android_build_root[0] == 0)
811                 break;
812 
813             if (!path_exists(android_build_root)) {
814                 derror("Can't find the Android build root '%s'\n"
815                     "Please check the definition of the ANDROID_BUILD_TOP variable.\n"
816                     "It should point to the root of your source tree.\n",
817                     android_build_root );
818                 exit(2);
819             }
820             android_build_out = out;
821             D( "found Android build root: %s", android_build_root );
822             D( "found Android build out:  %s", android_build_out );
823         } while (0);
824     }
825     /* if no virtual device name is given, and we're not in the
826      * Android build system, we'll need to perform some auto-detection
827      * magic :-)
828      */
829     if (opts->avd == NULL && !android_build_out)
830     {
831         char   dataDirIsSystem = 0;
832 
833         if (!opts->sysdir) {
834             opts->sysdir = _getSdkImagePath("system.img");
835             if (!opts->sysdir) {
836                 derror(
837                 "You did not specify a virtual device name, and the system\n"
838                 "directory could not be found.\n\n"
839                 "If you are an Android SDK user, please use '@<name>' or '-avd <name>'\n"
840                 "to start a given virtual device (see -help-avd for details).\n\n"
841 
842                 "Otherwise, follow the instructions in -help-disk-images to start the emulator\n"
843                 );
844                 exit(2);
845             }
846             D("autoconfig: -sysdir %s", opts->sysdir);
847         }
848 
849         if (!opts->system) {
850             opts->system = _getSdkSystemImage(opts->sysdir, "-image", "system.img");
851             D("autoconfig: -system %s", opts->system);
852         }
853 
854         if (!opts->kernel) {
855             opts->kernel = _getSdkSystemImage(opts->sysdir, "-kernel", "kernel-qemu");
856             D("autoconfig: -kernel %s", opts->kernel);
857         }
858 
859         if (!opts->ramdisk) {
860             opts->ramdisk = _getSdkSystemImage(opts->sysdir, "-ramdisk", "ramdisk.img");
861             D("autoconfig: -ramdisk %s", opts->ramdisk);
862         }
863 
864         /* if no data directory is specified, use the system directory */
865         if (!opts->datadir) {
866             opts->datadir   = android_strdup(opts->sysdir);
867             dataDirIsSystem = 1;
868             D("autoconfig: -datadir %s", opts->sysdir);
869         }
870 
871         if (!opts->data) {
872             /* check for userdata-qemu.img in the data directory */
873             bufprint(tmp, tmpend, "%s/userdata-qemu.img", opts->datadir);
874             if (!path_exists(tmp)) {
875                 derror(
876                 "You did not provide the name of an Android Virtual Device\n"
877                 "with the '-avd <name>' option. Read -help-avd for more information.\n\n"
878 
879                 "If you *really* want to *NOT* run an AVD, consider using '-data <file>'\n"
880                 "to specify a data partition image file (I hope you know what you're doing).\n"
881                 );
882                 exit(2);
883             }
884 
885             opts->data = android_strdup(tmp);
886             D("autoconfig: -data %s", opts->data);
887         }
888 
889         if (!opts->snapstorage && opts->datadir) {
890             bufprint(tmp, tmpend, "%s/snapshots.img", opts->datadir);
891             if (path_exists(tmp)) {
892                 opts->snapstorage = android_strdup(tmp);
893                 D("autoconfig: -snapstorage %s", opts->snapstorage);
894             }
895         }
896     }
897 
898     /* setup the virtual device differently depending on whether
899      * we are in the Android build system or not
900      */
901     if (opts->avd != NULL)
902     {
903         ret = avdInfo_new( opts->avd, android_avdParams );
904         if (ret == NULL) {
905             /* an error message has already been printed */
906             dprint("could not find virtual device named '%s'", opts->avd);
907             exit(1);
908         }
909     }
910     else
911     {
912         if (!android_build_out) {
913             android_build_out = android_build_root = opts->sysdir;
914         }
915         ret = avdInfo_newForAndroidBuild(
916                             android_build_root,
917                             android_build_out,
918                             android_avdParams );
919 
920         if(ret == NULL) {
921             D("could not start virtual device\n");
922             exit(1);
923         }
924     }
925 
926     if (android_build_out) {
927         *inAndroidBuild = 1;
928     } else {
929         *inAndroidBuild = 0;
930     }
931 
932     return ret;
933 }
934 
935 
936 
937 
938 #ifdef CONFIG_STANDALONE_UI
939 
940 #include "android/protocol/core-connection.h"
941 #include "android/protocol/fb-updates-impl.h"
942 #include "android/protocol/user-events-proxy.h"
943 #include "android/protocol/core-commands-proxy.h"
944 #include "android/protocol/ui-commands-impl.h"
945 #include "android/protocol/attach-ui-impl.h"
946 
947 /* Emulator's core port. */
948 int android_base_port = 0;
949 
950 // Base console port
951 #define CORE_BASE_PORT          5554
952 
953 // Maximum number of core porocesses running simultaneously on a machine.
954 #define MAX_CORE_PROCS          16
955 
956 // Socket timeout in millisec (set to 5 seconds)
957 #define CORE_PORT_TIMEOUT_MS    5000
958 
959 #include "android/async-console.h"
960 
961 typedef struct {
962     LoopIo                 io[1];
963     int                    port;
964     int                    ok;
965     AsyncConsoleConnector  connector[1];
966 } CoreConsole;
967 
968 static void
coreconsole_io_func(void * opaque,int fd,unsigned events)969 coreconsole_io_func(void* opaque, int fd, unsigned events)
970 {
971     CoreConsole* cc = opaque;
972     AsyncStatus  status;
973     status = asyncConsoleConnector_run(cc->connector);
974     if (status == ASYNC_COMPLETE) {
975         cc->ok = 1;
976     }
977 }
978 
979 static void
coreconsole_init(CoreConsole * cc,const SockAddress * address,Looper * looper)980 coreconsole_init(CoreConsole* cc, const SockAddress* address, Looper* looper)
981 {
982     int fd = socket_create_inet(SOCKET_STREAM);
983     AsyncStatus status;
984     cc->port = sock_address_get_port(address);
985     cc->ok   = 0;
986     loopIo_init(cc->io, looper, fd, coreconsole_io_func, cc);
987     if (fd >= 0) {
988         status = asyncConsoleConnector_connect(cc->connector, address, cc->io);
989         if (status == ASYNC_ERROR) {
990             cc->ok = 0;
991         }
992     }
993 }
994 
995 static void
coreconsole_done(CoreConsole * cc)996 coreconsole_done(CoreConsole* cc)
997 {
998     socket_close(cc->io->fd);
999     loopIo_done(cc->io);
1000 }
1001 
1002 /* List emulator core processes running on the given machine.
1003  * This routine is called from main() if -list-cores parameter is set in the
1004  * command line.
1005  * Param:
1006  *  host Value passed with -list-core parameter. Must be either "localhost", or
1007  *  an IP address of a machine where core processes must be enumerated.
1008  */
1009 static void
list_running_cores(const char * host)1010 list_running_cores(const char* host)
1011 {
1012     Looper*         looper;
1013     CoreConsole     cores[MAX_CORE_PROCS];
1014     SockAddress     address;
1015     int             nn, found;
1016 
1017     if (sock_address_init_resolve(&address, host, CORE_BASE_PORT, 0) < 0) {
1018         derror("Unable to resolve hostname %s: %s", host, errno_str);
1019         return;
1020     }
1021 
1022     looper = looper_newGeneric();
1023 
1024     for (nn = 0; nn < MAX_CORE_PROCS; nn++) {
1025         int port = CORE_BASE_PORT + nn*2;
1026         sock_address_set_port(&address, port);
1027         coreconsole_init(&cores[nn], &address, looper);
1028     }
1029 
1030     looper_runWithTimeout(looper, CORE_PORT_TIMEOUT_MS*2);
1031 
1032     found = 0;
1033     for (nn = 0; nn < MAX_CORE_PROCS; nn++) {
1034         int port = CORE_BASE_PORT + nn*2;
1035         if (cores[nn].ok) {
1036             if (found == 0) {
1037                 fprintf(stdout, "Running emulator core processes:\n");
1038             }
1039             fprintf(stdout, "Emulator console port %d\n", port);
1040             found++;
1041         }
1042         coreconsole_done(&cores[nn]);
1043     }
1044     looper_free(looper);
1045 
1046     if (found == 0) {
1047        fprintf(stdout, "There were no running emulator core processes found on %s.\n",
1048                host);
1049     }
1050 }
1051 
1052 /* Attaches starting UI to a running core process.
1053  * This routine is called from main() when -attach-core parameter is set,
1054  * indicating that this UI instance should attach to a running core, rather than
1055  * start a new core process.
1056  * Param:
1057  *  opts Android options containing non-NULL attach_core.
1058  * Return:
1059  *  0 on success, or -1 on failure.
1060  */
1061 static int
attach_to_core(AndroidOptions * opts)1062 attach_to_core(AndroidOptions* opts) {
1063     int iter;
1064     SockAddress console_socket;
1065     SockAddress** sockaddr_list;
1066     QEmulator* emulator;
1067 
1068     // Parse attach_core param extracting the host name, and the port name.
1069     char* console_address = strdup(opts->attach_core);
1070     char* host_name = console_address;
1071     char* port_num = strchr(console_address, ':');
1072     if (port_num == NULL) {
1073         // The host name is ommited, indicating the localhost
1074         host_name = "localhost";
1075         port_num = console_address;
1076     } else if (port_num == console_address) {
1077         // Invalid.
1078         derror("Invalid value %s for -attach-core parameter\n",
1079                opts->attach_core);
1080         return -1;
1081     } else {
1082         *port_num = '\0';
1083         port_num++;
1084         if (*port_num == '\0') {
1085             // Invalid.
1086             derror("Invalid value %s for -attach-core parameter\n",
1087                    opts->attach_core);
1088             return -1;
1089         }
1090     }
1091 
1092     /* Create socket address list for the given address, and pull appropriate
1093      * address to use for connection. Note that we're fine copying that address
1094      * out of the list, since INET and IN6 will entirely fit into SockAddress
1095      * structure. */
1096     sockaddr_list =
1097         sock_address_list_create(host_name, port_num, SOCKET_LIST_FORCE_INET);
1098     free(console_address);
1099     if (sockaddr_list == NULL) {
1100         derror("Unable to resolve address %s: %s\n",
1101                opts->attach_core, errno_str);
1102         return -1;
1103     }
1104     for (iter = 0; sockaddr_list[iter] != NULL; iter++) {
1105         if (sock_address_get_family(sockaddr_list[iter]) == SOCKET_INET ||
1106             sock_address_get_family(sockaddr_list[iter]) == SOCKET_IN6) {
1107             memcpy(&console_socket, sockaddr_list[iter], sizeof(SockAddress));
1108             break;
1109         }
1110     }
1111     if (sockaddr_list[iter] == NULL) {
1112         derror("Unable to resolve address %s. Note that 'port' parameter passed to -attach-core\n"
1113                "must be resolvable into an IP address.\n", opts->attach_core);
1114         sock_address_list_free(sockaddr_list);
1115         return -1;
1116     }
1117     sock_address_list_free(sockaddr_list);
1118 
1119     if (attachUiImpl_create(&console_socket)) {
1120         return -1;
1121     }
1122 
1123     // Save core's port, and set the title.
1124     android_base_port = sock_address_get_port(&console_socket);
1125     emulator = qemulator_get();
1126     qemulator_set_title(emulator);
1127 
1128     return 0;
1129 }
1130 
1131 
handle_ui_options(AndroidOptions * opts)1132 void handle_ui_options( AndroidOptions* opts )
1133 {
1134     // Lets see if user just wants to list core process.
1135     if (opts->list_cores) {
1136         fprintf(stdout, "Enumerating running core processes.\n");
1137         list_running_cores(opts->list_cores);
1138         exit(0);
1139     }
1140 }
1141 
attach_ui_to_core(AndroidOptions * opts)1142 int attach_ui_to_core( AndroidOptions* opts )
1143 {
1144     // Lets see if we're attaching to a running core process here.
1145     if (opts->attach_core) {
1146         if (attach_to_core(opts)) {
1147             return -1;
1148         }
1149         // Connect to the core's UI control services.
1150         if (coreCmdProxy_create(attachUiImpl_get_console_socket())) {
1151             return -1;
1152         }
1153         // Connect to the core's user events service.
1154         if (userEventsProxy_create(attachUiImpl_get_console_socket())) {
1155             return -1;
1156         }
1157     }
1158     return 0;
1159 }
1160 
1161 #else  /* !CONFIG_STANDALONE_UI */
1162 
handle_ui_options(AndroidOptions * opts)1163 void handle_ui_options( AndroidOptions* opts )
1164 {
1165     return;
1166 }
1167 
attach_ui_to_core(AndroidOptions * opts)1168 int attach_ui_to_core( AndroidOptions* opts )
1169 {
1170     return 0;
1171 }
1172 
1173 #endif /* CONFIG_STANDALONE_UI */
1174