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
58static AUserConfig*  userConfig;
59
60void
61user_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 */
67void
68user_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
82void
83user_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
91unsigned 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
103uint64_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
119SkinKeyset*  android_keyset = NULL;
120
121static int
122load_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
137void
138parse_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
178void
179write_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
213void *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
221static void
222sdl_set_window_icon( void )
223{
224    static int  window_icon_set;
225
226    if (!window_icon_set)
227    {
228#ifdef _WIN32
229        HANDLE         handle = GetModuleHandle( NULL );
230        HICON          icon   = LoadIcon( handle, MAKEINTRESOURCE(1) );
231        SDL_SysWMinfo  wminfo;
232
233        SDL_GetWMInfo(&wminfo);
234
235        SetClassLong( wminfo.window, GCL_HICON, (LONG)icon );
236#else  /* !_WIN32 */
237        unsigned              icon_w, icon_h;
238        size_t                icon_bytes;
239        const unsigned char*  icon_data;
240        void*                 icon_pixels;
241
242        window_icon_set = 1;
243
244        icon_data = android_icon_find( ANDROID_ICON_PNG, &icon_bytes );
245        if ( !icon_data )
246            return;
247
248        icon_pixels = readpng( icon_data, icon_bytes, &icon_w, &icon_h );
249        if ( !icon_pixels )
250            return;
251
252       /* the data is loaded into memory as RGBA bytes by libpng. we want to manage
253        * the values as 32-bit ARGB pixels, so swap the bytes accordingly depending
254        * on our CPU endianess
255        */
256        {
257            unsigned*  d     = icon_pixels;
258            unsigned*  d_end = d + icon_w*icon_h;
259
260            for ( ; d < d_end; d++ ) {
261                unsigned  pix = d[0];
262#if HOST_WORDS_BIGENDIAN
263                /* R,G,B,A read as RGBA => ARGB */
264                pix = ((pix >> 8) & 0xffffff) | (pix << 24);
265#else
266                /* R,G,B,A read as ABGR => ARGB */
267                pix = (pix & 0xff00ff00) | ((pix >> 16) & 0xff) | ((pix & 0xff) << 16);
268#endif
269                d[0] = pix;
270            }
271        }
272
273        SDL_Surface* icon = sdl_surface_from_argb32( icon_pixels, icon_w, icon_h );
274        if (icon != NULL) {
275            SDL_WM_SetIcon(icon, NULL);
276            SDL_FreeSurface(icon);
277            free( icon_pixels );
278        }
279#endif  /* !_WIN32 */
280    }
281}
282
283/***********************************************************************/
284/***********************************************************************/
285/*****                                                             *****/
286/*****            S K I N   S U P P O R T                          *****/
287/*****                                                             *****/
288/***********************************************************************/
289/***********************************************************************/
290
291const char*  skin_network_speed = NULL;
292const char*  skin_network_delay = NULL;
293
294
295static void sdl_at_exit(void)
296{
297    user_config_done();
298    qemulator_done(qemulator_get());
299    SDL_Quit();
300}
301
302
303void 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 */
325static 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
338void
339parse_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
427FOUND_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
486DEFAULT_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
511void
512init_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 */
594static char*
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
660FOUND_IT:
661    //D("image auto-detection: %s/%s", temp, fileName);
662    return android_strdup(temp);
663}
664
665static char*
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
678static char*
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
692void 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
784AvdInfo* 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. */
948int 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
961typedef struct {
962    LoopIo                 io[1];
963    int                    port;
964    int                    ok;
965    AsyncConsoleConnector  connector[1];
966} CoreConsole;
967
968static void
969coreconsole_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
979static void
980coreconsole_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
995static void
996coreconsole_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 */
1009static void
1010list_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 */
1061static int
1062attach_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
1132void 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
1142int 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
1163void handle_ui_options( AndroidOptions* opts )
1164{
1165    return;
1166}
1167
1168int attach_ui_to_core( AndroidOptions* opts )
1169{
1170    return 0;
1171}
1172
1173#endif /* CONFIG_STANDALONE_UI */
1174