main-common.c revision 40841b2d221273a08abfe20824e7631211ade31d
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
338/* this is used by hw/events_device.c to send the charmap name to the system */
339const char*    android_skin_keycharmap = NULL;
340
341void
342parse_skin_files(const char*      skinDirPath,
343                 const char*      skinName,
344                 AndroidOptions*  opts,
345                 AndroidHwConfig* hwConfig,
346                 AConfig*        *skinConfig,
347                 char*           *skinPath)
348{
349    char      tmp[1024];
350    AConfig*  root;
351    const char* path = NULL;
352    AConfig*  n;
353
354    root = aconfig_node("", "");
355
356    if (skinName == NULL)
357        goto DEFAULT_SKIN;
358
359    /* Support skin aliases like QVGA-H QVGA-P, etc...
360       But first we check if it's a directory that exist before applying
361       the alias */
362    int  checkAlias = 1;
363
364    if (skinDirPath != NULL) {
365        bufprint(tmp, tmp+sizeof(tmp), "%s/%s", skinDirPath, skinName);
366        if (path_exists(tmp)) {
367            checkAlias = 0;
368        } else {
369            D("there is no '%s' skin in '%s'", skinName, skinDirPath);
370        }
371    }
372
373    if (checkAlias) {
374        int  nn;
375
376        for (nn = 0; ; nn++ ) {
377            const char*  skin_name  = skin_aliases[nn].name;
378            const char*  skin_alias = skin_aliases[nn].alias;
379
380            if (!skin_name)
381                break;
382
383            if (!strcasecmp( skin_name, skinName )) {
384                D("skin name '%s' aliased to '%s'", skinName, skin_alias);
385                skinName = skin_alias;
386                break;
387            }
388        }
389    }
390
391    /* Magically support skins like "320x240" or "320x240x16" */
392    if(isdigit(skinName[0])) {
393        char *x = strchr(skinName, 'x');
394        if(x && isdigit(x[1])) {
395            int width = atoi(skinName);
396            int height = atoi(x+1);
397            int bpp   = 16;
398            char* y = strchr(x+1, 'x');
399            if (y && isdigit(y[1])) {
400                bpp = atoi(y+1);
401            }
402            snprintf(tmp, sizeof tmp,
403                        "display {\n  width %d\n  height %d\n bpp %d}\n",
404                        width, height,bpp);
405            aconfig_load(root, strdup(tmp));
406            path = ":";
407            D("found magic skin width=%d height=%d bpp=%d\n", width, height, bpp);
408            goto FOUND_SKIN;
409        }
410    }
411
412    if (skinDirPath == NULL) {
413        derror("unknown skin name '%s'", skinName);
414        exit(1);
415    }
416
417    snprintf(tmp, sizeof tmp, "%s/%s/layout", skinDirPath, skinName);
418    D("trying to load skin file '%s'", tmp);
419
420    if(aconfig_load_file(root, tmp) < 0) {
421        dwarning("could not load skin file '%s', using built-in one\n",
422                 tmp);
423        goto DEFAULT_SKIN;
424    }
425
426    snprintf(tmp, sizeof tmp, "%s/%s/", skinDirPath, skinName);
427    path = tmp;
428    goto FOUND_SKIN;
429
430FOUND_SKIN:
431    /* the default network speed and latency can now be specified by the device skin */
432    n = aconfig_find(root, "network");
433    if (n != NULL) {
434        skin_network_speed = aconfig_str(n, "speed", 0);
435        skin_network_delay = aconfig_str(n, "delay", 0);
436    }
437
438    /* extract framebuffer information from the skin.
439     *
440     * for version 1 of the skin format, they are in the top-level
441     * 'display' element.
442     *
443     * for version 2 of the skin format, they are under parts.device.display
444     */
445    n = aconfig_find(root, "display");
446    if (n == NULL) {
447        n = aconfig_find(root, "parts");
448        if (n != NULL) {
449            n = aconfig_find(root, "device");
450            if (n != NULL) {
451                n = aconfig_find(root, "display");
452            }
453        }
454    }
455
456    if (n != NULL) {
457        int  width  = aconfig_int(n, "width", hwConfig->hw_lcd_width);
458        int  height = aconfig_int(n, "height", hwConfig->hw_lcd_height);
459        int  depth  = aconfig_int(n, "bpp", hwConfig->hw_lcd_depth);
460
461        if (width > 0 && height > 0) {
462            /* The emulated framebuffer wants sizes that are multiples of 4 */
463            if (((width|height) & 3) != 0) {
464                width  = (width+3) & ~3;
465                height = (height+3) & ~3;
466                D("adjusting LCD dimensions to (%dx%dx)", width, height);
467            }
468
469            /* only depth values of 16 and 32 are correct. 16 is the default. */
470            if (depth != 32 && depth != 16) {
471                depth = 16;
472                D("adjusting LCD bit depth to %d", depth);
473            }
474
475            hwConfig->hw_lcd_width  = width;
476            hwConfig->hw_lcd_height = height;
477            hwConfig->hw_lcd_depth  = depth;
478        }
479        else {
480            D("ignoring invalid skin LCD dimensions (%dx%dx%d)",
481              width, height, depth);
482        }
483    }
484
485    *skinConfig = root;
486    *skinPath   = strdup(path);
487    return;
488
489DEFAULT_SKIN:
490    {
491        const unsigned char*  layout_base;
492        size_t                layout_size;
493        char*                 base;
494
495        skinName = "<builtin>";
496
497        layout_base = android_resource_find( "layout", &layout_size );
498        if (layout_base == NULL) {
499            fprintf(stderr, "Couldn't load builtin skin\n");
500            exit(1);
501        }
502        base = malloc( layout_size+1 );
503        memcpy( base, layout_base, layout_size );
504        base[layout_size] = 0;
505
506        D("parsing built-in skin layout file (%d bytes)", (int)layout_size);
507        aconfig_load(root, base);
508        path = ":";
509    }
510    goto FOUND_SKIN;
511}
512
513
514void
515init_sdl_ui(AConfig*         skinConfig,
516            const char*      skinPath,
517            AndroidOptions*  opts)
518{
519    int  win_x, win_y, flags;
520
521    signal(SIGINT, SIG_DFL);
522#ifndef _WIN32
523    signal(SIGQUIT, SIG_DFL);
524#endif
525
526    /* we're not a game, so allow the screensaver to run */
527    putenv("SDL_VIDEO_ALLOW_SCREENSAVER=1");
528
529    flags = SDL_INIT_NOPARACHUTE;
530    if (!opts->no_window)
531        flags |= SDL_INIT_VIDEO;
532
533    if(SDL_Init(flags)){
534        fprintf(stderr, "SDL init failure, reason is: %s\n", SDL_GetError() );
535        exit(1);
536    }
537
538    if (!opts->no_window) {
539        SDL_EnableUNICODE(!opts->raw_keys);
540        SDL_EnableKeyRepeat(0,0);
541
542        sdl_set_window_icon();
543    }
544    else
545    {
546#ifndef _WIN32
547       /* prevent SIGTTIN and SIGTTOUT from stopping us. this is necessary to be
548        * able to run the emulator in the background (e.g. "emulator &").
549        * despite the fact that the emulator should not grab input or try to
550        * write to the output in normal cases, we're stopped on some systems
551        * (e.g. OS X)
552        */
553        signal(SIGTTIN, SIG_IGN);
554        signal(SIGTTOU, SIG_IGN);
555#endif
556    }
557    atexit(sdl_at_exit);
558
559    user_config_get_window_pos(&win_x, &win_y);
560
561    if ( qemulator_init(qemulator_get(), skinConfig, skinPath, win_x, win_y, opts) < 0 ) {
562        fprintf(stderr, "### Error: could not load emulator skin from '%s'\n", skinPath);
563        exit(1);
564    }
565
566    android_skin_keycharmap = skin_keyboard_charmap_name(qemulator_get()->keyboard);
567
568    /* add an onion overlay image if needed */
569    if (opts->onion) {
570        SkinImage*  onion = skin_image_find_simple( opts->onion );
571        int         alpha, rotate;
572
573        if ( opts->onion_alpha && 1 == sscanf( opts->onion_alpha, "%d", &alpha ) ) {
574            alpha = (256*alpha)/100;
575        } else
576            alpha = 128;
577
578        if ( opts->onion_rotation && 1 == sscanf( opts->onion_rotation, "%d", &rotate ) ) {
579            rotate &= 3;
580        } else
581            rotate = SKIN_ROTATION_0;
582
583        qemulator_get()->onion          = onion;
584        qemulator_get()->onion_alpha    = alpha;
585        qemulator_get()->onion_rotation = rotate;
586    }
587}
588
589/* this function is used to perform auto-detection of the
590 * system directory in the case of a SDK installation.
591 *
592 * we want to deal with several historical usages, hence
593 * the slightly complicated logic.
594 *
595 * NOTE: the function returns the path to the directory
596 *       containing 'fileName'. this is *not* the full
597 *       path to 'fileName'.
598 */
599static char*
600_getSdkImagePath( const char*  fileName )
601{
602    char   temp[MAX_PATH];
603    char*  p   = temp;
604    char*  end = p + sizeof(temp);
605    char*  q;
606    char*  app;
607
608    static const char* const  searchPaths[] = {
609        "",                                  /* program's directory */
610        "/lib/images",                       /* this is for SDK 1.0 */
611        "/../platforms/android-1.1/images",  /* this is for SDK 1.1 */
612        NULL
613    };
614
615    app = bufprint_app_dir(temp, end);
616    if (app >= end)
617        return NULL;
618
619    do {
620        int  nn;
621
622        /* first search a few well-known paths */
623        for (nn = 0; searchPaths[nn] != NULL; nn++) {
624            p = bufprint(app, end, "%s", searchPaths[nn]);
625            q = bufprint(p, end, "/%s", fileName);
626            if (q < end && path_exists(temp)) {
627                *p = 0;
628                goto FOUND_IT;
629            }
630        }
631
632        /* hmmm. let's assume that we are in a post-1.1 SDK
633         * scan ../platforms if it exists
634         */
635        p = bufprint(app, end, "/../platforms");
636        if (p < end) {
637            DirScanner*  scanner = dirScanner_new(temp);
638            if (scanner != NULL) {
639                int          found = 0;
640                const char*  subdir;
641
642                for (;;) {
643                    subdir = dirScanner_next(scanner);
644                    if (!subdir) break;
645
646                    q = bufprint(p, end, "/%s/images/%s", subdir, fileName);
647                    if (q >= end || !path_exists(temp))
648                        continue;
649
650                    found = 1;
651                    p = bufprint(p, end, "/%s/images", subdir);
652                    break;
653                }
654                dirScanner_free(scanner);
655                if (found)
656                    break;
657            }
658        }
659
660        /* I'm out of ideas */
661        return NULL;
662
663    } while (0);
664
665FOUND_IT:
666    //D("image auto-detection: %s/%s", temp, fileName);
667    return android_strdup(temp);
668}
669
670static char*
671_getSdkImage( const char*  path, const char*  file )
672{
673    char  temp[MAX_PATH];
674    char  *p = temp, *end = p + sizeof(temp);
675
676    p = bufprint(temp, end, "%s/%s", path, file);
677    if (p >= end || !path_exists(temp))
678        return NULL;
679
680    return android_strdup(temp);
681}
682
683static char*
684_getSdkSystemImage( const char*  path, const char*  optionName, const char*  file )
685{
686    char*  image = _getSdkImage(path, file);
687
688    if (image == NULL) {
689        derror("Your system directory is missing the '%s' image file.\n"
690               "Please specify one with the '%s <filepath>' option",
691               file, optionName);
692        exit(2);
693    }
694    return image;
695}
696
697static void
698_forceAvdImagePath( AvdImageType  imageType,
699                   const char*   path,
700                   const char*   description,
701                   int           required )
702{
703    if (path == NULL)
704        return;
705
706    if (required && !path_exists(path)) {
707        derror("Cannot find %s image file: %s", description, path);
708        exit(1);
709    }
710    android_avdParams->forcePaths[imageType] = path;
711}
712
713
714void sanitizeOptions( AndroidOptions* opts )
715{
716    /* legacy support: we used to use -system <dir> and -image <file>
717     * instead of -sysdir <dir> and -system <file>, so handle this by checking
718     * whether the options point to directories or files.
719     */
720    if (opts->image != NULL) {
721        if (opts->system != NULL) {
722            if (opts->sysdir != NULL) {
723                derror( "You can't use -sysdir, -system and -image at the same time.\n"
724                        "You should probably use '-sysdir <path> -system <file>'.\n" );
725                exit(2);
726            }
727        }
728        dwarning( "Please note that -image is obsolete and that -system is now used to point\n"
729                  "to the system image. Next time, try using '-sysdir <path> -system <file>' instead.\n" );
730        opts->sysdir = opts->system;
731        opts->system = opts->image;
732        opts->image  = NULL;
733    }
734    else if (opts->system != NULL && path_is_dir(opts->system)) {
735        if (opts->sysdir != NULL) {
736            derror( "Option -system should now be followed by a file path, not a directory one.\n"
737                    "Please use '-sysdir <path>' to point to the system directory.\n" );
738            exit(1);
739        }
740        dwarning( "Please note that the -system option should now be used to point to the initial\n"
741                  "system image (like the obsolete -image option). To point to the system directory\n"
742                  "please now use '-sysdir <path>' instead.\n" );
743
744        opts->sysdir = opts->system;
745        opts->system = NULL;
746    }
747
748    if (opts->nojni) {
749        opts->no_jni = opts->nojni;
750        opts->nojni  = 0;
751    }
752
753    if (opts->nocache) {
754        opts->no_cache = opts->nocache;
755        opts->nocache  = 0;
756    }
757
758    if (opts->noaudio) {
759        opts->no_audio = opts->noaudio;
760        opts->noaudio  = 0;
761    }
762
763    if (opts->noskin) {
764        opts->no_skin = opts->noskin;
765        opts->noskin  = 0;
766    }
767
768    /* If -no-cache is used, ignore any -cache argument */
769    if (opts->no_cache) {
770        opts->cache = 0;
771    }
772
773    /* the purpose of -no-audio is to disable sound output from the emulator,
774     * not to disable Audio emulation. So simply force the 'none' backends */
775    if (opts->no_audio)
776        opts->audio = "none";
777
778    /* we don't accept -skindir without -skin now
779     * to simplify the autoconfig stuff with virtual devices
780     */
781    if (opts->no_skin) {
782        opts->skin    = "320x480";
783        opts->skindir = NULL;
784    }
785
786    if (opts->skindir) {
787        if (!opts->skin) {
788            derror( "the -skindir <path> option requires a -skin <name> option");
789            exit(1);
790        }
791    }
792
793    if (opts->bootchart) {
794        char*  end;
795        int    timeout = strtol(opts->bootchart, &end, 10);
796        if (timeout == 0)
797            opts->bootchart = NULL;
798        else if (timeout < 0 || timeout > 15*60) {
799            derror( "timeout specified for -bootchart option is invalid.\n"
800                    "please use integers between 1 and 900\n");
801            exit(1);
802        }
803    }
804}
805
806AvdInfo* createAVD(AndroidOptions* opts, int* inAndroidBuild)
807{
808    AvdInfo* ret = NULL;
809    char   tmp[MAX_PATH];
810    char*  tmpend = tmp + sizeof(tmp);
811    char*  android_build_root = NULL;
812    char*  android_build_out  = NULL;
813
814    /* setup the virtual device parameters from our options
815     */
816    if (opts->no_cache) {
817        android_avdParams->flags |= AVDINFO_NO_CACHE;
818    }
819    if (opts->wipe_data) {
820        android_avdParams->flags |= AVDINFO_WIPE_DATA | AVDINFO_WIPE_CACHE;
821    }
822    if (opts->no_snapstorage) {
823        android_avdParams->flags |= AVDINFO_NO_SNAPSHOTS;
824    }
825
826    /* If no AVD name was given, try to find the top of the
827     * Android build tree
828     */
829    if (opts->avd == NULL) {
830        do {
831            char*  out = getenv("ANDROID_PRODUCT_OUT");
832
833            if (out == NULL || out[0] == 0)
834                break;
835
836            if (!path_exists(out)) {
837                derror("Can't access ANDROID_PRODUCT_OUT as '%s'\n"
838                    "You need to build the Android system before launching the emulator",
839                    out);
840                exit(2);
841            }
842
843            android_build_root = path_parent( out, 4 );
844            if (android_build_root == NULL || !path_exists(android_build_root)) {
845                derror("Can't find the Android build root from '%s'\n"
846                    "Please check the definition of the ANDROID_PRODUCT_OUT variable.\n"
847                    "It should point to your product-specific build output directory.\n",
848                    out );
849                exit(2);
850            }
851            android_build_out = out;
852            D( "found Android build root: %s", android_build_root );
853            D( "found Android build out:  %s", android_build_out );
854        } while (0);
855    }
856    /* if no virtual device name is given, and we're not in the
857     * Android build system, we'll need to perform some auto-detection
858     * magic :-)
859     */
860    if (opts->avd == NULL && !android_build_out)
861    {
862        char   dataDirIsSystem = 0;
863
864        if (!opts->sysdir) {
865            opts->sysdir = _getSdkImagePath("system.img");
866            if (!opts->sysdir) {
867                derror(
868                "You did not specify a virtual device name, and the system\n"
869                "directory could not be found.\n\n"
870                "If you are an Android SDK user, please use '@<name>' or '-avd <name>'\n"
871                "to start a given virtual device (see -help-avd for details).\n\n"
872
873                "Otherwise, follow the instructions in -help-disk-images to start the emulator\n"
874                );
875                exit(2);
876            }
877            D("autoconfig: -sysdir %s", opts->sysdir);
878        }
879
880        if (!opts->system) {
881            opts->system = _getSdkSystemImage(opts->sysdir, "-image", "system.img");
882            D("autoconfig: -image %s", opts->image);
883        }
884
885        if (!opts->kernel) {
886            opts->kernel = _getSdkSystemImage(opts->sysdir, "-kernel", "kernel-qemu");
887            D("autoconfig: -kernel %s", opts->kernel);
888        }
889
890        if (!opts->ramdisk) {
891            opts->ramdisk = _getSdkSystemImage(opts->sysdir, "-ramdisk", "ramdisk.img");
892            D("autoconfig: -ramdisk %s", opts->ramdisk);
893        }
894
895        /* if no data directory is specified, use the system directory */
896        if (!opts->datadir) {
897            opts->datadir   = android_strdup(opts->sysdir);
898            dataDirIsSystem = 1;
899            D("autoconfig: -datadir %s", opts->sysdir);
900        }
901
902        if (!opts->data) {
903            /* check for userdata-qemu.img in the data directory */
904            bufprint(tmp, tmpend, "%s/userdata-qemu.img", opts->datadir);
905            if (!path_exists(tmp)) {
906                derror(
907                "You did not provide the name of an Android Virtual Device\n"
908                "with the '-avd <name>' option. Read -help-avd for more information.\n\n"
909
910                "If you *really* want to *NOT* run an AVD, consider using '-data <file>'\n"
911                "to specify a data partition image file (I hope you know what you're doing).\n"
912                );
913                exit(2);
914            }
915
916            opts->data = android_strdup(tmp);
917            D("autoconfig: -data %s", opts->data);
918        }
919
920        if (!opts->snapstorage && opts->datadir) {
921            bufprint(tmp, tmpend, "%s/snapshots.img", opts->datadir);
922            if (path_exists(tmp)) {
923                opts->snapstorage = android_strdup(tmp);
924                D("autoconfig: -snapstorage %s", opts->snapstorage);
925            }
926        }
927    }
928
929    /* if certain options are set, we can force the path of
930        * certain kernel/disk image files
931        */
932    _forceAvdImagePath(AVD_IMAGE_INITSYSTEM, opts->system,      "system", 1);
933    _forceAvdImagePath(AVD_IMAGE_USERDATA,   opts->data,        "user data", 0);
934    _forceAvdImagePath(AVD_IMAGE_SNAPSHOTS,  opts->snapstorage, "snapshots", 0);
935
936    android_avdParams->skinName     = opts->skin;
937    android_avdParams->skinRootPath = opts->skindir;
938
939    /* setup the virtual device differently depending on whether
940     * we are in the Android build system or not
941     */
942    if (opts->avd != NULL)
943    {
944        ret = avdInfo_new( opts->avd, android_avdParams );
945        if (ret == NULL) {
946            /* an error message has already been printed */
947            dprint("could not find virtual device named '%s'", opts->avd);
948            exit(1);
949        }
950    }
951    else
952    {
953        if (!android_build_out) {
954            android_build_out = android_build_root = opts->sysdir;
955        }
956        ret = avdInfo_newForAndroidBuild(
957                            android_build_root,
958                            android_build_out,
959                            android_avdParams );
960
961        if(ret == NULL) {
962            D("could not start virtual device\n");
963            exit(1);
964        }
965    }
966
967    if (android_build_out) {
968        *inAndroidBuild = 1;
969    } else {
970        *inAndroidBuild = 0;
971    }
972
973    return ret;
974}
975
976static int
977_is_valid_hw_disk_path(const char* path)
978{
979    if (path == NULL || '\0' == *path || !strcmp(path, "<init>")) {
980        return 0;
981    }
982    return 1;
983}
984
985static int
986_update_hwconfig_path(char** path,  AvdInfo* avd, int image_type)
987{
988    if (!_is_valid_hw_disk_path(*path)) {
989        *path = android_strdup(avdInfo_getImageFile(avd, image_type));
990        if (!_is_valid_hw_disk_path(*path)) {
991            return -1;
992        }
993    }
994    return 0;
995}
996
997static uint64_t
998_adjustPartitionSize( const char*  description,
999                      uint64_t     imageBytes,
1000                      uint64_t     defaultBytes,
1001                      int          inAndroidBuild )
1002{
1003    char      temp[64];
1004    unsigned  imageMB;
1005    unsigned  defaultMB;
1006
1007    if (imageBytes <= defaultBytes)
1008        return defaultBytes;
1009
1010    imageMB   = convertBytesToMB(imageBytes);
1011    defaultMB = convertBytesToMB(defaultBytes);
1012
1013    if (imageMB > defaultMB) {
1014        snprintf(temp, sizeof temp, "(%d MB > %d MB)", imageMB, defaultMB);
1015    } else {
1016        snprintf(temp, sizeof temp, "(%lld bytes > %lld bytes)", imageBytes, defaultBytes);
1017    }
1018
1019    if (inAndroidBuild) {
1020        dwarning("%s partition size adjusted to match image file %s\n", description, temp);
1021    }
1022
1023    return convertMBToBytes(imageMB);
1024}
1025
1026void
1027updateHwConfigFromAVD(AndroidHwConfig* hwConfig,
1028                      AvdInfo* avd,
1029                      AndroidOptions* opts,
1030                      int inAndroidBuild)
1031{
1032    unsigned  defaultPartitionSize = convertMBToBytes(66);
1033
1034    _update_hwconfig_path(&hwConfig->disk_dataPartition_path, avd, AVD_IMAGE_USERDATA);
1035    _update_hwconfig_path(&hwConfig->disk_dataPartition_path, avd, AVD_IMAGE_INITDATA);
1036
1037    if (opts->partition_size) {
1038        char*  end;
1039        long   sizeMB = strtol(opts->partition_size, &end, 0);
1040        long   minSizeMB = 10;
1041        long   maxSizeMB = LONG_MAX / ONE_MB;
1042
1043        if (sizeMB < 0 || *end != 0) {
1044            derror( "-partition-size must be followed by a positive integer" );
1045            exit(1);
1046        }
1047        if (sizeMB < minSizeMB || sizeMB > maxSizeMB) {
1048            derror( "partition-size (%d) must be between %dMB and %dMB",
1049                    sizeMB, minSizeMB, maxSizeMB );
1050            exit(1);
1051        }
1052        defaultPartitionSize = sizeMB * ONE_MB;
1053    }
1054    /* Check the size of the /data partition. The only interesting cases here are:
1055     * - when the USERDATA image already exists and is larger than the default
1056     * - when we're wiping data and the INITDATA is larger than the default.
1057     */
1058
1059    {
1060        const char*  dataPath     = avdInfo_getImageFile(avd, AVD_IMAGE_USERDATA);
1061        uint64_t     defaultBytes = defaultPartitionSize;
1062
1063        if (defaultBytes == 0 || opts->partition_size)
1064            defaultBytes = defaultPartitionSize;
1065
1066        if (dataPath == NULL || !path_exists(dataPath) || opts->wipe_data) {
1067            dataPath = avdInfo_getImageFile(avd, AVD_IMAGE_INITDATA);
1068        }
1069        if (dataPath == NULL || !path_exists(dataPath)) {
1070            hwConfig->disk_dataPartition_size = defaultBytes;
1071        }
1072        else {
1073            uint64_t  dataBytes;
1074            path_get_size(dataPath, &dataBytes);
1075
1076            hwConfig->disk_dataPartition_size =
1077                _adjustPartitionSize("data", dataBytes, defaultBytes, inAndroidBuild);
1078        }
1079    }
1080}
1081
1082
1083
1084#ifdef CONFIG_STANDALONE_UI
1085
1086#include "android/protocol/core-connection.h"
1087#include "android/protocol/fb-updates-impl.h"
1088#include "android/protocol/user-events-proxy.h"
1089#include "android/protocol/core-commands-proxy.h"
1090#include "android/protocol/ui-commands-impl.h"
1091#include "android/protocol/attach-ui-impl.h"
1092
1093/* Emulator's core port. */
1094int android_base_port = 0;
1095
1096// Base console port
1097#define CORE_BASE_PORT          5554
1098
1099// Maximum number of core porocesses running simultaneously on a machine.
1100#define MAX_CORE_PROCS          16
1101
1102// Socket timeout in millisec (set to 5 seconds)
1103#define CORE_PORT_TIMEOUT_MS    5000
1104
1105#include "android/async-console.h"
1106
1107typedef struct {
1108    LoopIo                 io[1];
1109    int                    port;
1110    int                    ok;
1111    AsyncConsoleConnector  connector[1];
1112} CoreConsole;
1113
1114static void
1115coreconsole_io_func(void* opaque, int fd, unsigned events)
1116{
1117    CoreConsole* cc = opaque;
1118    AsyncStatus  status;
1119    status = asyncConsoleConnector_run(cc->connector, cc->io);
1120    if (status == ASYNC_COMPLETE) {
1121        cc->ok = 1;
1122    }
1123}
1124
1125static void
1126coreconsole_init(CoreConsole* cc, const SockAddress* address, Looper* looper)
1127{
1128    int fd = socket_create_inet(SOCKET_STREAM);
1129    AsyncStatus status;
1130    cc->port = sock_address_get_port(address);
1131    cc->ok   = 0;
1132    loopIo_init(cc->io, looper, fd, coreconsole_io_func, cc);
1133    if (fd >= 0) {
1134        status = asyncConsoleConnector_connect(cc->connector, address, cc->io);
1135        if (status == ASYNC_ERROR) {
1136            cc->ok = 0;
1137        }
1138    }
1139}
1140
1141static void
1142coreconsole_done(CoreConsole* cc)
1143{
1144    socket_close(cc->io->fd);
1145    loopIo_done(cc->io);
1146}
1147
1148/* List emulator core processes running on the given machine.
1149 * This routine is called from main() if -list-cores parameter is set in the
1150 * command line.
1151 * Param:
1152 *  host Value passed with -list-core parameter. Must be either "localhost", or
1153 *  an IP address of a machine where core processes must be enumerated.
1154 */
1155static void
1156list_running_cores(const char* host)
1157{
1158    Looper*         looper;
1159    CoreConsole     cores[MAX_CORE_PROCS];
1160    SockAddress     address;
1161    int             nn, found;
1162
1163    if (sock_address_init_resolve(&address, host, CORE_BASE_PORT, 0) < 0) {
1164        derror("Unable to resolve hostname %s: %s", host, errno_str);
1165        return;
1166    }
1167
1168    looper = looper_newGeneric();
1169
1170    for (nn = 0; nn < MAX_CORE_PROCS; nn++) {
1171        int port = CORE_BASE_PORT + nn*2;
1172        sock_address_set_port(&address, port);
1173        coreconsole_init(&cores[nn], &address, looper);
1174    }
1175
1176    looper_runWithTimeout(looper, CORE_PORT_TIMEOUT_MS*2);
1177
1178    found = 0;
1179    for (nn = 0; nn < MAX_CORE_PROCS; nn++) {
1180        int port = CORE_BASE_PORT + nn*2;
1181        if (cores[nn].ok) {
1182            if (found == 0) {
1183                fprintf(stdout, "Running emulator core processes:\n");
1184            }
1185            fprintf(stdout, "Emulator console port %d\n", port);
1186            found++;
1187        }
1188        coreconsole_done(&cores[nn]);
1189    }
1190    looper_free(looper);
1191
1192    if (found == 0) {
1193       fprintf(stdout, "There were no running emulator core processes found on %s.\n",
1194               host);
1195    }
1196}
1197
1198/* Attaches starting UI to a running core process.
1199 * This routine is called from main() when -attach-core parameter is set,
1200 * indicating that this UI instance should attach to a running core, rather than
1201 * start a new core process.
1202 * Param:
1203 *  opts Android options containing non-NULL attach_core.
1204 * Return:
1205 *  0 on success, or -1 on failure.
1206 */
1207static int
1208attach_to_core(AndroidOptions* opts) {
1209    int iter;
1210    SockAddress console_socket;
1211    SockAddress** sockaddr_list;
1212    QEmulator* emulator;
1213
1214    // Parse attach_core param extracting the host name, and the port name.
1215    char* console_address = strdup(opts->attach_core);
1216    char* host_name = console_address;
1217    char* port_num = strchr(console_address, ':');
1218    if (port_num == NULL) {
1219        // The host name is ommited, indicating the localhost
1220        host_name = "localhost";
1221        port_num = console_address;
1222    } else if (port_num == console_address) {
1223        // Invalid.
1224        derror("Invalid value %s for -attach-core parameter\n",
1225               opts->attach_core);
1226        return -1;
1227    } else {
1228        *port_num = '\0';
1229        port_num++;
1230        if (*port_num == '\0') {
1231            // Invalid.
1232            derror("Invalid value %s for -attach-core parameter\n",
1233                   opts->attach_core);
1234            return -1;
1235        }
1236    }
1237
1238    /* Create socket address list for the given address, and pull appropriate
1239     * address to use for connection. Note that we're fine copying that address
1240     * out of the list, since INET and IN6 will entirely fit into SockAddress
1241     * structure. */
1242    sockaddr_list =
1243        sock_address_list_create(host_name, port_num, SOCKET_LIST_FORCE_INET);
1244    free(console_address);
1245    if (sockaddr_list == NULL) {
1246        derror("Unable to resolve address %s: %s\n",
1247               opts->attach_core, errno_str);
1248        return -1;
1249    }
1250    for (iter = 0; sockaddr_list[iter] != NULL; iter++) {
1251        if (sock_address_get_family(sockaddr_list[iter]) == SOCKET_INET ||
1252            sock_address_get_family(sockaddr_list[iter]) == SOCKET_IN6) {
1253            memcpy(&console_socket, sockaddr_list[iter], sizeof(SockAddress));
1254            break;
1255        }
1256    }
1257    if (sockaddr_list[iter] == NULL) {
1258        derror("Unable to resolve address %s. Note that 'port' parameter passed to -attach-core\n"
1259               "must be resolvable into an IP address.\n", opts->attach_core);
1260        sock_address_list_free(sockaddr_list);
1261        return -1;
1262    }
1263    sock_address_list_free(sockaddr_list);
1264
1265    if (attachUiImpl_create(&console_socket)) {
1266        return -1;
1267    }
1268
1269    // Save core's port, and set the title.
1270    android_base_port = sock_address_get_port(&console_socket);
1271    emulator = qemulator_get();
1272    qemulator_set_title(emulator);
1273
1274    return 0;
1275}
1276
1277
1278void handle_ui_options( AndroidOptions* opts )
1279{
1280    // Lets see if user just wants to list core process.
1281    if (opts->list_cores) {
1282        fprintf(stdout, "Enumerating running core processes.\n");
1283        list_running_cores(opts->list_cores);
1284        exit(0);
1285    }
1286}
1287
1288int attach_ui_to_core( AndroidOptions* opts )
1289{
1290    // Lets see if we're attaching to a running core process here.
1291    if (opts->attach_core) {
1292        if (attach_to_core(opts)) {
1293            return -1;
1294        }
1295        // Connect to the core's UI control services.
1296        if (coreCmdProxy_create(attachUiImpl_get_console_socket())) {
1297            return -1;
1298        }
1299        // Connect to the core's user events service.
1300        if (userEventsProxy_create(attachUiImpl_get_console_socket())) {
1301            return -1;
1302        }
1303    }
1304    return 0;
1305}
1306
1307#else  /* !CONFIG_STANDALONE_UI */
1308
1309void handle_ui_options( AndroidOptions* opts )
1310{
1311    return;
1312}
1313
1314int attach_ui_to_core( AndroidOptions* opts )
1315{
1316    return 0;
1317}
1318
1319#endif /* CONFIG_STANDALONE_UI */
1320