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