• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
qemulator_light_brightness(void * opaque,const char * light,int value)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
qemulator_setup(QEmulator * emulator)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
qemulator_fb_update(void * _emulator,int x,int y,int w,int h)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
qemulator_fb_rotate(void * _emulator,int rotation)99 qemulator_fb_rotate( void*  _emulator, int  rotation )
100 {
101     QEmulator*     emulator = _emulator;
102 
103     qemulator_setup( emulator );
104 }
105 
106 QEmulator*
qemulator_get(void)107 qemulator_get(void)
108 {
109     return qemulator;
110 }
111 
112 int
qemulator_init(QEmulator * emulator,AConfig * aconfig,const char * basepath,int x,int y,AndroidOptions * opts)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
qemulator_done(QEmulator * emulator)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*
qemulator_get_layout(QEmulator * emulator)176 qemulator_get_layout(QEmulator* emulator)
177 {
178     return emulator->layout;
179 }
180 
181 void
qemulator_set_title(QEmulator * emulator)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
get_device_dpi(AndroidOptions * opts)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
get_default_scale(AndroidOptions * opts)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*
android_emulator_get_keyboard(void)309 android_emulator_get_keyboard(void)
310 {
311     return qemulator->keyboard;
312 }
313 
314 void
android_emulator_set_window_scale(double scale,int is_dpi)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