Home | History | Annotate | Download | only in android
      1 /* Copyright (C) 2006-2010 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 
     13 #include "android/utils/debug.h"
     14 #include "android/utils/bufprint.h"
     15 #include "android/globals.h"
     16 #include "android/qemulator.h"
     17 #include "android/ui-core-protocol.h"
     18 
     19 #define  D(...)  do {  if (VERBOSE_CHECK(init)) dprint(__VA_ARGS__); } while (0)
     20 static double get_default_scale( AndroidOptions*  opts );
     21 
     22 /* QEmulator structure instance. */
     23 static QEmulator   qemulator[1];
     24 
     25 static void
     26 qemulator_light_brightness( void* opaque, const char*  light, int  value )
     27 {
     28     QEmulator*  emulator = opaque;
     29 
     30     VERBOSE_PRINT(hw_control,"%s: light='%s' value=%d window=%p", __FUNCTION__, light, value, emulator->window);
     31     if ( !strcmp(light, "lcd_backlight") ) {
     32         emulator->lcd_brightness = value;
     33         if (emulator->window)
     34             skin_window_set_lcd_brightness( emulator->window, value );
     35         return;
     36     }
     37 }
     38 
     39 static void
     40 qemulator_setup( QEmulator*  emulator )
     41 {
     42     AndroidOptions*  opts = emulator->opts;
     43 
     44     if ( !emulator->window && !opts->no_window ) {
     45         SkinLayout*  layout = emulator->layout;
     46         double       scale  = get_default_scale(emulator->opts);
     47 
     48         emulator->window = skin_window_create( layout, emulator->win_x, emulator->win_y, scale, 0);
     49         if (emulator->window == NULL)
     50             return;
     51 
     52         {
     53             SkinTrackBall*           ball;
     54             SkinTrackBallParameters  params;
     55 
     56             params.diameter   = 30;
     57             params.ring       = 2;
     58             params.ball_color = 0xffe0e0e0;
     59             params.dot_color  = 0xff202020;
     60             params.ring_color = 0xff000000;
     61 
     62             ball = skin_trackball_create( &params );
     63             emulator->trackball = ball;
     64             skin_window_set_trackball( emulator->window, ball );
     65 
     66             emulator->lcd_brightness = 128;  /* 50% */
     67             skin_window_set_lcd_brightness( emulator->window, emulator->lcd_brightness );
     68         }
     69 
     70         if ( emulator->onion != NULL )
     71             skin_window_set_onion( emulator->window,
     72                                    emulator->onion,
     73                                    emulator->onion_rotation,
     74                                    emulator->onion_alpha );
     75 
     76         qemulator_set_title(emulator);
     77 
     78         skin_window_enable_touch ( emulator->window, android_hw->hw_touchScreen != 0 );
     79         skin_window_enable_dpad  ( emulator->window, android_hw->hw_dPad != 0 );
     80         skin_window_enable_qwerty( emulator->window, android_hw->hw_keyboard != 0 );
     81         skin_window_enable_trackball( emulator->window, android_hw->hw_trackBall != 0 );
     82     }
     83 
     84     /* initialize hardware control support */
     85     android_core_set_brightness_change_callback(qemulator_light_brightness,
     86                                                 emulator);
     87 }
     88 
     89 static void
     90 qemulator_fb_update( void*   _emulator, int  x, int  y, int  w, int  h )
     91 {
     92     QEmulator*  emulator = _emulator;
     93 
     94     if (emulator->window)
     95         skin_window_update_display( emulator->window, x, y, w, h );
     96 }
     97 
     98 static void
     99 qemulator_fb_rotate( void*  _emulator, int  rotation )
    100 {
    101     QEmulator*     emulator = _emulator;
    102 
    103     qemulator_setup( emulator );
    104 }
    105 
    106 QEmulator*
    107 qemulator_get(void)
    108 {
    109     return qemulator;
    110 }
    111 
    112 int
    113 qemulator_init( QEmulator*       emulator,
    114                 AConfig*         aconfig,
    115                 const char*      basepath,
    116                 int              x,
    117                 int              y,
    118                 AndroidOptions*  opts )
    119 {
    120     emulator->aconfig     = aconfig;
    121     emulator->layout_file = skin_file_create_from_aconfig(aconfig, basepath);
    122     emulator->layout      = emulator->layout_file->layouts;
    123     // If we have a custom charmap use it to initialize keyboard.
    124     // Otherwise initialize keyboard from configuration settings.
    125     // Another way to configure keyboard to use a custom charmap would
    126     // be saving a custom charmap name into AConfig's keyboard->charmap
    127     // property, and calling single skin_keyboard_create_from_aconfig
    128     // routine to initialize keyboard.
    129     if (NULL != opts->charmap) {
    130         emulator->keyboard = skin_keyboard_create_from_kcm(opts->charmap, opts->raw_keys);
    131     } else {
    132         emulator->keyboard = skin_keyboard_create_from_aconfig(aconfig, opts->raw_keys);
    133     }
    134     emulator->window      = NULL;
    135     emulator->win_x       = x;
    136     emulator->win_y       = y;
    137     emulator->opts[0]     = opts[0];
    138 
    139     /* register as a framebuffer clients for all displays defined in the skin file */
    140     SKIN_FILE_LOOP_PARTS( emulator->layout_file, part )
    141         SkinDisplay*  disp = part->display;
    142         if (disp->valid) {
    143             qframebuffer_add_client( disp->qfbuff,
    144                                         emulator,
    145                                         qemulator_fb_update,
    146                                         qemulator_fb_rotate,
    147                                         NULL );
    148         }
    149     SKIN_FILE_LOOP_END_PARTS
    150     return 0;
    151 }
    152 
    153 void
    154 qemulator_done(QEmulator* emulator)
    155 {
    156     if (emulator->window) {
    157         skin_window_free(emulator->window);
    158         emulator->window = NULL;
    159     }
    160     if (emulator->trackball) {
    161         skin_trackball_destroy(emulator->trackball);
    162         emulator->trackball = NULL;
    163     }
    164     if (emulator->keyboard) {
    165         skin_keyboard_free(emulator->keyboard);
    166         emulator->keyboard = NULL;
    167     }
    168     emulator->layout = NULL;
    169     if (emulator->layout_file) {
    170         skin_file_free(emulator->layout_file);
    171         emulator->layout_file = NULL;
    172     }
    173 }
    174 
    175 SkinLayout*
    176 qemulator_get_layout(QEmulator* emulator)
    177 {
    178     return emulator->layout;
    179 }
    180 
    181 void
    182 qemulator_set_title(QEmulator* emulator)
    183 {
    184     char  temp[128], *p=temp, *end=p+sizeof temp;;
    185 
    186     if (emulator->window == NULL)
    187         return;
    188 
    189     if (emulator->show_trackball) {
    190         SkinKeyBinding  bindings[ SKIN_KEY_COMMAND_MAX_BINDINGS ];
    191         int             count;
    192 
    193         count = skin_keyset_get_bindings( android_keyset,
    194                                           SKIN_KEY_COMMAND_TOGGLE_TRACKBALL,
    195                                           bindings );
    196 
    197         if (count > 0) {
    198             int  nn;
    199             p = bufprint( p, end, "Press " );
    200             for (nn = 0; nn < count; nn++) {
    201                 if (nn > 0) {
    202                     if (nn < count-1)
    203                         p = bufprint(p, end, ", ");
    204                     else
    205                         p = bufprint(p, end, " or ");
    206                 }
    207                 p = bufprint(p, end, "%s",
    208                              skin_key_symmod_to_str( bindings[nn].sym,
    209                                                      bindings[nn].mod ) );
    210             }
    211             p = bufprint(p, end, " to leave trackball mode. ");
    212         }
    213     }
    214 
    215     p = bufprint(p, end, "%d:%s",
    216                  android_core_get_base_port(),
    217                  avdInfo_getName( android_avdInfo ));
    218 
    219     skin_window_set_title( emulator->window, temp );
    220 }
    221 
    222 /*
    223  * Helper routines
    224  */
    225 
    226 int
    227 get_device_dpi( AndroidOptions*  opts )
    228 {
    229     int    dpi_device  = android_core_get_hw_lcd_density();
    230 
    231     if (opts->dpi_device != NULL) {
    232         char*  end;
    233         dpi_device = strtol( opts->dpi_device, &end, 0 );
    234         if (end == NULL || *end != 0 || dpi_device <= 0) {
    235             fprintf(stderr, "argument for -dpi-device must be a positive integer. Aborting\n" );
    236             exit(1);
    237         }
    238     }
    239     return  dpi_device;
    240 }
    241 
    242 static double
    243 get_default_scale( AndroidOptions*  opts )
    244 {
    245     int     dpi_device  = get_device_dpi( opts );
    246     int     dpi_monitor = -1;
    247     double  scale       = 0.0;
    248 
    249     /* possible values for the 'scale' option are
    250      *   'auto'        : try to determine the scale automatically
    251      *   '<number>dpi' : indicates the host monitor dpi, compute scale accordingly
    252      *   '<fraction>'  : use direct scale coefficient
    253      */
    254 
    255     if (opts->scale) {
    256         if (!strcmp(opts->scale, "auto"))
    257         {
    258             /* we need to get the host dpi resolution ? */
    259             int   xdpi, ydpi;
    260 
    261             if ( SDL_WM_GetMonitorDPI( &xdpi, &ydpi ) < 0 ) {
    262                 fprintf(stderr, "could not get monitor DPI resolution from system. please use -dpi-monitor to specify one\n" );
    263                 exit(1);
    264             }
    265             D( "system reported monitor resolutions: xdpi=%d ydpi=%d\n", xdpi, ydpi);
    266             dpi_monitor = (xdpi + ydpi+1)/2;
    267         }
    268         else
    269         {
    270             char*   end;
    271             scale = strtod( opts->scale, &end );
    272 
    273             if (end && end[0] == 'd' && end[1] == 'p' && end[2] == 'i' && end[3] == 0) {
    274                 if ( scale < 20 || scale > 1000 ) {
    275                     fprintf(stderr, "emulator: ignoring bad -scale argument '%s': %s\n", opts->scale,
    276                             "host dpi number must be between 20 and 1000" );
    277                     exit(1);
    278                 }
    279                 dpi_monitor = scale;
    280                 scale       = 0.0;
    281             }
    282             else if (end == NULL || *end != 0) {
    283                 fprintf(stderr, "emulator: ignoring bad -scale argument '%s': %s\n", opts->scale,
    284                         "not a number or the 'auto' keyword" );
    285                 exit(1);
    286             }
    287             else if ( scale < 0.1 || scale > 3. ) {
    288                 fprintf(stderr, "emulator: ignoring bad -window-scale argument '%s': %s\n", opts->scale,
    289                         "must be between 0.1 and 3.0" );
    290                 exit(1);
    291             }
    292         }
    293     }
    294 
    295     if (scale == 0.0 && dpi_monitor > 0)
    296         scale = dpi_monitor*1.0/dpi_device;
    297 
    298     if (scale == 0.0)
    299         scale = 1.0;
    300 
    301     return scale;
    302 }
    303 
    304 /*
    305  * android/console.c helper routines.
    306  */
    307 
    308 SkinKeyboard*
    309 android_emulator_get_keyboard(void)
    310 {
    311     return qemulator->keyboard;
    312 }
    313 
    314 void
    315 android_emulator_set_window_scale( double  scale, int  is_dpi )
    316 {
    317     QEmulator*  emulator = qemulator;
    318 
    319     if (is_dpi)
    320         scale /= get_device_dpi( emulator->opts );
    321 
    322     if (emulator->window)
    323         skin_window_set_scale( emulator->window, scale );
    324 }
    325 
    326