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