Merge changes I5fc0f53f,If810fe10,Ie3f03d96,I59c1c4fc
* changes:
android-constants.c: Move constants to single file.
main-common.h: Add reassign_string().
android/: Add proper C++ inclusion guards.
android/avd: Add proper C++ inclusion guards.
diff --git a/Makefile.common b/Makefile.common
index 2ff49e8..c3f6820 100644
--- a/Makefile.common
+++ b/Makefile.common
@@ -103,6 +103,7 @@
# Android utility functions
#
common_LOCAL_SRC_FILES += \
+ android/android-constants.c \
android/async-console.c \
android/async-utils.c \
android/charmap.c \
diff --git a/Makefile.target b/Makefile.target
index e2d2871..4b50420 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -306,6 +306,7 @@
android/display-core.c \
android/help.c \
android/main-common.c \
+ android/main-common-ui.c \
android/main.c \
android/opengles.c \
android/protocol/core-commands-qemu.c \
diff --git a/android/android-constants.c b/android/android-constants.c
new file mode 100644
index 0000000..aa73d70
--- /dev/null
+++ b/android/android-constants.c
@@ -0,0 +1,39 @@
+/* Copyright (C) 2007 The Android Open Source Project
+**
+** This software is licensed under the terms of the GNU General Public
+** License version 2, as published by the Free Software Foundation, and
+** may be copied, distributed, and modified under those terms.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+*/
+
+#include "android/android.h"
+
+/* see http://en.wikipedia.org/wiki/List_of_device_bandwidths or a complete list */
+const NetworkSpeed android_netspeeds[] = {
+ { "gsm", "GSM/CSD", 14400, 14400 },
+ { "hscsd", "HSCSD", 14400, 43200 },
+ { "gprs", "GPRS", 40000, 80000 },
+ { "edge", "EDGE/EGPRS", 118400, 236800 },
+ { "umts", "UMTS/3G", 128000, 1920000 },
+ { "hsdpa", "HSDPA", 348000, 14400000 },
+ { "full", "no limit", 0, 0 },
+ { NULL, NULL, 0, 0 }
+};
+const size_t android_netspeeds_count =
+ sizeof(android_netspeeds) / sizeof(android_netspeeds[0]);
+
+const NetworkLatency android_netdelays[] = {
+ /* FIXME: these numbers are totally imaginary */
+ { "gprs", "GPRS", 150, 550 },
+ { "edge", "EDGE/EGPRS", 80, 400 },
+ { "umts", "UMTS/3G", 35, 200 },
+ { "none", "no latency", 0, 0 },
+ { NULL, NULL, 0, 0 }
+};
+const size_t android_netdelays_count =
+ sizeof(android_netdelays) / sizeof(android_netdelays[0]);
+
diff --git a/android/avd/hw-config.h b/android/avd/hw-config.h
index 82a3a5e..df9f1f0 100644
--- a/android/avd/hw-config.h
+++ b/android/avd/hw-config.h
@@ -13,8 +13,11 @@
#define _ANDROID_AVD_HW_CONFIG_H
#include <stdint.h>
+#include "android/utils/compiler.h"
#include "android/utils/ini.h"
+ANDROID_BEGIN_HEADER
+
typedef char hw_bool_t;
typedef int hw_int_t;
typedef int64_t hw_disksize_t;
@@ -86,4 +89,6 @@
// kernel.newDeviceNaming.
const char* androidHwConfig_getKernelSerialPrefix( AndroidHwConfig* config );
+ANDROID_END_HEADER
+
#endif /* _ANDROID_AVD_HW_CONFIG_H */
diff --git a/android/avd/info.h b/android/avd/info.h
index d2b0b74..f0fc1db 100644
--- a/android/avd/info.h
+++ b/android/avd/info.h
@@ -12,11 +12,14 @@
#ifndef ANDROID_AVD_INFO_H
#define ANDROID_AVD_INFO_H
+#include "android/utils/compiler.h"
#include "android/utils/ini.h"
#include "android/avd/hw-config.h"
#include "android/config/config.h"
#include "android/utils/file_data.h"
+ANDROID_BEGIN_HEADER
+
/* An Android Virtual Device (AVD for short) corresponds to a
* directory containing all kernel/disk images for a given virtual
* device, as well as information about its hardware capabilities,
@@ -284,6 +287,6 @@
*/
int avdInfo_getSnapshotPresent(AvdInfo* i);
-/* */
+ANDROID_END_HEADER
#endif /* ANDROID_AVD_INFO_H */
diff --git a/android/cmdline-option.h b/android/cmdline-option.h
index 6fba00a..cb650dd 100644
--- a/android/cmdline-option.h
+++ b/android/cmdline-option.h
@@ -12,6 +12,10 @@
#ifndef _ANDROID_OPTION_H
#define _ANDROID_OPTION_H
+#include "android/utils/compiler.h"
+
+ANDROID_BEGIN_HEADER
+
/* a structure used to model a linked list of parameters
*/
typedef struct ParamList {
@@ -43,4 +47,6 @@
*/
#define DEFAULT_DEVICE_DPI 165
+ANDROID_END_HEADER
+
#endif /* _ANDROID_OPTION_H */
diff --git a/android/help.c b/android/help.c
index 0fb7f40..3ba19bf 100644
--- a/android/help.c
+++ b/android/help.c
@@ -4,13 +4,13 @@
#include "android/utils/bufprint.h"
#include "android/utils/debug.h"
#include "android/utils/misc.h"
+#ifndef NO_SKIN
#include "android/skin/keyset.h"
+#endif
#include "android/android.h"
#include <stdint.h>
-#include "audio/audio.h"
#include <string.h>
#include <stdlib.h>
-#include "android/protocol/core-commands-api.h"
/* XXX: TODO: put most of the help stuff in auto-generated files */
@@ -208,6 +208,7 @@
static void
help_keys(stralloc_t* out)
{
+#ifndef NO_SKIN
int pass, maxw = 0;
stralloc_add_str( out, " When running the emulator, use the following keypresses:\n\n");
@@ -244,6 +245,7 @@
}
PRINTF( "\n" );
PRINTF( " note that NumLock must be deactivated for keypad keys to work\n\n" );
+#endif // !NO_SKIN
}
@@ -281,6 +283,7 @@
static void
help_keyset_file(stralloc_t* out)
{
+#ifndef NO_SKIN
int n, count;
const char** strings;
char temp[MAX_PATH];
@@ -346,6 +349,7 @@
" CHANGE_LAYOUT_PREV Keypad_7,Ctrl-J # switch to a previous skin layout\n"
"\n"
);
+#endif // !NO_SKIN
}
@@ -809,8 +813,6 @@
help_shaper(stralloc_t* out)
{
int n;
- NetworkSpeed* android_netspeed;
- NetworkLatency* android_netdelay;
PRINTF(
" the Android emulator supports network throttling, i.e. slower network\n"
" bandwidth as well as higher connection latencies. this is done either through\n"
@@ -818,24 +820,30 @@
" the format of -netspeed is one of the following (numbers are kbits/s):\n\n" );
- for (n = 0; !corecmd_get_netspeed(n, &android_netspeed); n++) {
+ for (n = 0;; ++n) {
+ const NetworkSpeed* android_netspeed = &android_netspeeds[n];
+ if (!android_netspeed->name) {
+ break;
+ }
PRINTF( " -netspeed %-12s %-15s (up: %.1f, down: %.1f)\n",
android_netspeed->name,
android_netspeed->display,
android_netspeed->upload/1000.,
android_netspeed->download/1000. );
- free(android_netspeed);
}
PRINTF( "\n" );
PRINTF( " -netspeed %-12s %s", "<num>", "select both upload and download speed\n");
PRINTF( " -netspeed %-12s %s", "<up>:<down>", "select individual up and down speed\n");
PRINTF( "\n The format of -netdelay is one of the following (numbers are msec):\n\n" );
- for (n = 0; !corecmd_get_netdelay(n, &android_netdelay); n++) {
+ for (n = 0; ; ++n) {
+ const NetworkLatency* android_netdelay = &android_netdelays[n];
+ if (!android_netdelay->name) {
+ break;
+ }
PRINTF( " -netdelay %-10s %-15s (min %d, max %d)\n",
android_netdelay->name, android_netdelay->display,
android_netdelay->min_ms, android_netdelay->max_ms );
- free(android_netdelay);
}
PRINTF( " -netdelay %-10s %s", "<num>", "select exact latency\n");
PRINTF( " -netdelay %-10s %s", "<min>:<max>", "select min and max latencies\n\n");
diff --git a/android/help.h b/android/help.h
index ee15941..5624823 100644
--- a/android/help.h
+++ b/android/help.h
@@ -12,8 +12,11 @@
#ifndef _ANDROID_HELP_H
#define _ANDROID_HELP_H
+#include "android/utils/compiler.h"
#include "android/utils/stralloc.h"
+ANDROID_BEGIN_HEADER
+
/* these values give the maximum length of system property
* names and values. They must match the definitions for PROPERTY_MAX_NAME and
* PROPERTY_MAX_VALUE in the Android source tree
@@ -41,4 +44,6 @@
*/
extern int android_help_for_topic( const char* topic, stralloc_t* out );
+ANDROID_END_HEADER
+
#endif /* _ANDROID_HELP_H */
diff --git a/android/main-common-ui.c b/android/main-common-ui.c
new file mode 100644
index 0000000..0a58eda
--- /dev/null
+++ b/android/main-common-ui.c
@@ -0,0 +1,758 @@
+/* Copyright (C) 2011 The Android Open Source Project
+**
+** This software is licensed under the terms of the GNU General Public
+** License version 2, as published by the Free Software Foundation, and
+** may be copied, distributed, and modified under those terms.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+*/
+
+#include <SDL.h>
+#include <SDL_syswm.h>
+
+#include "android/avd/util.h"
+#include "android/globals.h"
+#include "android/main-common.h"
+#include "android/qemulator.h"
+#include "android/display.h"
+#include "android/resource.h"
+#include "android/skin/image.h"
+#include "android/skin/trackball.h"
+#include "android/skin/keyboard.h"
+#include "android/skin/file.h"
+#include "android/skin/window.h"
+#include "android/user-config.h"
+#include "android/utils/bufprint.h"
+#include "android/utils/debug.h"
+#include "android/utils/eintr_wrapper.h"
+#include "android/utils/path.h"
+
+#include "ui/console.h"
+
+#include <stdlib.h>
+
+#define D(...) do { if (VERBOSE_CHECK(init)) dprint(__VA_ARGS__); } while (0)
+
+/*** CONFIGURATION
+ ***/
+
+static AUserConfig* userConfig;
+
+void
+user_config_init( void )
+{
+ userConfig = auserConfig_new( android_avdInfo );
+}
+
+/* only call this function on normal exits, so that ^C doesn't save the configuration */
+void
+user_config_done( void )
+{
+ int win_x, win_y;
+
+ if (!userConfig) {
+ D("no user configuration?");
+ return;
+ }
+
+ SDL_WM_GetPos( &win_x, &win_y );
+ auserConfig_setWindowPos(userConfig, win_x, win_y);
+ auserConfig_save(userConfig);
+}
+
+void
+user_config_get_window_pos( int *window_x, int *window_y )
+{
+ *window_x = *window_y = 10;
+
+ if (userConfig)
+ auserConfig_getWindowPos(userConfig, window_x, window_y);
+}
+
+/***********************************************************************/
+/***********************************************************************/
+/***** *****/
+/***** K E Y S E T R O U T I N E S *****/
+/***** *****/
+/***********************************************************************/
+/***********************************************************************/
+
+#define KEYSET_FILE "default.keyset"
+
+SkinKeyset* android_keyset = NULL;
+
+static int
+load_keyset(const char* path)
+{
+ if (path_can_read(path)) {
+ AConfig* root = aconfig_node("","");
+ if (!aconfig_load_file(root, path)) {
+ android_keyset = skin_keyset_new(root);
+ if (android_keyset != NULL) {
+ D( "keyset loaded from: %s", path);
+ return 0;
+ }
+ }
+ }
+ return -1;
+}
+
+void
+parse_keyset(const char* keyset, AndroidOptions* opts)
+{
+ char kname[MAX_PATH];
+ char temp[MAX_PATH];
+ char* p;
+ char* end;
+
+ /* append .keyset suffix if needed */
+ if (strchr(keyset, '.') == NULL) {
+ p = kname;
+ end = p + sizeof(kname);
+ p = bufprint(p, end, "%s.keyset", keyset);
+ if (p >= end) {
+ derror( "keyset name too long: '%s'\n", keyset);
+ exit(1);
+ }
+ keyset = kname;
+ }
+
+ /* look for a the keyset file */
+ p = temp;
+ end = p + sizeof(temp);
+ p = bufprint_config_file(p, end, keyset);
+ if (p < end && load_keyset(temp) == 0)
+ return;
+
+ p = temp;
+ p = bufprint(p, end, "%s" PATH_SEP "keysets" PATH_SEP "%s", opts->sysdir, keyset);
+ if (p < end && load_keyset(temp) == 0)
+ return;
+
+ p = temp;
+ p = bufprint_app_dir(p, end);
+ p = bufprint(p, end, PATH_SEP "keysets" PATH_SEP "%s", keyset);
+ if (p < end && load_keyset(temp) == 0)
+ return;
+
+ return;
+}
+
+void
+write_default_keyset( void )
+{
+ char path[MAX_PATH];
+
+ bufprint_config_file( path, path+sizeof(path), KEYSET_FILE );
+
+ /* only write if there is no file here */
+ if (!path_exists(path)) {
+ int fd = open( path, O_WRONLY | O_CREAT, 0666 );
+ const char* ks = skin_keyset_get_default();
+
+
+ D( "writing default keyset file to %s", path );
+
+ if (fd < 0) {
+ D( "%s: could not create file: %s", __FUNCTION__, strerror(errno) );
+ return;
+ }
+ HANDLE_EINTR(write(fd, ks, strlen(ks)));
+ IGNORE_EINTR(close(fd));
+ }
+}
+
+
+
+/***********************************************************************/
+/***********************************************************************/
+/***** *****/
+/***** S D L S U P P O R T *****/
+/***** *****/
+/***********************************************************************/
+/***********************************************************************/
+
+void *readpng(const unsigned char* base, size_t size, unsigned *_width, unsigned *_height);
+
+#ifdef CONFIG_DARWIN
+# define ANDROID_ICON_PNG "android_icon_256.png"
+#else
+# define ANDROID_ICON_PNG "android_icon_16.png"
+#endif
+
+static void
+sdl_set_window_icon( void )
+{
+ static int window_icon_set;
+
+ if (!window_icon_set)
+ {
+#ifdef _WIN32
+ HANDLE handle = GetModuleHandle( NULL );
+ HICON icon = LoadIcon( handle, MAKEINTRESOURCE(1) );
+ SDL_SysWMinfo wminfo;
+
+ SDL_GetWMInfo(&wminfo);
+
+ SetClassLongPtr( wminfo.window, GCLP_HICON, (LONG)icon );
+#else /* !_WIN32 */
+ unsigned icon_w, icon_h;
+ size_t icon_bytes;
+ const unsigned char* icon_data;
+ void* icon_pixels;
+
+ window_icon_set = 1;
+
+ icon_data = android_icon_find( ANDROID_ICON_PNG, &icon_bytes );
+ if ( !icon_data )
+ return;
+
+ icon_pixels = readpng( icon_data, icon_bytes, &icon_w, &icon_h );
+ if ( !icon_pixels )
+ return;
+
+ /* the data is loaded into memory as RGBA bytes by libpng. we want to manage
+ * the values as 32-bit ARGB pixels, so swap the bytes accordingly depending
+ * on our CPU endianess
+ */
+ {
+ unsigned* d = icon_pixels;
+ unsigned* d_end = d + icon_w*icon_h;
+
+ for ( ; d < d_end; d++ ) {
+ unsigned pix = d[0];
+#if HOST_WORDS_BIGENDIAN
+ /* R,G,B,A read as RGBA => ARGB */
+ pix = ((pix >> 8) & 0xffffff) | (pix << 24);
+#else
+ /* R,G,B,A read as ABGR => ARGB */
+ pix = (pix & 0xff00ff00) | ((pix >> 16) & 0xff) | ((pix & 0xff) << 16);
+#endif
+ d[0] = pix;
+ }
+ }
+
+ SDL_Surface* icon = sdl_surface_from_argb32( icon_pixels, icon_w, icon_h );
+ if (icon != NULL) {
+ SDL_WM_SetIcon(icon, NULL);
+ SDL_FreeSurface(icon);
+ free( icon_pixels );
+ }
+#endif /* !_WIN32 */
+ }
+}
+
+/***********************************************************************/
+/***********************************************************************/
+/***** *****/
+/***** S K I N S U P P O R T *****/
+/***** *****/
+/***********************************************************************/
+/***********************************************************************/
+
+const char* skin_network_speed = NULL;
+const char* skin_network_delay = NULL;
+
+
+static void sdl_at_exit(void)
+{
+ user_config_done();
+ qemulator_done(qemulator_get());
+ SDL_Quit();
+}
+
+
+void sdl_display_init(DisplayState *ds, int full_screen, int no_frame)
+{
+ QEmulator* emulator = qemulator_get();
+ SkinDisplay* disp = skin_layout_get_display(emulator->layout);
+ int width, height;
+ char buf[128];
+
+ if (disp->rotation & 1) {
+ width = disp->rect.size.h;
+ height = disp->rect.size.w;
+ } else {
+ width = disp->rect.size.w;
+ height = disp->rect.size.h;
+ }
+
+ snprintf(buf, sizeof buf, "width=%d,height=%d", width, height);
+#if !defined(CONFIG_STANDALONE_UI) && !defined(CONFIG_STANDALONE_CORE)
+ android_display_init(ds, qframebuffer_fifo_get());
+#endif
+}
+
+typedef struct part_properties part_properties;
+struct part_properties {
+ const char* name;
+ int width;
+ int height;
+ part_properties* next;
+};
+
+part_properties*
+read_all_part_properties(AConfig* parts)
+{
+ part_properties* head = NULL;
+ part_properties* prev = NULL;
+
+ AConfig *node = parts->first_child;
+ while (node) {
+ part_properties* t = calloc(1, sizeof(part_properties));
+ t->name = node->name;
+
+ AConfig* bg = aconfig_find(node, "background");
+ if (bg != NULL) {
+ t->width = aconfig_int(bg, "width", 0);
+ t->height = aconfig_int(bg, "height", 0);
+ }
+
+ if (prev == NULL) {
+ head = t;
+ } else {
+ prev->next = t;
+ }
+ prev = t;
+ node = node->next;
+ }
+
+ return head;
+}
+
+void
+free_all_part_properties(part_properties* head)
+{
+ part_properties* prev = head;
+ while (head) {
+ prev = head;
+ head = head->next;
+ free(prev);
+ }
+}
+
+part_properties*
+get_part_properties(part_properties* allparts, char *partname)
+{
+ part_properties* p;
+ for (p = allparts; p != NULL; p = p->next) {
+ if (!strcmp(partname, p->name))
+ return p;
+ }
+
+ return NULL;
+}
+
+void
+add_parts_to_layout(AConfig* layout,
+ char* parts[],
+ int n_parts,
+ part_properties *props,
+ int xoffset,
+ int x_margin,
+ int y_margin)
+{
+ int i;
+ int y = 10;
+ char tmp[512];
+ for (i = 0; i < n_parts; i++) {
+ part_properties *p = get_part_properties(props, parts[i]);
+ snprintf(tmp, sizeof tmp,
+ "part%d {\n \
+ name %s\n \
+ x %d\n \
+ y %d\n \
+ }",
+ i + 2, // layout already has the device part as part1, so start from part2
+ p->name,
+ xoffset + x_margin,
+ y
+ );
+ y += p->height + y_margin;
+ aconfig_load(layout, strdup(tmp));
+ }
+}
+
+int
+load_dynamic_skin(AndroidHwConfig* hwConfig,
+ char** skinDirPath,
+ int width,
+ int height,
+ AConfig* root)
+{
+ char tmp[1024];
+ AConfig* node;
+ int i;
+ int max_part_width;
+
+ *skinDirPath = avdInfo_getDynamicSkinPath(android_avdInfo);
+ if (*skinDirPath == NULL) {
+ dwarning("Unable to locate dynamic skin directory. Will not use dynamic skin.");
+ return 0;
+ }
+
+ snprintf(tmp, sizeof(tmp), "%s/layout", *skinDirPath);
+ D("trying to load skin file '%s'", tmp);
+
+ if(aconfig_load_file(root, tmp) < 0) {
+ dwarning("could not load skin file '%s', won't use a skin\n", tmp);
+ return 0;
+ }
+
+ /* Fix the width and height specified for the "device" part in the layout */
+ node = aconfig_find(root, "parts");
+ if (node != NULL) {
+ node = aconfig_find(node, "device");
+ if (node != NULL) {
+ node = aconfig_find(node, "display");
+ if (node != NULL) {
+ snprintf(tmp, sizeof tmp, "%d", width);
+ aconfig_set(node, "width", strdup(tmp));
+ snprintf(tmp, sizeof tmp, "%d", height);
+ aconfig_set(node, "height", strdup(tmp));
+ }
+ }
+ }
+
+ /* The dynamic layout declares all the parts that are available statically
+ in the layout file. Now we need to dynamically generate the
+ appropriate layout based on the hardware config */
+
+ part_properties* props = read_all_part_properties(aconfig_find(root, "parts"));
+
+ const int N_PARTS = 4;
+ char* parts[N_PARTS];
+ parts[0] = "basic_controls";
+ parts[1] = hwConfig->hw_mainKeys ? "hwkeys_on" : "hwkeys_off";
+ parts[2] = hwConfig->hw_dPad ? "dpad_on" : "dpad_off";
+ parts[3] = hwConfig->hw_keyboard ? "keyboard_on" : "keyboard_off";
+
+ for (i = 0, max_part_width = 0; i < N_PARTS; i++) {
+ part_properties *p = get_part_properties(props, parts[i]);
+ if (p != NULL && p->width > max_part_width)
+ max_part_width = p->width;
+ }
+
+ int x_margin = 10;
+ int y_margin = 10;
+ snprintf(tmp, sizeof tmp,
+ "layouts {\n \
+ portrait {\n \
+ width %d\n \
+ height %d\n \
+ color 0x404040\n \
+ event EV_SW:0:1\n \
+ part1 {\n name device\n x 0\n y 0\n}\n \
+ }\n \
+ landscape {\n \
+ width %d\n \
+ height %d\n \
+ color 0x404040\n \
+ event EV_SW:0:0\n \
+ dpad-rotation 3\n \
+ part1 {\n name device\n x 0\n y %d\n rotation 3\n }\n \
+ }\n \
+ }\n \
+ }\n",
+ width + max_part_width + 2 * x_margin,
+ height,
+ height + max_part_width + 2 * x_margin,
+ width,
+ width);
+ aconfig_load(root, strdup(tmp));
+
+ /* Add parts to portrait orientation */
+ node = aconfig_find(root, "layouts");
+ if (node != NULL) {
+ node = aconfig_find(node, "portrait");
+ if (node != NULL) {
+ add_parts_to_layout(node, parts, N_PARTS, props, width, x_margin, y_margin);
+ }
+ }
+
+ /* Add parts to landscape orientation */
+ node = aconfig_find(root, "layouts");
+ if (node != NULL) {
+ node = aconfig_find(node, "landscape");
+ if (node != NULL) {
+ add_parts_to_layout(node, parts, N_PARTS, props, height, x_margin, y_margin);
+ }
+ }
+
+ free_all_part_properties(props);
+
+ return 1;
+}
+
+/* list of skin aliases */
+static const struct {
+ const char* name;
+ const char* alias;
+} skin_aliases[] = {
+ { "QVGA-L", "320x240" },
+ { "QVGA-P", "240x320" },
+ { "HVGA-L", "480x320" },
+ { "HVGA-P", "320x480" },
+ { "QVGA", "320x240" },
+ { "HVGA", "320x480" },
+ { NULL, NULL }
+};
+
+void
+parse_skin_files(const char* skinDirPath,
+ const char* skinName,
+ AndroidOptions* opts,
+ AndroidHwConfig* hwConfig,
+ AConfig* *skinConfig,
+ char* *skinPath)
+{
+ char tmp[1024];
+ AConfig* root;
+ const char* path = NULL;
+ AConfig* n;
+
+ root = aconfig_node("", "");
+
+ if (skinName == NULL)
+ goto DEFAULT_SKIN;
+
+ /* Support skin aliases like QVGA-H QVGA-P, etc...
+ But first we check if it's a directory that exist before applying
+ the alias */
+ int checkAlias = 1;
+
+ if (skinDirPath != NULL) {
+ bufprint(tmp, tmp+sizeof(tmp), "%s/%s", skinDirPath, skinName);
+ if (path_exists(tmp)) {
+ checkAlias = 0;
+ } else {
+ D("there is no '%s' skin in '%s'", skinName, skinDirPath);
+ }
+ }
+
+ if (checkAlias) {
+ int nn;
+
+ for (nn = 0; ; nn++ ) {
+ const char* skin_name = skin_aliases[nn].name;
+ const char* skin_alias = skin_aliases[nn].alias;
+
+ if (!skin_name)
+ break;
+
+ if (!strcasecmp( skin_name, skinName )) {
+ D("skin name '%s' aliased to '%s'", skinName, skin_alias);
+ skinName = skin_alias;
+ break;
+ }
+ }
+ }
+
+ /* Magically support skins like "320x240" or "320x240x16" */
+ if(isdigit(skinName[0])) {
+ char *x = strchr(skinName, 'x');
+ if(x && isdigit(x[1])) {
+ int width = atoi(skinName);
+ int height = atoi(x+1);
+ int bpp = 16;
+ char* y = strchr(x+1, 'x');
+ if (y && isdigit(y[1])) {
+ bpp = atoi(y+1);
+ }
+
+ if (opts->dynamic_skin) {
+ char *dynamicSkinDirPath;
+ if (load_dynamic_skin(hwConfig, &dynamicSkinDirPath, width, height, root)) {
+ path = dynamicSkinDirPath;
+ D("loaded dynamic skin width=%d height=%d bpp=%d\n", width, height, bpp);
+ goto FOUND_SKIN;
+ }
+ }
+
+ snprintf(tmp, sizeof tmp,
+ "display {\n width %d\n height %d\n bpp %d}\n",
+ width, height,bpp);
+ aconfig_load(root, strdup(tmp));
+ path = ":";
+ D("found magic skin width=%d height=%d bpp=%d\n", width, height, bpp);
+ goto FOUND_SKIN;
+ }
+ }
+
+ if (skinDirPath == NULL) {
+ derror("unknown skin name '%s'", skinName);
+ exit(1);
+ }
+
+ snprintf(tmp, sizeof tmp, "%s/%s/layout", skinDirPath, skinName);
+ D("trying to load skin file '%s'", tmp);
+
+ if(aconfig_load_file(root, tmp) < 0) {
+ dwarning("could not load skin file '%s', using built-in one\n",
+ tmp);
+ goto DEFAULT_SKIN;
+ }
+
+ snprintf(tmp, sizeof tmp, "%s/%s/", skinDirPath, skinName);
+ path = tmp;
+ goto FOUND_SKIN;
+
+FOUND_SKIN:
+ /* the default network speed and latency can now be specified by the device skin */
+ n = aconfig_find(root, "network");
+ if (n != NULL) {
+ skin_network_speed = aconfig_str(n, "speed", 0);
+ skin_network_delay = aconfig_str(n, "delay", 0);
+ }
+
+ /* extract framebuffer information from the skin.
+ *
+ * for version 1 of the skin format, they are in the top-level
+ * 'display' element.
+ *
+ * for version 2 of the skin format, they are under parts.device.display
+ */
+ n = aconfig_find(root, "display");
+ if (n == NULL) {
+ n = aconfig_find(root, "parts");
+ if (n != NULL) {
+ n = aconfig_find(n, "device");
+ if (n != NULL) {
+ n = aconfig_find(n, "display");
+ }
+ }
+ }
+
+ if (n != NULL) {
+ int width = aconfig_int(n, "width", hwConfig->hw_lcd_width);
+ int height = aconfig_int(n, "height", hwConfig->hw_lcd_height);
+ int depth = aconfig_int(n, "bpp", hwConfig->hw_lcd_depth);
+
+ if (width > 0 && height > 0) {
+ /* The emulated framebuffer wants sizes that are multiples of 4 */
+ if (((width|height) & 3) != 0) {
+ width = (width+3) & ~3;
+ height = (height+3) & ~3;
+ D("adjusting LCD dimensions to (%dx%dx)", width, height);
+ }
+
+ /* only depth values of 16 and 32 are correct. 16 is the default. */
+ if (depth != 32 && depth != 16) {
+ depth = 16;
+ D("adjusting LCD bit depth to %d", depth);
+ }
+
+ hwConfig->hw_lcd_width = width;
+ hwConfig->hw_lcd_height = height;
+ hwConfig->hw_lcd_depth = depth;
+ }
+ else {
+ D("ignoring invalid skin LCD dimensions (%dx%dx%d)",
+ width, height, depth);
+ }
+ }
+
+ *skinConfig = root;
+ *skinPath = strdup(path);
+ return;
+
+DEFAULT_SKIN:
+ {
+ const unsigned char* layout_base;
+ size_t layout_size;
+ char* base;
+
+ skinName = "<builtin>";
+
+ layout_base = android_resource_find( "layout", &layout_size );
+ if (layout_base == NULL) {
+ fprintf(stderr, "Couldn't load builtin skin\n");
+ exit(1);
+ }
+ base = malloc( layout_size+1 );
+ memcpy( base, layout_base, layout_size );
+ base[layout_size] = 0;
+
+ D("parsing built-in skin layout file (%d bytes)", (int)layout_size);
+ aconfig_load(root, base);
+ path = ":";
+ }
+ goto FOUND_SKIN;
+}
+
+
+void
+init_sdl_ui(AConfig* skinConfig,
+ const char* skinPath,
+ AndroidOptions* opts)
+{
+ int win_x, win_y, flags;
+
+ signal(SIGINT, SIG_DFL);
+#ifndef _WIN32
+ signal(SIGQUIT, SIG_DFL);
+#endif
+
+ /* we're not a game, so allow the screensaver to run */
+ setenv("SDL_VIDEO_ALLOW_SCREENSAVER","1",1);
+
+ flags = SDL_INIT_NOPARACHUTE;
+ if (!opts->no_window)
+ flags |= SDL_INIT_VIDEO;
+
+ if(SDL_Init(flags)){
+ fprintf(stderr, "SDL init failure, reason is: %s\n", SDL_GetError() );
+ exit(1);
+ }
+
+ if (!opts->no_window) {
+ SDL_EnableUNICODE(!opts->raw_keys);
+ SDL_EnableKeyRepeat(0,0);
+
+ sdl_set_window_icon();
+ }
+ else
+ {
+#ifndef _WIN32
+ /* prevent SIGTTIN and SIGTTOUT from stopping us. this is necessary to be
+ * able to run the emulator in the background (e.g. "emulator &").
+ * despite the fact that the emulator should not grab input or try to
+ * write to the output in normal cases, we're stopped on some systems
+ * (e.g. OS X)
+ */
+ signal(SIGTTIN, SIG_IGN);
+ signal(SIGTTOU, SIG_IGN);
+#endif
+ }
+ atexit(sdl_at_exit);
+
+ user_config_get_window_pos(&win_x, &win_y);
+
+ if ( qemulator_init(qemulator_get(), skinConfig, skinPath, win_x, win_y, opts) < 0 ) {
+ fprintf(stderr, "### Error: could not load emulator skin from '%s'\n", skinPath);
+ exit(1);
+ }
+
+ /* add an onion overlay image if needed */
+ if (opts->onion) {
+ SkinImage* onion = skin_image_find_simple( opts->onion );
+ int alpha, rotate;
+
+ if ( opts->onion_alpha && 1 == sscanf( opts->onion_alpha, "%d", &alpha ) ) {
+ alpha = (256*alpha)/100;
+ } else
+ alpha = 128;
+
+ if ( opts->onion_rotation && 1 == sscanf( opts->onion_rotation, "%d", &rotate ) ) {
+ rotate &= 3;
+ } else
+ rotate = SKIN_ROTATION_0;
+
+ qemulator_get()->onion = onion;
+ qemulator_get()->onion_alpha = alpha;
+ qemulator_get()->onion_rotation = rotate;
+ }
+}
diff --git a/android/main-common.c b/android/main-common.c
index 990c44b..de51109 100644
--- a/android/main-common.c
+++ b/android/main-common.c
@@ -9,39 +9,28 @@
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
*/
-#include <signal.h>
-#include <unistd.h>
-#include <string.h>
-#include <sys/time.h>
-#include <errno.h>
-#include <fcntl.h>
-#ifdef _WIN32
-#include <process.h>
-#endif
-
-#include <SDL.h>
-#include <SDL_syswm.h>
-
-#include "ui/console.h"
-
#include "android/avd/util.h"
+#include "android/utils/bufprint.h"
#include "android/utils/debug.h"
#include "android/utils/eintr_wrapper.h"
#include "android/utils/path.h"
-#include "android/utils/bufprint.h"
#include "android/utils/dirscanner.h"
#include "android/main-common.h"
#include "android/globals.h"
#include "android/resource.h"
#include "android/user-config.h"
-#include "android/qemulator.h"
-#include "android/display.h"
-#include "android/skin/image.h"
-#include "android/skin/trackball.h"
-#include "android/skin/keyboard.h"
-#include "android/skin/file.h"
-#include "android/skin/window.h"
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#ifdef _WIN32
+#include <process.h>
+#endif
+#include <signal.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/time.h>
+#include <unistd.h>
/***********************************************************************/
@@ -54,40 +43,9 @@
#define D(...) do { if (VERBOSE_CHECK(init)) dprint(__VA_ARGS__); } while (0)
-/*** CONFIGURATION
- ***/
-
-static AUserConfig* userConfig;
-
-void
-user_config_init( void )
-{
- userConfig = auserConfig_new( android_avdInfo );
-}
-
-/* only call this function on normal exits, so that ^C doesn't save the configuration */
-void
-user_config_done( void )
-{
- int win_x, win_y;
-
- if (!userConfig) {
- D("no user configuration?");
- return;
- }
-
- SDL_WM_GetPos( &win_x, &win_y );
- auserConfig_setWindowPos(userConfig, win_x, win_y);
- auserConfig_save(userConfig);
-}
-
-void
-user_config_get_window_pos( int *window_x, int *window_y )
-{
- *window_x = *window_y = 10;
-
- if (userConfig)
- auserConfig_getWindowPos(userConfig, window_x, window_y);
+void reassign_string(char** string, const char* new_value) {
+ free(*string);
+ *string = ASTRDUP(new_value);
}
unsigned convertBytesToMB( uint64_t size )
@@ -107,692 +65,6 @@
return ((uint64_t)megaBytes << 20);
}
-
-/***********************************************************************/
-/***********************************************************************/
-/***** *****/
-/***** K E Y S E T R O U T I N E S *****/
-/***** *****/
-/***********************************************************************/
-/***********************************************************************/
-
-#define KEYSET_FILE "default.keyset"
-
-SkinKeyset* android_keyset = NULL;
-
-static int
-load_keyset(const char* path)
-{
- if (path_can_read(path)) {
- AConfig* root = aconfig_node("","");
- if (!aconfig_load_file(root, path)) {
- android_keyset = skin_keyset_new(root);
- if (android_keyset != NULL) {
- D( "keyset loaded from: %s", path);
- return 0;
- }
- }
- }
- return -1;
-}
-
-void
-parse_keyset(const char* keyset, AndroidOptions* opts)
-{
- char kname[MAX_PATH];
- char temp[MAX_PATH];
- char* p;
- char* end;
-
- /* append .keyset suffix if needed */
- if (strchr(keyset, '.') == NULL) {
- p = kname;
- end = p + sizeof(kname);
- p = bufprint(p, end, "%s.keyset", keyset);
- if (p >= end) {
- derror( "keyset name too long: '%s'\n", keyset);
- exit(1);
- }
- keyset = kname;
- }
-
- /* look for a the keyset file */
- p = temp;
- end = p + sizeof(temp);
- p = bufprint_config_file(p, end, keyset);
- if (p < end && load_keyset(temp) == 0)
- return;
-
- p = temp;
- p = bufprint(p, end, "%s" PATH_SEP "keysets" PATH_SEP "%s", opts->sysdir, keyset);
- if (p < end && load_keyset(temp) == 0)
- return;
-
- p = temp;
- p = bufprint_app_dir(p, end);
- p = bufprint(p, end, PATH_SEP "keysets" PATH_SEP "%s", keyset);
- if (p < end && load_keyset(temp) == 0)
- return;
-
- return;
-}
-
-void
-write_default_keyset( void )
-{
- char path[MAX_PATH];
-
- bufprint_config_file( path, path+sizeof(path), KEYSET_FILE );
-
- /* only write if there is no file here */
- if (!path_exists(path)) {
- int fd = open( path, O_WRONLY | O_CREAT, 0666 );
- const char* ks = skin_keyset_get_default();
-
-
- D( "writing default keyset file to %s", path );
-
- if (fd < 0) {
- D( "%s: could not create file: %s", __FUNCTION__, strerror(errno) );
- return;
- }
- HANDLE_EINTR(write(fd, ks, strlen(ks)));
- IGNORE_EINTR(close(fd));
- }
-}
-
-
-
-/***********************************************************************/
-/***********************************************************************/
-/***** *****/
-/***** S D L S U P P O R T *****/
-/***** *****/
-/***********************************************************************/
-/***********************************************************************/
-
-void *readpng(const unsigned char* base, size_t size, unsigned *_width, unsigned *_height);
-
-#ifdef CONFIG_DARWIN
-# define ANDROID_ICON_PNG "android_icon_256.png"
-#else
-# define ANDROID_ICON_PNG "android_icon_16.png"
-#endif
-
-static void
-sdl_set_window_icon( void )
-{
- static int window_icon_set;
-
- if (!window_icon_set)
- {
-#ifdef _WIN32
- HANDLE handle = GetModuleHandle( NULL );
- HICON icon = LoadIcon( handle, MAKEINTRESOURCE(1) );
- SDL_SysWMinfo wminfo;
-
- SDL_GetWMInfo(&wminfo);
-
- SetClassLongPtr( wminfo.window, GCLP_HICON, (LONG)icon );
-#else /* !_WIN32 */
- unsigned icon_w, icon_h;
- size_t icon_bytes;
- const unsigned char* icon_data;
- void* icon_pixels;
-
- window_icon_set = 1;
-
- icon_data = android_icon_find( ANDROID_ICON_PNG, &icon_bytes );
- if ( !icon_data )
- return;
-
- icon_pixels = readpng( icon_data, icon_bytes, &icon_w, &icon_h );
- if ( !icon_pixels )
- return;
-
- /* the data is loaded into memory as RGBA bytes by libpng. we want to manage
- * the values as 32-bit ARGB pixels, so swap the bytes accordingly depending
- * on our CPU endianess
- */
- {
- unsigned* d = icon_pixels;
- unsigned* d_end = d + icon_w*icon_h;
-
- for ( ; d < d_end; d++ ) {
- unsigned pix = d[0];
-#if HOST_WORDS_BIGENDIAN
- /* R,G,B,A read as RGBA => ARGB */
- pix = ((pix >> 8) & 0xffffff) | (pix << 24);
-#else
- /* R,G,B,A read as ABGR => ARGB */
- pix = (pix & 0xff00ff00) | ((pix >> 16) & 0xff) | ((pix & 0xff) << 16);
-#endif
- d[0] = pix;
- }
- }
-
- SDL_Surface* icon = sdl_surface_from_argb32( icon_pixels, icon_w, icon_h );
- if (icon != NULL) {
- SDL_WM_SetIcon(icon, NULL);
- SDL_FreeSurface(icon);
- free( icon_pixels );
- }
-#endif /* !_WIN32 */
- }
-}
-
-/***********************************************************************/
-/***********************************************************************/
-/***** *****/
-/***** S K I N S U P P O R T *****/
-/***** *****/
-/***********************************************************************/
-/***********************************************************************/
-
-const char* skin_network_speed = NULL;
-const char* skin_network_delay = NULL;
-
-
-static void sdl_at_exit(void)
-{
- user_config_done();
- qemulator_done(qemulator_get());
- SDL_Quit();
-}
-
-
-void sdl_display_init(DisplayState *ds, int full_screen, int no_frame)
-{
- QEmulator* emulator = qemulator_get();
- SkinDisplay* disp = skin_layout_get_display(emulator->layout);
- int width, height;
- char buf[128];
-
- if (disp->rotation & 1) {
- width = disp->rect.size.h;
- height = disp->rect.size.w;
- } else {
- width = disp->rect.size.w;
- height = disp->rect.size.h;
- }
-
- snprintf(buf, sizeof buf, "width=%d,height=%d", width, height);
-#if !defined(CONFIG_STANDALONE_UI) && !defined(CONFIG_STANDALONE_CORE)
- android_display_init(ds, qframebuffer_fifo_get());
-#endif
-}
-
-typedef struct part_properties part_properties;
-struct part_properties {
- const char* name;
- int width;
- int height;
- part_properties* next;
-};
-
-part_properties*
-read_all_part_properties(AConfig* parts)
-{
- part_properties* head = NULL;
- part_properties* prev = NULL;
-
- AConfig *node = parts->first_child;
- while (node) {
- part_properties* t = calloc(1, sizeof(part_properties));
- t->name = node->name;
-
- AConfig* bg = aconfig_find(node, "background");
- if (bg != NULL) {
- t->width = aconfig_int(bg, "width", 0);
- t->height = aconfig_int(bg, "height", 0);
- }
-
- if (prev == NULL) {
- head = t;
- } else {
- prev->next = t;
- }
- prev = t;
- node = node->next;
- }
-
- return head;
-}
-
-void
-free_all_part_properties(part_properties* head)
-{
- part_properties* prev = head;
- while (head) {
- prev = head;
- head = head->next;
- free(prev);
- }
-}
-
-part_properties*
-get_part_properties(part_properties* allparts, char *partname)
-{
- part_properties* p;
- for (p = allparts; p != NULL; p = p->next) {
- if (!strcmp(partname, p->name))
- return p;
- }
-
- return NULL;
-}
-
-void
-add_parts_to_layout(AConfig* layout,
- char* parts[],
- int n_parts,
- part_properties *props,
- int xoffset,
- int x_margin,
- int y_margin)
-{
- int i;
- int y = 10;
- char tmp[512];
- for (i = 0; i < n_parts; i++) {
- part_properties *p = get_part_properties(props, parts[i]);
- snprintf(tmp, sizeof tmp,
- "part%d {\n \
- name %s\n \
- x %d\n \
- y %d\n \
- }",
- i + 2, // layout already has the device part as part1, so start from part2
- p->name,
- xoffset + x_margin,
- y
- );
- y += p->height + y_margin;
- aconfig_load(layout, strdup(tmp));
- }
-}
-
-int
-load_dynamic_skin(AndroidHwConfig* hwConfig,
- char** skinDirPath,
- int width,
- int height,
- AConfig* root)
-{
- char tmp[1024];
- AConfig* node;
- int i;
- int max_part_width;
-
- *skinDirPath = avdInfo_getDynamicSkinPath(android_avdInfo);
- if (*skinDirPath == NULL) {
- dwarning("Unable to locate dynamic skin directory. Will not use dynamic skin.");
- return 0;
- }
-
- snprintf(tmp, sizeof(tmp), "%s/layout", *skinDirPath);
- D("trying to load skin file '%s'", tmp);
-
- if(aconfig_load_file(root, tmp) < 0) {
- dwarning("could not load skin file '%s', won't use a skin\n", tmp);
- return 0;
- }
-
- /* Fix the width and height specified for the "device" part in the layout */
- node = aconfig_find(root, "parts");
- if (node != NULL) {
- node = aconfig_find(node, "device");
- if (node != NULL) {
- node = aconfig_find(node, "display");
- if (node != NULL) {
- snprintf(tmp, sizeof tmp, "%d", width);
- aconfig_set(node, "width", strdup(tmp));
- snprintf(tmp, sizeof tmp, "%d", height);
- aconfig_set(node, "height", strdup(tmp));
- }
- }
- }
-
- /* The dynamic layout declares all the parts that are available statically
- in the layout file. Now we need to dynamically generate the
- appropriate layout based on the hardware config */
-
- part_properties* props = read_all_part_properties(aconfig_find(root, "parts"));
-
- const int N_PARTS = 4;
- char* parts[N_PARTS];
- parts[0] = "basic_controls";
- parts[1] = hwConfig->hw_mainKeys ? "hwkeys_on" : "hwkeys_off";
- parts[2] = hwConfig->hw_dPad ? "dpad_on" : "dpad_off";
- parts[3] = hwConfig->hw_keyboard ? "keyboard_on" : "keyboard_off";
-
- for (i = 0, max_part_width = 0; i < N_PARTS; i++) {
- part_properties *p = get_part_properties(props, parts[i]);
- if (p != NULL && p->width > max_part_width)
- max_part_width = p->width;
- }
-
- int x_margin = 10;
- int y_margin = 10;
- snprintf(tmp, sizeof tmp,
- "layouts {\n \
- portrait {\n \
- width %d\n \
- height %d\n \
- color 0x404040\n \
- event EV_SW:0:1\n \
- part1 {\n name device\n x 0\n y 0\n}\n \
- }\n \
- landscape {\n \
- width %d\n \
- height %d\n \
- color 0x404040\n \
- event EV_SW:0:0\n \
- dpad-rotation 3\n \
- part1 {\n name device\n x 0\n y %d\n rotation 3\n }\n \
- }\n \
- }\n \
- }\n",
- width + max_part_width + 2 * x_margin,
- height,
- height + max_part_width + 2 * x_margin,
- width,
- width);
- aconfig_load(root, strdup(tmp));
-
- /* Add parts to portrait orientation */
- node = aconfig_find(root, "layouts");
- if (node != NULL) {
- node = aconfig_find(node, "portrait");
- if (node != NULL) {
- add_parts_to_layout(node, parts, N_PARTS, props, width, x_margin, y_margin);
- }
- }
-
- /* Add parts to landscape orientation */
- node = aconfig_find(root, "layouts");
- if (node != NULL) {
- node = aconfig_find(node, "landscape");
- if (node != NULL) {
- add_parts_to_layout(node, parts, N_PARTS, props, height, x_margin, y_margin);
- }
- }
-
- free_all_part_properties(props);
-
- return 1;
-}
-
-/* list of skin aliases */
-static const struct {
- const char* name;
- const char* alias;
-} skin_aliases[] = {
- { "QVGA-L", "320x240" },
- { "QVGA-P", "240x320" },
- { "HVGA-L", "480x320" },
- { "HVGA-P", "320x480" },
- { "QVGA", "320x240" },
- { "HVGA", "320x480" },
- { NULL, NULL }
-};
-
-void
-parse_skin_files(const char* skinDirPath,
- const char* skinName,
- AndroidOptions* opts,
- AndroidHwConfig* hwConfig,
- AConfig* *skinConfig,
- char* *skinPath)
-{
- char tmp[1024];
- AConfig* root;
- const char* path = NULL;
- AConfig* n;
-
- root = aconfig_node("", "");
-
- if (skinName == NULL)
- goto DEFAULT_SKIN;
-
- /* Support skin aliases like QVGA-H QVGA-P, etc...
- But first we check if it's a directory that exist before applying
- the alias */
- int checkAlias = 1;
-
- if (skinDirPath != NULL) {
- bufprint(tmp, tmp+sizeof(tmp), "%s/%s", skinDirPath, skinName);
- if (path_exists(tmp)) {
- checkAlias = 0;
- } else {
- D("there is no '%s' skin in '%s'", skinName, skinDirPath);
- }
- }
-
- if (checkAlias) {
- int nn;
-
- for (nn = 0; ; nn++ ) {
- const char* skin_name = skin_aliases[nn].name;
- const char* skin_alias = skin_aliases[nn].alias;
-
- if (!skin_name)
- break;
-
- if (!strcasecmp( skin_name, skinName )) {
- D("skin name '%s' aliased to '%s'", skinName, skin_alias);
- skinName = skin_alias;
- break;
- }
- }
- }
-
- /* Magically support skins like "320x240" or "320x240x16" */
- if(isdigit(skinName[0])) {
- char *x = strchr(skinName, 'x');
- if(x && isdigit(x[1])) {
- int width = atoi(skinName);
- int height = atoi(x+1);
- int bpp = 16;
- char* y = strchr(x+1, 'x');
- if (y && isdigit(y[1])) {
- bpp = atoi(y+1);
- }
-
- if (opts->dynamic_skin) {
- char *dynamicSkinDirPath;
- if (load_dynamic_skin(hwConfig, &dynamicSkinDirPath, width, height, root)) {
- path = dynamicSkinDirPath;
- D("loaded dynamic skin width=%d height=%d bpp=%d\n", width, height, bpp);
- goto FOUND_SKIN;
- }
- }
-
- snprintf(tmp, sizeof tmp,
- "display {\n width %d\n height %d\n bpp %d}\n",
- width, height,bpp);
- aconfig_load(root, strdup(tmp));
- path = ":";
- D("found magic skin width=%d height=%d bpp=%d\n", width, height, bpp);
- goto FOUND_SKIN;
- }
- }
-
- if (skinDirPath == NULL) {
- derror("unknown skin name '%s'", skinName);
- exit(1);
- }
-
- snprintf(tmp, sizeof tmp, "%s/%s/layout", skinDirPath, skinName);
- D("trying to load skin file '%s'", tmp);
-
- if(aconfig_load_file(root, tmp) < 0) {
- dwarning("could not load skin file '%s', using built-in one\n",
- tmp);
- goto DEFAULT_SKIN;
- }
-
- snprintf(tmp, sizeof tmp, "%s/%s/", skinDirPath, skinName);
- path = tmp;
- goto FOUND_SKIN;
-
-FOUND_SKIN:
- /* the default network speed and latency can now be specified by the device skin */
- n = aconfig_find(root, "network");
- if (n != NULL) {
- skin_network_speed = aconfig_str(n, "speed", 0);
- skin_network_delay = aconfig_str(n, "delay", 0);
- }
-
- /* extract framebuffer information from the skin.
- *
- * for version 1 of the skin format, they are in the top-level
- * 'display' element.
- *
- * for version 2 of the skin format, they are under parts.device.display
- */
- n = aconfig_find(root, "display");
- if (n == NULL) {
- n = aconfig_find(root, "parts");
- if (n != NULL) {
- n = aconfig_find(n, "device");
- if (n != NULL) {
- n = aconfig_find(n, "display");
- }
- }
- }
-
- if (n != NULL) {
- int width = aconfig_int(n, "width", hwConfig->hw_lcd_width);
- int height = aconfig_int(n, "height", hwConfig->hw_lcd_height);
- int depth = aconfig_int(n, "bpp", hwConfig->hw_lcd_depth);
-
- if (width > 0 && height > 0) {
- /* The emulated framebuffer wants sizes that are multiples of 4 */
- if (((width|height) & 3) != 0) {
- width = (width+3) & ~3;
- height = (height+3) & ~3;
- D("adjusting LCD dimensions to (%dx%dx)", width, height);
- }
-
- /* only depth values of 16 and 32 are correct. 16 is the default. */
- if (depth != 32 && depth != 16) {
- depth = 16;
- D("adjusting LCD bit depth to %d", depth);
- }
-
- hwConfig->hw_lcd_width = width;
- hwConfig->hw_lcd_height = height;
- hwConfig->hw_lcd_depth = depth;
- }
- else {
- D("ignoring invalid skin LCD dimensions (%dx%dx%d)",
- width, height, depth);
- }
- }
-
- *skinConfig = root;
- *skinPath = strdup(path);
- return;
-
-DEFAULT_SKIN:
- {
- const unsigned char* layout_base;
- size_t layout_size;
- char* base;
-
- skinName = "<builtin>";
-
- layout_base = android_resource_find( "layout", &layout_size );
- if (layout_base == NULL) {
- fprintf(stderr, "Couldn't load builtin skin\n");
- exit(1);
- }
- base = malloc( layout_size+1 );
- memcpy( base, layout_base, layout_size );
- base[layout_size] = 0;
-
- D("parsing built-in skin layout file (%d bytes)", (int)layout_size);
- aconfig_load(root, base);
- path = ":";
- }
- goto FOUND_SKIN;
-}
-
-
-void
-init_sdl_ui(AConfig* skinConfig,
- const char* skinPath,
- AndroidOptions* opts)
-{
- int win_x, win_y, flags;
-
- signal(SIGINT, SIG_DFL);
-#ifndef _WIN32
- signal(SIGQUIT, SIG_DFL);
-#endif
-
- /* we're not a game, so allow the screensaver to run */
- setenv("SDL_VIDEO_ALLOW_SCREENSAVER","1",1);
-
- flags = SDL_INIT_NOPARACHUTE;
- if (!opts->no_window)
- flags |= SDL_INIT_VIDEO;
-
- if(SDL_Init(flags)){
- fprintf(stderr, "SDL init failure, reason is: %s\n", SDL_GetError() );
- exit(1);
- }
-
- if (!opts->no_window) {
- SDL_EnableUNICODE(!opts->raw_keys);
- SDL_EnableKeyRepeat(0,0);
-
- sdl_set_window_icon();
- }
- else
- {
-#ifndef _WIN32
- /* prevent SIGTTIN and SIGTTOUT from stopping us. this is necessary to be
- * able to run the emulator in the background (e.g. "emulator &").
- * despite the fact that the emulator should not grab input or try to
- * write to the output in normal cases, we're stopped on some systems
- * (e.g. OS X)
- */
- signal(SIGTTIN, SIG_IGN);
- signal(SIGTTOU, SIG_IGN);
-#endif
- }
- atexit(sdl_at_exit);
-
- user_config_get_window_pos(&win_x, &win_y);
-
- if ( qemulator_init(qemulator_get(), skinConfig, skinPath, win_x, win_y, opts) < 0 ) {
- fprintf(stderr, "### Error: could not load emulator skin from '%s'\n", skinPath);
- exit(1);
- }
-
- /* add an onion overlay image if needed */
- if (opts->onion) {
- SkinImage* onion = skin_image_find_simple( opts->onion );
- int alpha, rotate;
-
- if ( opts->onion_alpha && 1 == sscanf( opts->onion_alpha, "%d", &alpha ) ) {
- alpha = (256*alpha)/100;
- } else
- alpha = 128;
-
- if ( opts->onion_rotation && 1 == sscanf( opts->onion_rotation, "%d", &rotate ) ) {
- rotate &= 3;
- } else
- rotate = SKIN_ROTATION_0;
-
- qemulator_get()->onion = onion;
- qemulator_get()->onion_alpha = alpha;
- qemulator_get()->onion_rotation = rotate;
- }
-}
-
/* this function is used to perform auto-detection of the
* system directory in the case of a SDK installation.
*
diff --git a/android/main-common.h b/android/main-common.h
index 523e441..53c9029 100644
--- a/android/main-common.h
+++ b/android/main-common.h
@@ -13,13 +13,20 @@
#define ANDROID_MAIN_COMMON_H
#include <stdint.h>
-#include "android/cmdline-option.h"
-#include "android/skin/keyset.h"
-#include "android/config-file.h"
#include "android/avd/hw-config.h"
+#include "android/cmdline-option.h"
+#include "android/config-file.h"
+#include "android/skin/keyset.h"
+#include "android/utils/compiler.h"
+
+ANDROID_BEGIN_HEADER
/* Common routines used by both android/main.c and android/main-ui.c */
+// Reset the value of |*string| to a copy of |new_value|. This
+// will free() the previous value of |*string| first.
+void reassign_string(char** string, const char* new_value);
+
/** Emulator user configuration (e.g. last window position)
**/
@@ -103,4 +110,6 @@
*/
int attach_ui_to_core( AndroidOptions* opts );
+ANDROID_END_HEADER
+
#endif /* ANDROID_MAIN_COMMON_H */
diff --git a/android/main.c b/android/main.c
index 4f48291..b1a3053 100644
--- a/android/main.c
+++ b/android/main.c
@@ -405,14 +405,11 @@
/* Update CPU architecture for HW configs created from build dir. */
if (inAndroidBuild) {
#if defined(TARGET_ARM)
- free(android_hw->hw_cpu_arch);
- android_hw->hw_cpu_arch = ASTRDUP("arm");
+ reassign_string(&android_hw->hw_cpu_arch, "arm");
#elif defined(TARGET_I386)
- free(android_hw->hw_cpu_arch);
- android_hw->hw_cpu_arch = ASTRDUP("x86");
+ reassign_string(&android_hw->hw_cpu_arch, "x86");
#elif defined(TARGET_MIPS)
- free(android_hw->hw_cpu_arch);
- android_hw->hw_cpu_arch = ASTRDUP("mips");
+ reassign_string(&android_hw->hw_cpu_arch, "mips");
#endif
}
@@ -472,8 +469,7 @@
} else {
D("Auto-detect: Kernel image requires legacy device naming scheme.");
}
- AFREE(hw->kernel_newDeviceNaming);
- hw->kernel_newDeviceNaming = ASTRDUP(newDeviceNaming);
+ reassign_string(&hw->kernel_newDeviceNaming, newDeviceNaming);
}
// Auto-detect YAFFS2 partition support if needed.
@@ -486,8 +482,7 @@
} else {
D("Auto-detect: Kernel does not support YAFFS2 partitions.");
}
- AFREE(hw->kernel_supportsYaffs2);
- hw->kernel_supportsYaffs2 = ASTRDUP(newYaffs2Support);
+ reassign_string(&hw->kernel_supportsYaffs2, newYaffs2Support);
}
if (boot_prop_ip[0]) {
@@ -541,8 +536,7 @@
/* opts->ramdisk is never NULL (see createAVD) here */
if (opts->ramdisk) {
- AFREE(hw->disk_ramdisk_path);
- hw->disk_ramdisk_path = ASTRDUP(opts->ramdisk);
+ reassign_string(&hw->disk_ramdisk_path, opts->ramdisk);
}
else if (!hw->disk_ramdisk_path[0]) {
hw->disk_ramdisk_path = avdInfo_getRamdiskPath(avd);
@@ -1157,8 +1151,7 @@
*/
kcm_extract_charmap_name(opts->charmap, charmap_name,
sizeof(charmap_name));
- AFREE(hw->hw_keyboard_charmap);
- hw->hw_keyboard_charmap = ASTRDUP(charmap_name);
+ reassign_string(&hw->hw_keyboard_charmap, charmap_name);
}
if (opts->gpu) {
@@ -1247,8 +1240,7 @@
exit(1);
}
} else {
- AFREE(opts->accel);
- opts->accel = ASTRDUP("off");
+ reassign_string(&opts->accel, "off");
}
}
@@ -1382,8 +1374,7 @@
}
if (forceArmv7 != 0) {
- AFREE(hw->hw_cpu_model);
- hw->hw_cpu_model = ASTRDUP("cortex-a8");
+ reassign_string(&hw->hw_cpu_model, "cortex-a8");
D("Auto-config: -qemu -cpu %s", hw->hw_cpu_model);
}
@@ -1396,8 +1387,7 @@
char* arch = avdInfo_getTargetCpuArch(avd);
D("Target arch = '%s'", arch ? arch : "NULL");
if (arch != NULL && !strcmp(arch, "x86")) {
- AFREE(hw->hw_cpu_model);
- hw->hw_cpu_model = ASTRDUP("qemu32");
+ reassign_string(&hw->hw_cpu_model, "qemu32");
D("Auto-config: -qemu -cpu %s", hw->hw_cpu_model);
}
AFREE(arch);
diff --git a/net/net-android.c b/net/net-android.c
index f12e865..23db2f2 100644
--- a/net/net-android.c
+++ b/net/net-android.c
@@ -135,31 +135,6 @@
static VLANState *first_vlan;
-/* see http://en.wikipedia.org/wiki/List_of_device_bandwidths or a complete list */
-const NetworkSpeed android_netspeeds[] = {
- { "gsm", "GSM/CSD", 14400, 14400 },
- { "hscsd", "HSCSD", 14400, 43200 },
- { "gprs", "GPRS", 40000, 80000 },
- { "edge", "EDGE/EGPRS", 118400, 236800 },
- { "umts", "UMTS/3G", 128000, 1920000 },
- { "hsdpa", "HSDPA", 348000, 14400000 },
- { "full", "no limit", 0, 0 },
- { NULL, NULL, 0, 0 }
-};
-const size_t android_netspeeds_count =
- sizeof(android_netspeeds) / sizeof(android_netspeeds[0]);
-
-const NetworkLatency android_netdelays[] = {
- /* FIXME: these numbers are totally imaginary */
- { "gprs", "GPRS", 150, 550 },
- { "edge", "EDGE/EGPRS", 80, 400 },
- { "umts", "UMTS/3G", 35, 200 },
- { "none", "no latency", 0, 0 },
- { NULL, NULL, 0, 0 }
-};
-const size_t android_netdelays_count =
- sizeof(android_netdelays) / sizeof(android_netdelays[0]);
-
/***********************************************************/
/* network device redirectors */