main-common.c revision 74d7acec6643694132a127feb5ccadda7ea793d6
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/main-common.h" 31#include "android/globals.h" 32#include "android/resource.h" 33#include "android/user-config.h" 34#include "android/qemulator.h" 35#include "android/display.h" 36#include "android/skin/image.h" 37#include "android/skin/trackball.h" 38#include "android/skin/keyboard.h" 39#include "android/skin/file.h" 40#include "android/skin/window.h" 41 42 43 44/***********************************************************************/ 45/***********************************************************************/ 46/***** *****/ 47/***** U T I L I T Y R O U T I N E S *****/ 48/***** *****/ 49/***********************************************************************/ 50/***********************************************************************/ 51 52#define D(...) do { if (VERBOSE_CHECK(init)) dprint(__VA_ARGS__); } while (0) 53 54/*** CONFIGURATION 55 ***/ 56 57static AUserConfig* userConfig; 58 59void 60emulator_config_init( void ) 61{ 62 userConfig = auserConfig_new( android_avdInfo ); 63} 64 65/* only call this function on normal exits, so that ^C doesn't save the configuration */ 66void 67emulator_config_done( void ) 68{ 69 int win_x, win_y; 70 71 if (!userConfig) { 72 D("no user configuration?"); 73 return; 74 } 75 76 SDL_WM_GetPos( &win_x, &win_y ); 77 auserConfig_setWindowPos(userConfig, win_x, win_y); 78 auserConfig_save(userConfig); 79} 80 81void 82emulator_config_get_window_pos( int *window_x, int *window_y ) 83{ 84 *window_x = *window_y = 10; 85 86 if (userConfig) 87 auserConfig_getWindowPos(userConfig, window_x, window_y); 88} 89 90unsigned convertBytesToMB( uint64_t size ) 91{ 92 if (size == 0) 93 return 0; 94 95 size = (size + ONE_MB-1) >> 20; 96 if (size > UINT_MAX) 97 size = UINT_MAX; 98 99 return (unsigned) size; 100} 101 102uint64_t convertMBToBytes( unsigned megaBytes ) 103{ 104 return ((uint64_t)megaBytes << 20); 105} 106 107 108/***********************************************************************/ 109/***********************************************************************/ 110/***** *****/ 111/***** K E Y S E T R O U T I N E S *****/ 112/***** *****/ 113/***********************************************************************/ 114/***********************************************************************/ 115 116#define KEYSET_FILE "default.keyset" 117 118SkinKeyset* android_keyset = NULL; 119 120static int 121load_keyset(const char* path) 122{ 123 if (path_can_read(path)) { 124 AConfig* root = aconfig_node("",""); 125 if (!aconfig_load_file(root, path)) { 126 android_keyset = skin_keyset_new(root); 127 if (android_keyset != NULL) { 128 D( "keyset loaded from: %s", path); 129 return 0; 130 } 131 } 132 } 133 return -1; 134} 135 136void 137parse_keyset(const char* keyset, AndroidOptions* opts) 138{ 139 char kname[MAX_PATH]; 140 char temp[MAX_PATH]; 141 char* p; 142 char* end; 143 144 /* append .keyset suffix if needed */ 145 if (strchr(keyset, '.') == NULL) { 146 p = kname; 147 end = p + sizeof(kname); 148 p = bufprint(p, end, "%s.keyset", keyset); 149 if (p >= end) { 150 derror( "keyset name too long: '%s'\n", keyset); 151 exit(1); 152 } 153 keyset = kname; 154 } 155 156 /* look for a the keyset file */ 157 p = temp; 158 end = p + sizeof(temp); 159 p = bufprint_config_file(p, end, keyset); 160 if (p < end && load_keyset(temp) == 0) 161 return; 162 163 p = temp; 164 p = bufprint(p, end, "%s" PATH_SEP "keysets" PATH_SEP "%s", opts->sysdir, keyset); 165 if (p < end && load_keyset(temp) == 0) 166 return; 167 168 p = temp; 169 p = bufprint_app_dir(p, end); 170 p = bufprint(p, end, PATH_SEP "keysets" PATH_SEP "%s", keyset); 171 if (p < end && load_keyset(temp) == 0) 172 return; 173 174 return; 175} 176 177void 178write_default_keyset( void ) 179{ 180 char path[MAX_PATH]; 181 182 bufprint_config_file( path, path+sizeof(path), KEYSET_FILE ); 183 184 /* only write if there is no file here */ 185 if ( !path_exists(path) ) { 186 int fd = open( path, O_WRONLY | O_CREAT, 0666 ); 187 int ret; 188 const char* ks = skin_keyset_get_default(); 189 190 191 D( "writing default keyset file to %s", path ); 192 193 if (fd < 0) { 194 D( "%s: could not create file: %s", __FUNCTION__, strerror(errno) ); 195 return; 196 } 197 CHECKED(ret, write(fd, ks, strlen(ks))); 198 close(fd); 199 } 200} 201 202 203 204/***********************************************************************/ 205/***********************************************************************/ 206/***** *****/ 207/***** S D L S U P P O R T *****/ 208/***** *****/ 209/***********************************************************************/ 210/***********************************************************************/ 211 212void *readpng(const unsigned char* base, size_t size, unsigned *_width, unsigned *_height); 213 214#ifdef CONFIG_DARWIN 215# define ANDROID_ICON_PNG "android_icon_256.png" 216#else 217# define ANDROID_ICON_PNG "android_icon_16.png" 218#endif 219 220static void 221sdl_set_window_icon( void ) 222{ 223 static int window_icon_set; 224 225 if (!window_icon_set) 226 { 227#ifdef _WIN32 228 HANDLE handle = GetModuleHandle( NULL ); 229 HICON icon = LoadIcon( handle, MAKEINTRESOURCE(1) ); 230 SDL_SysWMinfo wminfo; 231 232 SDL_GetWMInfo(&wminfo); 233 234 SetClassLong( wminfo.window, GCL_HICON, (LONG)icon ); 235#else /* !_WIN32 */ 236 unsigned icon_w, icon_h; 237 size_t icon_bytes; 238 const unsigned char* icon_data; 239 void* icon_pixels; 240 241 window_icon_set = 1; 242 243 icon_data = android_icon_find( ANDROID_ICON_PNG, &icon_bytes ); 244 if ( !icon_data ) 245 return; 246 247 icon_pixels = readpng( icon_data, icon_bytes, &icon_w, &icon_h ); 248 if ( !icon_pixels ) 249 return; 250 251 /* the data is loaded into memory as RGBA bytes by libpng. we want to manage 252 * the values as 32-bit ARGB pixels, so swap the bytes accordingly depending 253 * on our CPU endianess 254 */ 255 { 256 unsigned* d = icon_pixels; 257 unsigned* d_end = d + icon_w*icon_h; 258 259 for ( ; d < d_end; d++ ) { 260 unsigned pix = d[0]; 261#if HOST_WORDS_BIGENDIAN 262 /* R,G,B,A read as RGBA => ARGB */ 263 pix = ((pix >> 8) & 0xffffff) | (pix << 24); 264#else 265 /* R,G,B,A read as ABGR => ARGB */ 266 pix = (pix & 0xff00ff00) | ((pix >> 16) & 0xff) | ((pix & 0xff) << 16); 267#endif 268 d[0] = pix; 269 } 270 } 271 272 SDL_Surface* icon = sdl_surface_from_argb32( icon_pixels, icon_w, icon_h ); 273 if (icon != NULL) { 274 SDL_WM_SetIcon(icon, NULL); 275 SDL_FreeSurface(icon); 276 free( icon_pixels ); 277 } 278#endif /* !_WIN32 */ 279 } 280} 281 282/***********************************************************************/ 283/***********************************************************************/ 284/***** *****/ 285/***** S K I N S U P P O R T *****/ 286/***** *****/ 287/***********************************************************************/ 288/***********************************************************************/ 289 290const char* skin_network_speed = NULL; 291const char* skin_network_delay = NULL; 292 293 294static void sdl_at_exit(void) 295{ 296 emulator_config_done(); 297 qemulator_done(qemulator_get()); 298 SDL_Quit(); 299} 300 301 302void sdl_display_init(DisplayState *ds, int full_screen, int no_frame) 303{ 304 QEmulator* emulator = qemulator_get(); 305 SkinDisplay* disp = skin_layout_get_display(emulator->layout); 306 int width, height; 307 char buf[128]; 308 309 if (disp->rotation & 1) { 310 width = disp->rect.size.h; 311 height = disp->rect.size.w; 312 } else { 313 width = disp->rect.size.w; 314 height = disp->rect.size.h; 315 } 316 317 snprintf(buf, sizeof buf, "width=%d,height=%d", width, height); 318 android_display_init(ds, qframebuffer_fifo_get()); 319} 320 321/* list of skin aliases */ 322static const struct { 323 const char* name; 324 const char* alias; 325} skin_aliases[] = { 326 { "QVGA-L", "320x240" }, 327 { "QVGA-P", "240x320" }, 328 { "HVGA-L", "480x320" }, 329 { "HVGA-P", "320x480" }, 330 { "QVGA", "320x240" }, 331 { "HVGA", "320x480" }, 332 { NULL, NULL } 333}; 334 335/* this is used by hw/events_device.c to send the charmap name to the system */ 336const char* android_skin_keycharmap = NULL; 337 338void 339parse_skin_files(const char* skinDirPath, 340 const char* skinName, 341 AndroidOptions* opts, 342 AConfig* *skinConfig, 343 char* *skinPath) 344{ 345 char tmp[1024]; 346 AConfig* root; 347 const char* path = NULL; 348 AConfig* n; 349 350 root = aconfig_node("", ""); 351 352 if (skinName == NULL) 353 goto DEFAULT_SKIN; 354 355 /* Support skin aliases like QVGA-H QVGA-P, etc... 356 But first we check if it's a directory that exist before applying 357 the alias */ 358 int checkAlias = 1; 359 360 if (skinDirPath != NULL) { 361 bufprint(tmp, tmp+sizeof(tmp), "%s/%s", skinDirPath, skinName); 362 if (path_exists(tmp)) { 363 checkAlias = 0; 364 } else { 365 D("there is no '%s' skin in '%s'", skinName, skinDirPath); 366 } 367 } 368 369 if (checkAlias) { 370 int nn; 371 372 for (nn = 0; ; nn++ ) { 373 const char* skin_name = skin_aliases[nn].name; 374 const char* skin_alias = skin_aliases[nn].alias; 375 376 if (!skin_name) 377 break; 378 379 if (!strcasecmp( skin_name, skinName )) { 380 D("skin name '%s' aliased to '%s'", skinName, skin_alias); 381 skinName = skin_alias; 382 break; 383 } 384 } 385 } 386 387 /* Magically support skins like "320x240" or "320x240x16" */ 388 if(isdigit(skinName[0])) { 389 char *x = strchr(skinName, 'x'); 390 if(x && isdigit(x[1])) { 391 int width = atoi(skinName); 392 int height = atoi(x+1); 393 int bpp = 16; 394 char* y = strchr(x+1, 'x'); 395 if (y && isdigit(y[1])) { 396 bpp = atoi(y+1); 397 } 398 snprintf(tmp, sizeof tmp, 399 "display {\n width %d\n height %d\n bpp %d}\n", 400 width, height,bpp); 401 aconfig_load(root, strdup(tmp)); 402 path = ":"; 403 D("found magic skin width=%d height=%d bpp=%d\n", width, height, bpp); 404 goto FOUND_SKIN; 405 } 406 } 407 408 if (skinDirPath == NULL) { 409 derror("unknown skin name '%s'", skinName); 410 exit(1); 411 } 412 413 snprintf(tmp, sizeof tmp, "%s/%s/layout", skinDirPath, skinName); 414 D("trying to load skin file '%s'", tmp); 415 416 if(aconfig_load_file(root, tmp) < 0) { 417 dwarning("could not load skin file '%s', using built-in one\n", 418 tmp); 419 goto DEFAULT_SKIN; 420 } 421 422 snprintf(tmp, sizeof tmp, "%s/%s/", skinDirPath, skinName); 423 path = tmp; 424 goto FOUND_SKIN; 425 426FOUND_SKIN: 427 /* the default network speed and latency can now be specified by the device skin */ 428 n = aconfig_find(root, "network"); 429 if (n != NULL) { 430 skin_network_speed = aconfig_str(n, "speed", 0); 431 skin_network_delay = aconfig_str(n, "delay", 0); 432 } 433 434 *skinConfig = root; 435 *skinPath = strdup(path); 436 return; 437 438DEFAULT_SKIN: 439 { 440 const unsigned char* layout_base; 441 size_t layout_size; 442 char* base; 443 444 skinName = "<builtin>"; 445 446 layout_base = android_resource_find( "layout", &layout_size ); 447 if (layout_base == NULL) { 448 fprintf(stderr, "Couldn't load builtin skin\n"); 449 exit(1); 450 } 451 base = malloc( layout_size+1 ); 452 memcpy( base, layout_base, layout_size ); 453 base[layout_size] = 0; 454 455 D("parsing built-in skin layout file (%d bytes)", (int)layout_size); 456 aconfig_load(root, base); 457 path = ":"; 458 } 459 goto FOUND_SKIN; 460} 461 462 463void 464init_sdl_ui(AConfig* skinConfig, 465 const char* skinPath, 466 AndroidOptions* opts) 467{ 468 int win_x, win_y, flags; 469 470 signal(SIGINT, SIG_DFL); 471#ifndef _WIN32 472 signal(SIGQUIT, SIG_DFL); 473#endif 474 475 /* we're not a game, so allow the screensaver to run */ 476 putenv("SDL_VIDEO_ALLOW_SCREENSAVER=1"); 477 478 flags = SDL_INIT_NOPARACHUTE; 479 if (!opts->no_window) 480 flags |= SDL_INIT_VIDEO; 481 482 if(SDL_Init(flags)){ 483 fprintf(stderr, "SDL init failure, reason is: %s\n", SDL_GetError() ); 484 exit(1); 485 } 486 487 if (!opts->no_window) { 488 SDL_EnableUNICODE(!opts->raw_keys); 489 SDL_EnableKeyRepeat(0,0); 490 491 sdl_set_window_icon(); 492 } 493 else 494 { 495#ifndef _WIN32 496 /* prevent SIGTTIN and SIGTTOUT from stopping us. this is necessary to be 497 * able to run the emulator in the background (e.g. "emulator &"). 498 * despite the fact that the emulator should not grab input or try to 499 * write to the output in normal cases, we're stopped on some systems 500 * (e.g. OS X) 501 */ 502 signal(SIGTTIN, SIG_IGN); 503 signal(SIGTTOU, SIG_IGN); 504#endif 505 } 506 atexit(sdl_at_exit); 507 508 emulator_config_get_window_pos(&win_x, &win_y); 509 510 if ( qemulator_init(qemulator_get(), skinConfig, skinPath, win_x, win_y, opts) < 0 ) { 511 fprintf(stderr, "### Error: could not load emulator skin from '%s'\n", skinPath); 512 exit(1); 513 } 514 515 android_skin_keycharmap = skin_keyboard_charmap_name(qemulator_get()->keyboard); 516 517 /* add an onion overlay image if needed */ 518 if (opts->onion) { 519 SkinImage* onion = skin_image_find_simple( opts->onion ); 520 int alpha, rotate; 521 522 if ( opts->onion_alpha && 1 == sscanf( opts->onion_alpha, "%d", &alpha ) ) { 523 alpha = (256*alpha)/100; 524 } else 525 alpha = 128; 526 527 if ( opts->onion_rotation && 1 == sscanf( opts->onion_rotation, "%d", &rotate ) ) { 528 rotate &= 3; 529 } else 530 rotate = SKIN_ROTATION_0; 531 532 qemulator_get()->onion = onion; 533 qemulator_get()->onion_alpha = alpha; 534 qemulator_get()->onion_rotation = rotate; 535 } 536} 537 538int64_t get_screen_pixels(AConfig* skinConfig) 539{ 540 int64_t pixels = 0; 541 AConfig* disp; 542 543 if (skinConfig != NULL) { 544 disp = aconfig_find(skinConfig, "display"); 545 if (disp != NULL) { 546 int width = aconfig_int(disp, "width", 0); 547 int height = aconfig_int(disp, "height", 0); 548 pixels = (int64_t)width*height; 549 } 550 } 551 if (pixels == 0) 552 pixels = 320*240; 553 554 return pixels; 555} 556