aboutsummaryrefslogtreecommitdiffstats
path: root/android
diff options
context:
space:
mode:
authorSiva Velusamy <vsiva@google.com>2012-10-04 17:44:27 -0700
committerChirayu Desai <cdesai@cyanogenmod.org>2013-03-28 20:11:22 +0530
commit2ed75275928cbccd3c30b12856866a61442363ff (patch)
tree19fb4b7bccc165f4071bd1d69a0f69451a1f38f8 /android
parenta546c7006355a7bd1df4267ee53d0bfa2c017c8c (diff)
downloadexternal_qemu-2ed75275928cbccd3c30b12856866a61442363ff.zip
external_qemu-2ed75275928cbccd3c30b12856866a61442363ff.tar.gz
external_qemu-2ed75275928cbccd3c30b12856866a61442363ff.tar.bz2
Support dynamic skin layout
This CL adds support for a skin whose layout section is generated at runtime based on the hardware configuration. Change-Id: I5f81f665b49ce0f3ec5795d922a08b30c1f34b98
Diffstat (limited to 'android')
-rw-r--r--android/cmdline-options.h1
-rw-r--r--android/help.c9
-rw-r--r--android/main-common.c215
3 files changed, 223 insertions, 2 deletions
diff --git a/android/cmdline-options.h b/android/cmdline-options.h
index 5e8d59f..16edeac 100644
--- a/android/cmdline-options.h
+++ b/android/cmdline-options.h
@@ -90,6 +90,7 @@ CFG_PARAM( skindir, "<dir>", "search skins in <dir> (default <system>/skins)" )
CFG_PARAM( skin, "<name>", "select a given skin" )
CFG_FLAG ( no_skin, "don't use any emulator skin" )
CFG_FLAG ( noskin, "same as -no-skin" )
+CFG_FLAG ( dynamic_skin, "dynamically construct a skin of given size, requires -skin WxH option" )
CFG_PARAM( memory, "<size>", "physical RAM size in MBs" )
OPT_PARAM( netspeed, "<speed>", "maximum network download/upload speeds" )
diff --git a/android/help.c b/android/help.c
index 1570160..0a9eed8 100644
--- a/android/help.c
+++ b/android/help.c
@@ -759,6 +759,15 @@ help_skin(stralloc_t* out)
" specify an exact framebuffer size, without any visual ornaments.\n\n" );
}
+static void
+help_dynamic_skin(stralloc_t* out)
+{
+ PRINTF(
+ " use '-dynamic_skin' to dynamically generate a skin based on the settings\n"
+ " in the AVD. This option only has effect if the -skin WxH option is used\n"
+ " to specify the width and height of the framebuffer\n");
+}
+
/* default network settings for emulator */
#define DEFAULT_NETSPEED "full"
#define DEFAULT_NETDELAY "none"
diff --git a/android/main-common.c b/android/main-common.c
index 2d535c7..5c82005 100644
--- a/android/main-common.c
+++ b/android/main-common.c
@@ -321,6 +321,207 @@ void sdl_display_init(DisplayState *ds, int full_screen, int no_frame)
#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,
+ const char* skinDirPath,
+ int width,
+ int height,
+ AConfig* root)
+{
+ char tmp[1024];
+ AConfig* node;
+ int i;
+ int max_part_width;
+
+ if (skinDirPath == NULL)
+ return 0;
+
+ snprintf(tmp, sizeof(tmp), "%s/dynamic", skinDirPath);
+ if (!path_exists(tmp))
+ return 0;
+
+ snprintf(tmp, sizeof(tmp), "%s/dynamic/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 = 3;
+ char* parts[N_PARTS];
+ parts[0] = hwConfig->hw_mainKeys ? "hwkeys_on" : "hwkeys_off";
+ parts[1] = hwConfig->hw_dPad ? "dpad_on" : "dpad_off";
+ parts[2] = 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;
@@ -396,9 +597,19 @@ parse_skin_files(const char* skinDirPath,
if (y && isdigit(y[1])) {
bpp = atoi(y+1);
}
+
+ if (opts->dynamic_skin) {
+ if (load_dynamic_skin(hwConfig, skinDirPath, width, height, root)) {
+ snprintf(tmp, sizeof tmp, "%s/dynamic/", skinDirPath);
+ path = tmp;
+ 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);
+ "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);