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
59static AUserConfig*  userConfig;
60
61void
62user_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 */
68void
69user_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
83void
84user_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
92unsigned 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
104uint64_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
120SkinKeyset*  android_keyset = NULL;
121
122static int
123load_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
138void
139parse_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
179void
180write_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
214void *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
222static void
223sdl_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
292const char*  skin_network_speed = NULL;
293const char*  skin_network_delay = NULL;
294
295
296static void sdl_at_exit(void)
297{
298    user_config_done();
299    qemulator_done(qemulator_get());
300    SDL_Quit();
301}
302
303
304void 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
325typedef struct part_properties part_properties;
326struct part_properties {
327    const char*      name;
328    int              width;
329    int              height;
330    part_properties* next;
331};
332
333part_properties*
334read_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
362void
363free_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
373part_properties*
374get_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
385void
386add_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
415int
416load_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 */
535static 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
548void
549parse_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
647FOUND_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
706DEFAULT_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
731void
732init_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 */
814static char*
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
880FOUND_IT:
881    //D("image auto-detection: %s/%s", temp, fileName);
882    return android_strdup(temp);
883}
884
885static char*
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
898static char*
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
912void 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
1004AvdInfo* 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. */
1168int 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
1181typedef struct {
1182    LoopIo                 io[1];
1183    int                    port;
1184    int                    ok;
1185    AsyncConsoleConnector  connector[1];
1186} CoreConsole;
1187
1188static void
1189coreconsole_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
1199static void
1200coreconsole_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
1215static void
1216coreconsole_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 */
1229static void
1230list_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 */
1281static int
1282attach_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
1352void 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
1362int 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
1383void handle_ui_options( AndroidOptions* opts )
1384{
1385    return;
1386}
1387
1388int attach_ui_to_core( AndroidOptions* opts )
1389{
1390    return 0;
1391}
1392
1393#endif /* CONFIG_STANDALONE_UI */
1394