Merge "Add drmrpc group to mediaserver and drmserver so they can make the drm rpc calls"
diff --git a/adb/commandline.c b/adb/commandline.c
index 75f337b..4c15232 100644
--- a/adb/commandline.c
+++ b/adb/commandline.c
@@ -129,18 +129,22 @@
         "  adb bugreport                - return all information from the device\n"
         "                                 that should be included in a bug report.\n"
         "\n"
-        "  adb backup [-f <file>] [-apk|-noapk] [-shared|-noshared] [-all] [<packages...>]\n"
-        "                               - Write an archive of the device's data to <file>.\n"
-        "                                 If a -f option is not supplied then the data is\n"
-        "                                 written to \"backup.ab\" in the current directory.\n"
+        "  adb backup [-f <file>] [-apk|-noapk] [-shared|-noshared] [-all] [-system|-nosystem] [<packages...>]\n"
+        "                               - write an archive of the device's data to <file>.\n"
+        "                                 If no -f option is supplied then the data is written\n"
+        "                                 to \"backup.ab\" in the current directory.\n"
         "                                 (-apk|-noapk enable/disable backup of the .apks themselves\n"
         "                                    in the archive; the default is noapk.)\n"
         "                                 (-shared|-noshared enable/disable backup of the device's\n"
         "                                    shared storage / SD card contents; the default is noshared.)\n"
         "                                 (-all means to back up all installed applications)\n"
+        "                                 (-system|-nosystem toggles whether -all automatically includes\n"
+        "                                    system applications; the default is to include system apps)\n"
         "                                 (<packages...> is the list of applications to be backed up.  If\n"
         "                                    the -all or -shared flags are passed, then the package\n"
-        "                                    list is optional.)\n"
+        "                                    list is optional.  Applications explicitly given on the\n"
+        "                                    command line will be included even if -nosystem would\n"
+        "                                    ordinarily cause them to be omitted.)\n"
         "\n"
         "  adb restore <file>           - restore device contents from the <file> backup archive\n"
         "\n"
@@ -1419,16 +1423,19 @@
         if (*argv[i] != '-') {
             file_arg = i;
             break;
+        } else if (!strcmp(argv[i], "-i")) {
+            // Skip the installer package name.
+            i++;
         } else if (!strcmp(argv[i], "-s")) {
             where = SD_DEST;
         }
     }
 
     if (file_arg < 0) {
-        fprintf(stderr, "can't find filename in arguments");
+        fprintf(stderr, "can't find filename in arguments\n");
         return 1;
     } else if (file_arg + 2 < argc) {
-        fprintf(stderr, "too many files specified; only takes APK file and verifier file");
+        fprintf(stderr, "too many files specified; only takes APK file and verifier file\n");
         return 1;
     }
 
diff --git a/charger/Android.mk b/charger/Android.mk
index 75e78d5..5367a98 100644
--- a/charger/Android.mk
+++ b/charger/Android.mk
@@ -1,5 +1,7 @@
 # Copyright 2011 The Android Open Source Project
 
+ifneq ($(BUILD_TINY_ANDROID),true)
+
 LOCAL_PATH := $(call my-dir)
 include $(CLEAR_VARS)
 
@@ -18,3 +20,31 @@
 LOCAL_STATIC_LIBRARIES += libz libstdc++ libcutils libc
 
 include $(BUILD_EXECUTABLE)
+
+define _add-charger-image
+include $$(CLEAR_VARS)
+LOCAL_MODULE := system_core_charger_$(notdir $(1))
+LOCAL_MODULE_STEM := $(notdir $(1))
+_img_modules += $$(LOCAL_MODULE)
+LOCAL_SRC_FILES := $1
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_PATH := $$(TARGET_ROOT_OUT)/res/images/charger
+include $$(BUILD_PREBUILT)
+endef
+
+_img_modules :=
+_images :=
+$(foreach _img, $(call find-subdir-subdir-files, "images", "*.png"), \
+  $(eval $(call _add-charger-image,$(_img))))
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := charger_res_images
+LOCAL_MODULE_TAGS := optional
+LOCAL_REQUIRED_MODULES := $(_img_modules)
+include $(BUILD_PHONY_PACKAGE)
+
+_add-charger-image :=
+_img_modules :=
+
+endif
diff --git a/charger/charger.c b/charger/charger.c
index 9320e8a..d3b414d 100644
--- a/charger/charger.c
+++ b/charger/charger.c
@@ -37,6 +37,7 @@
 #include <cutils/android_reboot.h>
 #include <cutils/klog.h>
 #include <cutils/list.h>
+#include <cutils/misc.h>
 #include <cutils/uevent.h>
 
 #include "minui/minui.h"
@@ -49,13 +50,20 @@
 #define min(a,b) ((a) < (b) ? (a) : (b))
 #endif
 
+#define ARRAY_SIZE(x)           (sizeof(x)/sizeof(x[0]))
+
 #define MSEC_PER_SEC            (1000LL)
 #define NSEC_PER_MSEC           (1000000LL)
 
-#define SCREEN_ON_TIME          (5 * MSEC_PER_SEC)
+#define BATTERY_UNKNOWN_TIME    (2 * MSEC_PER_SEC)
 #define POWER_ON_KEY_TIME       (2 * MSEC_PER_SEC)
 #define UNPLUGGED_SHUTDOWN_TIME (10 * MSEC_PER_SEC)
 
+#define BATTERY_FULL_THRESH     95
+
+#define LAST_KMSG_PATH          "/proc/last_kmsg"
+#define LAST_KMSG_MAX_SZ        (32 * 1024)
+
 #define LOGE(x...) do { KLOG_ERROR("charger", x); } while (0)
 #define LOGI(x...) do { KLOG_INFO("charger", x); } while (0)
 #define LOGV(x...) do { KLOG_DEBUG("charger", x); } while (0)
@@ -72,22 +80,46 @@
     char type[32];
     bool online;
     bool valid;
+    char cap_path[PATH_MAX];
+};
+
+struct frame {
+    const char *name;
+    int disp_time;
+    int min_capacity;
+
+    gr_surface surface;
+};
+
+struct animation {
+    bool run;
+
+    struct frame *frames;
+    int cur_frame;
+    int num_frames;
+
+    int cur_cycle;
+    int num_cycles;
+
+    /* current capacity being animated */
+    int capacity;
 };
 
 struct charger {
     int64_t next_screen_transition;
     int64_t next_key_check;
     int64_t next_pwr_check;
-    bool screen_on;
 
     struct key_state keys[KEY_MAX + 1];
-    gr_surface surf_charging;
     int uevent_fd;
 
     struct listnode supplies;
     int num_supplies;
     int num_supplies_online;
 
+    struct animation *batt_anim;
+    gr_surface surf_unknown;
+
     struct power_supply *battery;
 };
 
@@ -100,11 +132,52 @@
     const char *ps_online;
 };
 
+static struct frame batt_anim_frames[] = {
+    {
+        .name = "charger/battery_0",
+        .disp_time = 750,
+        .min_capacity = 0,
+    },
+    {
+        .name = "charger/battery_1",
+        .disp_time = 750,
+        .min_capacity = 20,
+    },
+    {
+        .name = "charger/battery_2",
+        .disp_time = 750,
+        .min_capacity = 40,
+    },
+    {
+        .name = "charger/battery_3",
+        .disp_time = 750,
+        .min_capacity = 60,
+    },
+    {
+        .name = "charger/battery_4",
+        .disp_time = 750,
+        .min_capacity = 80,
+    },
+    {
+        .name = "charger/battery_5",
+        .disp_time = 750,
+        .min_capacity = BATTERY_FULL_THRESH,
+    },
+};
+
+static struct animation battery_animation = {
+    .frames = batt_anim_frames,
+    .num_frames = ARRAY_SIZE(batt_anim_frames),
+    .num_cycles = 3,
+};
+
+static struct charger charger_state = {
+    .batt_anim = &battery_animation,
+};
+
 static int char_width;
 static int char_height;
 
-struct charger charger_state;
-
 /* current time in milliseconds */
 static int64_t curr_time_ms(void)
 {
@@ -119,6 +192,53 @@
     gr_fill(0, 0, gr_fb_width(), gr_fb_height());
 };
 
+#define MAX_KLOG_WRITE_BUF_SZ 256
+
+static void dump_last_kmsg(void)
+{
+    char *buf;
+    char *ptr;
+    unsigned sz = 0;
+    int len;
+
+    LOGI("\n");
+    LOGI("*************** LAST KMSG ***************\n");
+    LOGI("\n");
+    buf = load_file(LAST_KMSG_PATH, &sz);
+    if (!buf || !sz) {
+        LOGI("last_kmsg not found. Cold reset?\n");
+        goto out;
+    }
+
+    len = min(sz, LAST_KMSG_MAX_SZ);
+    ptr = buf + (sz - len);
+
+    while (len > 0) {
+        int cnt = min(len, MAX_KLOG_WRITE_BUF_SZ);
+        char yoink;
+        char *nl;
+
+        nl = memrchr(ptr, '\n', cnt - 1);
+        if (nl)
+            cnt = nl - ptr + 1;
+
+        yoink = ptr[cnt];
+        ptr[cnt] = '\0';
+        KLOG_INFO("", "%s", ptr);
+        ptr[cnt] = yoink;
+
+        len -= cnt;
+        ptr += cnt;
+    }
+
+    free(buf);
+
+out:
+    LOGI("\n");
+    LOGI("************* END LAST KMSG *************\n");
+    LOGI("\n");
+}
+
 static int read_file(const char *path, char *buf, size_t sz)
 {
     int fd;
@@ -169,6 +289,22 @@
     return -1;
 }
 
+static int get_battery_capacity(struct charger *charger)
+{
+    int ret;
+    int batt_cap = -1;
+
+    if (!charger->battery)
+        return -1;
+
+    ret = read_file_int(charger->battery->cap_path, &batt_cap);
+    if (ret < 0 || batt_cap > 100) {
+        batt_cap = -1;
+    }
+
+    return batt_cap;
+}
+
 static struct power_supply *find_supply(struct charger *charger,
                                         const char *name)
 {
@@ -185,7 +321,7 @@
 
 static struct power_supply *add_supply(struct charger *charger,
                                        const char *name, const char *type,
-                                       bool online)
+                                       const char *path, bool online)
 {
     struct power_supply *supply;
 
@@ -195,6 +331,8 @@
 
     strlcpy(supply->name, name, sizeof(supply->name));
     strlcpy(supply->type, type, sizeof(supply->type));
+    snprintf(supply->cap_path, sizeof(supply->cap_path),
+             "/sys/%s/capacity", path);
     supply->online = online;
     list_add_tail(&charger->supplies, &supply->list);
     charger->num_supplies++;
@@ -293,7 +431,8 @@
 
     if (!strcmp(uevent->action, "add")) {
         if (!supply) {
-            supply = add_supply(charger, uevent->ps_name, ps_type, online);
+            supply = add_supply(charger, uevent->ps_name, ps_type, uevent->path,
+                                online);
             if (!supply) {
                 LOGE("cannot add supply '%s' (%s %d)\n", uevent->ps_name,
                      uevent->ps_type, online);
@@ -459,74 +598,151 @@
     gr_color(0xa4, 0xc6, 0x39, 255);
 }
 
-static void redraw_screen(struct charger *charger)
+/* returns the last y-offset of where the surface ends */
+static int draw_surface_centered(struct charger *charger, gr_surface surface)
 {
-    int surf_height;
-    int surf_width;
+    int w;
+    int h;
     int x;
-    int y = 0;
-    int batt_cap;
-    int ret;
-    char cap_string[128];
-    char cap_path[256];
+    int y;
 
-    clear_screen();
+    w = gr_get_width(surface);
+    h = gr_get_height(surface);
+    x = (gr_fb_width() - w) / 2 ;
+    y = (gr_fb_height() - h) / 2 ;
 
-    if (charger->surf_charging) {
-        surf_width = gr_get_width(charger->surf_charging);
-        surf_height = gr_get_height(charger->surf_charging);
-        x = (gr_fb_width() - surf_width) / 2 ;
-        y = (gr_fb_height() - surf_height) / 2 ;
+    LOGV("drawing surface %dx%d+%d+%d\n", w, h, x, y);
+    gr_blit(surface, 0, 0, w, h, x, y);
+    return y + h;
+}
 
-        gr_blit(charger->surf_charging, 0, 0,
-                surf_width, surf_height,
-                x, y);
-        y += surf_height;
+static void draw_unknown(struct charger *charger)
+{
+    int y;
+    if (charger->surf_unknown) {
+        draw_surface_centered(charger, charger->surf_unknown);
     } else {
         android_green();
         y = draw_text("Charging!", -1, -1);
+        draw_text("?\?/100", -1, y + 25);
     }
+}
 
-    cap_string[0] = '\0';
-    if (charger->battery) {
-        ret = snprintf(cap_path, sizeof(cap_path),
-                       "/sys/class/power_supply/%s/capacity",
-                       charger->battery->name);
-        if (ret <= 0)
-            goto done;
-        ret = read_file_int(cap_path, &batt_cap);
-        if (ret >= 0)
-            snprintf(cap_string, sizeof(cap_string), "%d/100", batt_cap);
+static void draw_battery(struct charger *charger)
+{
+    struct animation *batt_anim = charger->batt_anim;
+    struct frame *frame = &batt_anim->frames[batt_anim->cur_frame];
+
+    if (batt_anim->num_frames != 0) {
+        draw_surface_centered(charger, frame->surface);
+        LOGV("drawing frame #%d name=%s min_cap=%d time=%d\n",
+             batt_anim->cur_frame, frame->name, frame->min_capacity,
+             frame->disp_time);
     }
+}
 
-    if (cap_string[0] == '\0')
-        snprintf(cap_string, sizeof(cap_string), "?\?/100");
+static void redraw_screen(struct charger *charger)
+{
+    struct animation *batt_anim = charger->batt_anim;
 
-    y += 25;
-    android_green();
-    draw_text(cap_string, -1, y);
+    clear_screen();
 
-done:
+    /* try to display *something* */
+    if (batt_anim->capacity < 0 || batt_anim->num_frames == 0)
+        draw_unknown(charger);
+    else
+        draw_battery(charger);
     gr_flip();
 }
 
-static void update_screen_state(struct charger *charger, int64_t now,
-                                bool force)
+static void kick_animation(struct animation *anim)
 {
-    if (!force && ((now < charger->next_screen_transition) ||
-                   (charger->next_screen_transition == -1)))
+    anim->run = true;
+}
+
+static void reset_animation(struct animation *anim)
+{
+    anim->cur_cycle = 0;
+    anim->cur_frame = 0;
+    anim->run = false;
+}
+
+static void update_screen_state(struct charger *charger, int64_t now)
+{
+    struct animation *batt_anim = charger->batt_anim;
+    int cur_frame;
+    int disp_time;
+
+    if (!batt_anim->run || now < charger->next_screen_transition)
         return;
 
-    if (!charger->screen_on)
-        charger->next_screen_transition = now + SCREEN_ON_TIME;
-    else
+    /* animation is over, blank screen and leave */
+    if (batt_anim->cur_cycle == batt_anim->num_cycles) {
+        reset_animation(batt_anim);
         charger->next_screen_transition = -1;
-    charger->screen_on = !charger->screen_on;
+        gr_fb_blank(true);
+        LOGV("[%lld] animation done\n", now);
+        return;
+    }
 
-    gr_fb_blank(!charger->screen_on);
-    if (charger->screen_on)
-        redraw_screen(charger);
-    LOGV("[%lld] screen %s\n", now, charger->screen_on ? "on" : "off");
+    disp_time = batt_anim->frames[batt_anim->cur_frame].disp_time;
+
+    /* animation starting, set up the animation */
+    if (batt_anim->cur_frame == 0) {
+        int batt_cap;
+        int ret;
+
+        LOGV("[%lld] animation starting\n", now);
+        batt_cap = get_battery_capacity(charger);
+        if (batt_cap >= 0 && batt_anim->num_frames != 0) {
+            int i;
+
+            /* find first frame given current capacity */
+            for (i = 1; i < batt_anim->num_frames; i++) {
+                if (batt_cap < batt_anim->frames[i].min_capacity)
+                    break;
+            }
+            batt_anim->cur_frame = i - 1;
+
+            /* show the first frame for twice as long */
+            disp_time = batt_anim->frames[batt_anim->cur_frame].disp_time * 2;
+        }
+
+        batt_anim->capacity = batt_cap;
+    }
+
+    /* unblank the screen  on first cycle */
+    if (batt_anim->cur_cycle == 0)
+        gr_fb_blank(false);
+
+    /* draw the new frame (@ cur_frame) */
+    redraw_screen(charger);
+
+    /* if we don't have anim frames, we only have one image, so just bump
+     * the cycle counter and exit
+     */
+    if (batt_anim->num_frames == 0 || batt_anim->capacity < 0) {
+        LOGV("[%lld] animation missing or unknown battery status\n", now);
+        charger->next_screen_transition = now + BATTERY_UNKNOWN_TIME;
+        batt_anim->cur_cycle++;
+        return;
+    }
+
+    /* schedule next screen transition */
+    charger->next_screen_transition = now + disp_time;
+
+    /* advance frame cntr to the next valid frame
+     * if necessary, advance cycle cntr, and reset frame cntr
+     */
+    batt_anim->cur_frame++;
+    if (batt_anim->cur_frame == batt_anim->num_frames) {
+        batt_anim->cur_cycle++;
+        batt_anim->cur_frame = 0;
+
+        /* don't reset the cycle counter, since we use that as a signal
+         * in a test above to check if animation is over
+         */
+    }
 }
 
 static void update_input_state(struct charger *charger,
@@ -585,7 +801,7 @@
         } else {
             /* if the power key got released, force screen state cycle */
             if (key->pending)
-                update_screen_state(charger, now, true);
+                kick_animation(charger->batt_anim);
         }
     }
 
@@ -617,7 +833,7 @@
         /* online supply present, reset shutdown timer if set */
         if (charger->next_pwr_check != -1) {
             LOGI("[%lld] device plugged in: shutdown cancelled\n", now);
-            update_screen_state(charger, now, true);
+            kick_animation(charger->batt_anim);
         }
         charger->next_pwr_check = -1;
     }
@@ -634,8 +850,6 @@
          charger->next_screen_transition, charger->next_key_check,
          charger->next_pwr_check);
 
-    /* TODO: right now it's just screen on/off and keys, but later I'm sure
-     *       there will be animations */
     if (charger->next_screen_transition != -1)
         next_event = charger->next_screen_transition;
     if (charger->next_key_check != -1 && charger->next_key_check < next_event)
@@ -675,9 +889,13 @@
 
         LOGV("[%lld] event_loop()\n", now);
         handle_input_state(charger, now);
-        update_screen_state(charger, now, false);
         handle_power_supply_state(charger, now);
 
+        /* do screen update last in case any of the above want to start
+         * screen transitions (animations, etc)
+         */
+        update_screen_state(charger, now);
+
         wait_next_event(charger, now);
     }
 }
@@ -688,12 +906,17 @@
     struct charger *charger = &charger_state;
     int64_t now = curr_time_ms() - 1;
     int fd;
+    int i;
 
     list_init(&charger->supplies);
 
     klog_init();
     klog_set_level(CHARGER_KLOG_LEVEL);
 
+    dump_last_kmsg();
+
+    LOGI("--------------- STARTING CHARGER MODE ---------------\n");
+
     gr_init();
     gr_font_size(&char_width, &char_height);
 
@@ -707,10 +930,23 @@
     charger->uevent_fd = fd;
     coldboot(charger, "/sys/class/power_supply", "add");
 
-    ret = res_create_surface("charging", &charger->surf_charging);
+    ret = res_create_surface("charger/battery_fail", &charger->surf_unknown);
     if (ret < 0) {
         LOGE("Cannot load image\n");
-        charger->surf_charging = NULL;
+        charger->surf_unknown = NULL;
+    }
+
+    for (i = 0; i < charger->batt_anim->num_frames; i++) {
+        struct frame *frame = &charger->batt_anim->frames[i];
+
+        ret = res_create_surface(frame->name, &frame->surface);
+        if (ret < 0) {
+            LOGE("Cannot load image %s\n", frame->name);
+            /* TODO: free the already allocated surfaces... */
+            charger->batt_anim->num_frames = 0;
+            charger->batt_anim->num_cycles = 1;
+            break;
+        }
     }
 
     gr_fb_blank(true);
@@ -718,7 +954,8 @@
     charger->next_screen_transition = now - 1;
     charger->next_key_check = -1;
     charger->next_pwr_check = -1;
-    charger->screen_on = false;
+    reset_animation(charger->batt_anim);
+    kick_animation(charger->batt_anim);
 
     event_loop(charger);
 
diff --git a/charger/images/battery_0.png b/charger/images/battery_0.png
new file mode 100644
index 0000000..2347074
--- /dev/null
+++ b/charger/images/battery_0.png
Binary files differ
diff --git a/charger/images/battery_1.png b/charger/images/battery_1.png
new file mode 100644
index 0000000..cd34620
--- /dev/null
+++ b/charger/images/battery_1.png
Binary files differ
diff --git a/charger/images/battery_2.png b/charger/images/battery_2.png
new file mode 100644
index 0000000..3e4095e
--- /dev/null
+++ b/charger/images/battery_2.png
Binary files differ
diff --git a/charger/images/battery_3.png b/charger/images/battery_3.png
new file mode 100644
index 0000000..08c1551
--- /dev/null
+++ b/charger/images/battery_3.png
Binary files differ
diff --git a/charger/images/battery_4.png b/charger/images/battery_4.png
new file mode 100644
index 0000000..3a678da
--- /dev/null
+++ b/charger/images/battery_4.png
Binary files differ
diff --git a/charger/images/battery_5.png b/charger/images/battery_5.png
new file mode 100644
index 0000000..d8dc40e
--- /dev/null
+++ b/charger/images/battery_5.png
Binary files differ
diff --git a/charger/images/battery_charge.png b/charger/images/battery_charge.png
new file mode 100644
index 0000000..b501933
--- /dev/null
+++ b/charger/images/battery_charge.png
Binary files differ
diff --git a/charger/images/battery_fail.png b/charger/images/battery_fail.png
new file mode 100644
index 0000000..36fc254
--- /dev/null
+++ b/charger/images/battery_fail.png
Binary files differ
diff --git a/charger/images/charging.png b/charger/images/charging.png
deleted file mode 100644
index 94ce4b1..0000000
--- a/charger/images/charging.png
+++ /dev/null
Binary files differ
diff --git a/include/arch/linux-arm/AndroidConfig.h b/include/arch/linux-arm/AndroidConfig.h
index 83891cd..cae112b 100644
--- a/include/arch/linux-arm/AndroidConfig.h
+++ b/include/arch/linux-arm/AndroidConfig.h
@@ -190,7 +190,7 @@
  * with a memory address.  If not defined, stack crawls will not have symbolic
  * information.
  */
-#define HAVE_DLADDR 0
+#define HAVE_DLADDR 1
 
 /*
  * Defined if we have the cxxabi.h header for demangling C++ symbols.  If
diff --git a/include/netutils/ifc.h b/include/netutils/ifc.h
index 575e72e..67a4a45 100644
--- a/include/netutils/ifc.h
+++ b/include/netutils/ifc.h
@@ -38,9 +38,13 @@
 
 extern int ifc_get_addr(const char *name, in_addr_t *addr);
 extern int ifc_set_addr(const char *name, in_addr_t addr);
-extern int ifc_get_prefixLength(const char *name, uint32_t *prefixLength);
-extern int ifc_set_prefixLength(const char *name, uint32_t prefixLength);
+extern int ifc_add_address(const char *name, const char *address,
+                           int prefixlen);
+extern int ifc_del_address(const char *name, const char *address,
+                           int prefixlen);
+extern int ifc_set_prefixLength(const char *name, int prefixLength);
 extern int ifc_set_hwaddr(const char *name, const void *ptr);
+extern int ifc_clear_addresses(const char *name);
 
 /* This function is deprecated. Use ifc_add_route instead. */
 extern int ifc_add_host_route(const char *name, in_addr_t addr);
@@ -53,9 +57,10 @@
 extern int ifc_remove_default_route(const char *ifname);
 extern int ifc_add_route(const char *name, const char *addr, int prefix_length,
                          const char *gw);
-
-extern int ifc_get_info(const char *name, in_addr_t *addr, in_addr_t *mask,
-                        in_addr_t *flags);
+extern int ifc_remove_route(const char *ifname, const char *dst,
+                            int prefix_length, const char *gw);
+extern int ifc_get_info(const char *name, in_addr_t *addr, int *prefixLength,
+                        unsigned *flags);
 
 extern int ifc_configure(const char *ifname, in_addr_t address,
                          uint32_t prefixLength, in_addr_t gateway,
diff --git a/include/system/camera.h b/include/system/camera.h
index 81ce4cb..86b62b7 100644
--- a/include/system/camera.h
+++ b/include/system/camera.h
@@ -105,8 +105,8 @@
      * This does not affect the order of byte array of
      * CAMERA_MSG_PREVIEW_FRAME, CAMERA_MSG_VIDEO_FRAME,
      * CAMERA_MSG_POSTVIEW_FRAME, CAMERA_MSG_RAW_IMAGE, or
-     * CAMERA_MSG_COMPRESSED_IMAGE. This is not allowed to be set during
-     * preview
+     * CAMERA_MSG_COMPRESSED_IMAGE. This is allowed to be set during preview
+     * since API level 14.
      */
     CAMERA_CMD_SET_DISPLAY_ORIENTATION = 3,
 
diff --git a/include/sysutils/SocketClient.h b/include/sysutils/SocketClient.h
index d6bb7d5..7d2b1d6 100644
--- a/include/sysutils/SocketClient.h
+++ b/include/sysutils/SocketClient.h
@@ -8,6 +8,7 @@
 
 class SocketClient {
     int             mSocket;
+    bool            mSocketOwned;
     pthread_mutex_t mWriteMutex;
 
     /* Peer process ID */
@@ -24,8 +25,8 @@
     int mRefCount;
 
 public:
-    SocketClient(int sock);
-    virtual ~SocketClient() {}
+    SocketClient(int sock, bool owned);
+    virtual ~SocketClient();
 
     int getSocket() { return mSocket; }
     pid_t getPid() const { return mPid; }
diff --git a/init/init.c b/init/init.c
index af88f30..7b4a963 100755
--- a/init/init.c
+++ b/init/init.c
@@ -92,7 +92,7 @@
 int add_environment(const char *key, const char *val)
 {
     int n;
- 
+
     for (n = 0; n < 31; n++) {
         if (!ENV[n]) {
             size_t len = strlen(key) + strlen(val) + 2;
@@ -156,7 +156,7 @@
          */
     svc->flags &= (~(SVC_DISABLED|SVC_RESTARTING|SVC_RESET));
     svc->time_started = 0;
-    
+
         /* running processes require no additional work -- if
          * they're in the process of exiting, we've ensured
          * that they will immediately restart on exit, unless
@@ -381,7 +381,7 @@
 
         svc = service_find_by_name(tmp);
     }
-    
+
     if (svc) {
         service_start(svc, args);
     } else {
@@ -455,38 +455,6 @@
     }
 }
 
-static void import_kernel_cmdline(int in_qemu)
-{
-    char cmdline[1024];
-    char *ptr;
-    int fd;
-
-    fd = open("/proc/cmdline", O_RDONLY);
-    if (fd >= 0) {
-        int n = read(fd, cmdline, 1023);
-        if (n < 0) n = 0;
-
-        /* get rid of trailing newline, it happens */
-        if (n > 0 && cmdline[n-1] == '\n') n--;
-
-        cmdline[n] = 0;
-        close(fd);
-    } else {
-        cmdline[0] = 0;
-    }
-
-    ptr = cmdline;
-    while (ptr && *ptr) {
-        char *x = strchr(ptr, ' ');
-        if (x != 0) *x++ = 0;
-        import_kernel_nv(ptr, in_qemu);
-        ptr = x;
-    }
-
-        /* don't expose the raw commandline to nonpriv processes */
-    chmod("/proc/cmdline", 0440);
-}
-
 static struct command *get_first_command(struct action *act)
 {
     struct listnode *node;
@@ -609,7 +577,7 @@
     char tmp[PROP_VALUE_MAX];
 
     if (qemu[0])
-        import_kernel_cmdline(1);
+        import_kernel_cmdline(1, import_kernel_nv);
 
     if (!strcmp(bootmode,"factory"))
         property_set("ro.factorytest", "1");
@@ -729,13 +697,14 @@
          */
     open_devnull_stdio();
     klog_init();
-    
+
     INFO("reading config file\n");
     init_parse_config_file("/init.rc");
 
     /* pull the kernel commandline and ramdisk properties file in */
-    import_kernel_cmdline(0);
-
+    import_kernel_cmdline(0, import_kernel_nv);
+    /* don't expose the raw commandline to nonpriv processes */
+    chmod("/proc/cmdline", 0440);
     get_hardware_name(hardware, &revision);
     snprintf(tmp, sizeof(tmp), "/init.%s.rc", hardware);
     init_parse_config_file(tmp);
diff --git a/init/ueventd.c b/init/ueventd.c
index ddf42be..ecf3b9b 100644
--- a/init/ueventd.c
+++ b/init/ueventd.c
@@ -33,6 +33,20 @@
 static char hardware[32];
 static unsigned revision = 0;
 
+static void import_kernel_nv(char *name, int in_qemu)
+{
+    if (*name != '\0') {
+        char *value = strchr(name, '=');
+        if (value != NULL) {
+            *value++ = 0;
+            if (!strcmp(name,"androidboot.hardware"))
+            {
+                strlcpy(hardware, value, sizeof(hardware));
+            }
+        }
+    }
+}
+
 int ueventd_main(int argc, char **argv)
 {
     struct pollfd ufd;
@@ -51,6 +65,11 @@
 
     INFO("starting ueventd\n");
 
+    /* Respect hardware passed in through the kernel cmd line. Here we will look
+     * for androidboot.hardware param in kernel cmdline, and save its value in
+     * hardware[]. */
+    import_kernel_cmdline(0, import_kernel_nv);
+
     get_hardware_name(hardware, &revision);
 
     ueventd_parse_config_file("/ueventd.rc");
diff --git a/init/util.c b/init/util.c
index fd4bee2..13c9ca2 100755
--- a/init/util.c
+++ b/init/util.c
@@ -399,3 +399,33 @@
         }
     }
 }
+
+void import_kernel_cmdline(int in_qemu,
+                           void (*import_kernel_nv)(char *name, int in_qemu))
+{
+    char cmdline[1024];
+    char *ptr;
+    int fd;
+
+    fd = open("/proc/cmdline", O_RDONLY);
+    if (fd >= 0) {
+        int n = read(fd, cmdline, 1023);
+        if (n < 0) n = 0;
+
+        /* get rid of trailing newline, it happens */
+        if (n > 0 && cmdline[n-1] == '\n') n--;
+
+        cmdline[n] = 0;
+        close(fd);
+    } else {
+        cmdline[0] = 0;
+    }
+
+    ptr = cmdline;
+    while (ptr && *ptr) {
+        char *x = strchr(ptr, ' ');
+        if (x != 0) *x++ = 0;
+        import_kernel_nv(ptr, in_qemu);
+        ptr = x;
+    }
+}
diff --git a/init/util.h b/init/util.h
index 2e47369..9247739 100644
--- a/init/util.h
+++ b/init/util.h
@@ -38,4 +38,5 @@
 int wait_for_file(const char *filename, int timeout);
 void open_devnull_stdio(void);
 void get_hardware_name(char *hardware, unsigned int *revision);
+void import_kernel_cmdline(int in_qemu, void (*import_kernel_nv)(char *name, int in_qemu));
 #endif
diff --git a/libcutils/qtaguid.c b/libcutils/qtaguid.c
index 7e1c42b..994ad32 100644
--- a/libcutils/qtaguid.c
+++ b/libcutils/qtaguid.c
@@ -15,6 +15,8 @@
 ** limitations under the License.
 */
 
+// #define LOG_NDEBUG 0
+
 #define LOG_TAG "qtaguid"
 
 #include <cutils/qtaguid.h>
@@ -58,7 +60,7 @@
 static int write_ctrl(const char *cmd) {
     int fd, res, savedErrno;
 
-    LOGI("write_ctrl(%s)", cmd);
+    LOGV("write_ctrl(%s)", cmd);
 
     fd = TEMP_FAILURE_RETRY(open(CTRL_PROCPATH, O_WRONLY));
     if (fd < 0) {
@@ -105,7 +107,7 @@
 
     snprintf(lineBuf, sizeof(lineBuf), "t %d %llu %d", sockfd, kTag, uid);
 
-    LOGI("Tagging socket %d with tag %llx{%u,0} for uid %d", sockfd, kTag, tag, uid);
+    LOGV("Tagging socket %d with tag %llx{%u,0} for uid %d", sockfd, kTag, tag, uid);
 
     res = write_ctrl(lineBuf);
     if (res < 0) {
@@ -120,7 +122,7 @@
     char lineBuf[CTRL_MAX_INPUT_LEN];
     int res;
 
-    LOGI("Untagging socket %d", sockfd);
+    LOGV("Untagging socket %d", sockfd);
 
     snprintf(lineBuf, sizeof(lineBuf), "u %d", sockfd);
     res = write_ctrl(lineBuf);
@@ -135,7 +137,7 @@
     char lineBuf[CTRL_MAX_INPUT_LEN];
     int res;
 
-    LOGI("Setting counters to set %d for uid %d", counterSetNum, uid);
+    LOGV("Setting counters to set %d for uid %d", counterSetNum, uid);
 
     snprintf(lineBuf, sizeof(lineBuf), "s %d %d", counterSetNum, uid);
     res = write_ctrl(lineBuf);
@@ -147,7 +149,7 @@
     int fd, cnt = 0, res = 0;
     uint64_t kTag = (uint64_t)tag << 32;
 
-    LOGI("Deleting tag data with tag %llx{%d,0} for uid %d", kTag, tag, uid);
+    LOGV("Deleting tag data with tag %llx{%d,0} for uid %d", kTag, tag, uid);
 
     pthread_once(&resTrackInitDone, qtaguid_resTrack);
 
diff --git a/liblog/logprint.c b/liblog/logprint.c
index 4c5b3e5..59fed9b 100644
--- a/liblog/logprint.c
+++ b/liblog/logprint.c
@@ -350,16 +350,28 @@
 int android_log_processLogBuffer(struct logger_entry *buf,
                                  AndroidLogEntry *entry)
 {
-    size_t tag_len;
-
     entry->tv_sec = buf->sec;
     entry->tv_nsec = buf->nsec;
     entry->priority = buf->msg[0];
     entry->pid = buf->pid;
     entry->tid = buf->tid;
+
+    /*
+     * format: <priority:1><tag:N>\0<message:N>\0
+     *
+     * tag str
+     *   starts at msg+1
+     * msg
+     *   starts at msg+1+len(tag)+1
+     */
     entry->tag = buf->msg + 1;
-    tag_len = strlen(entry->tag);
-    entry->messageLen = buf->len - tag_len - 3;
+    const size_t tag_len = strlen(entry->tag);
+    const size_t preambleAndNullLen = tag_len + 3;
+    if (buf->len <= preambleAndNullLen) {
+        fprintf(stderr, "+++ LOG: entry corrupt or truncated\n");
+        return -1;
+    }
+    entry->messageLen = buf->len - preambleAndNullLen;
     entry->message = entry->tag + tag_len + 1;
 
     return 0;
diff --git a/libnetutils/Android.mk b/libnetutils/Android.mk
index 1ef7da9..5f5849f 100644
--- a/libnetutils/Android.mk
+++ b/libnetutils/Android.mk
@@ -6,10 +6,10 @@
         dhcpmsg.c \
         dhcp_utils.c \
         ifc_utils.c \
-	packet.c
+        packet.c
 
 LOCAL_SHARED_LIBRARIES := \
-	libcutils
+        libcutils
 
 LOCAL_MODULE:= libnetutils
 
diff --git a/libnetutils/ifc_utils.c b/libnetutils/ifc_utils.c
index 04b0dfa..0a2f760 100644
--- a/libnetutils/ifc_utils.c
+++ b/libnetutils/ifc_utils.c
@@ -26,15 +26,18 @@
 #include <netinet/in.h>
 #include <arpa/inet.h>
 #include <net/if.h>
+#include <netdb.h>
 
 #include <linux/if.h>
 #include <linux/if_ether.h>
 #include <linux/if_arp.h>
-#include <linux/sockios.h>
+#include <linux/netlink.h>
 #include <linux/route.h>
 #include <linux/ipv6_route.h>
-#include <netdb.h>
-#include <linux/wireless.h>
+#include <linux/rtnetlink.h>
+#include <linux/sockios.h>
+
+#include "netutils/ifc.h"
 
 #ifdef ANDROID
 #define LOG_TAG "NetUtils"
@@ -52,6 +55,8 @@
 void printerr(char *fmt, ...);
 
 #define DBG 0
+#define INET_ADDRLEN 4
+#define INET6_ADDRLEN 16
 
 in_addr_t prefixLengthToIpv4Netmask(int prefix_length)
 {
@@ -88,6 +93,28 @@
     return inet_ntoa(in_addr);
 }
 
+int string_to_ip(const char *string, struct sockaddr_storage *ss) {
+    struct addrinfo hints, *ai;
+    int ret;
+
+    if (ss == NULL) {
+        return -EFAULT;
+    }
+
+    memset(&hints, 0, sizeof(hints));
+    hints.ai_family = AF_UNSPEC;
+    hints.ai_flags = AI_NUMERICHOST;
+    hints.ai_socktype = SOCK_DGRAM;
+
+    ret = getaddrinfo(string, NULL, &hints, &ai);
+    if (ret == 0) {
+        memcpy(ss, ai->ai_addr, ai->ai_addrlen);
+        freeaddrinfo(ai);
+    }
+
+    return ret;
+}
+
 int ifc_init(void)
 {
     int ret;
@@ -209,6 +236,185 @@
     return ret;
 }
 
+/*
+ * Adds or deletes an IP address on an interface.
+ *
+ * Action is one of:
+ * - RTM_NEWADDR (to add a new address)
+ * - RTM_DELADDR (to delete an existing address)
+ *
+ * Returns zero on success and negative errno on failure.
+ */
+int ifc_act_on_address(int action, const char *name, const char *address,
+                       int prefixlen) {
+    int ifindex, s, len, ret;
+    struct sockaddr_storage ss;
+    void *addr;
+    size_t addrlen;
+    struct {
+        struct nlmsghdr n;
+        struct ifaddrmsg r;
+        // Allow for IPv6 address, headers, and padding.
+        char attrbuf[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
+                     NLMSG_ALIGN(sizeof(struct rtattr)) +
+                     NLMSG_ALIGN(INET6_ADDRLEN)];
+    } req;
+    struct rtattr *rta;
+    struct nlmsghdr *nh;
+    struct nlmsgerr *err;
+    char buf[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
+             NLMSG_ALIGN(sizeof(struct nlmsgerr)) +
+             NLMSG_ALIGN(sizeof(struct nlmsghdr))];
+
+    // Get interface ID.
+    ifindex = if_nametoindex(name);
+    if (ifindex == 0) {
+        return -errno;
+    }
+
+    // Convert string representation to sockaddr_storage.
+    ret = string_to_ip(address, &ss);
+    if (ret) {
+        return ret;
+    }
+
+    // Determine address type and length.
+    if (ss.ss_family == AF_INET) {
+        struct sockaddr_in *sin = (struct sockaddr_in *) &ss;
+        addr = &sin->sin_addr;
+        addrlen = INET_ADDRLEN;
+    } else if (ss.ss_family == AF_INET6) {
+        struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) &ss;
+        addr = &sin6->sin6_addr;
+        addrlen = INET6_ADDRLEN;
+    } else {
+        return -EAFNOSUPPORT;
+    }
+
+    // Fill in netlink structures.
+    memset(&req, 0, sizeof(req));
+
+    // Netlink message header.
+    req.n.nlmsg_len = NLMSG_LENGTH(sizeof(req.r));
+    req.n.nlmsg_type = action;
+    req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
+    req.n.nlmsg_pid = getpid();
+
+    // Interface address message header.
+    req.r.ifa_family = ss.ss_family;
+    req.r.ifa_prefixlen = prefixlen;
+    req.r.ifa_index = ifindex;
+
+    // Routing attribute. Contains the actual IP address.
+    rta = (struct rtattr *) (((char *) &req) + NLMSG_ALIGN(req.n.nlmsg_len));
+    rta->rta_type = IFA_LOCAL;
+    rta->rta_len = RTA_LENGTH(addrlen);
+    req.n.nlmsg_len = NLMSG_ALIGN(req.n.nlmsg_len) + RTA_LENGTH(addrlen);
+    memcpy(RTA_DATA(rta), addr, addrlen);
+
+    s = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
+    if (send(s, &req, req.n.nlmsg_len, 0) < 0) {
+        close(s);
+        return -errno;
+    }
+
+    len = recv(s, buf, sizeof(buf), 0);
+    close(s);
+    if (len < 0) {
+        return -errno;
+    }
+
+    // Parse the acknowledgement to find the return code.
+    nh = (struct nlmsghdr *) buf;
+    if (!NLMSG_OK(nh, (unsigned) len) || nh->nlmsg_type != NLMSG_ERROR) {
+        return -EINVAL;
+    }
+    err = NLMSG_DATA(nh);
+
+    // Return code is negative errno.
+    return err->error;
+}
+
+int ifc_add_address(const char *name, const char *address, int prefixlen) {
+    return ifc_act_on_address(RTM_NEWADDR, name, address, prefixlen);
+}
+
+int ifc_del_address(const char *name, const char * address, int prefixlen) {
+    return ifc_act_on_address(RTM_DELADDR, name, address, prefixlen);
+}
+
+/*
+ * Clears IPv6 addresses on the specified interface.
+ */
+int ifc_clear_ipv6_addresses(const char *name) {
+    char rawaddrstr[INET6_ADDRSTRLEN], addrstr[INET6_ADDRSTRLEN];
+    unsigned int prefixlen;
+    int lasterror = 0, i, j, ret;
+    char ifname[64];  // Currently, IFNAMSIZ = 16.
+    FILE *f = fopen("/proc/net/if_inet6", "r");
+    if (!f) {
+        return -errno;
+    }
+
+    // Format:
+    // 20010db8000a0001fc446aa4b5b347ed 03 40 00 01    wlan0
+    while (fscanf(f, "%32s %*02x %02x %*02x %*02x %63s\n",
+                  rawaddrstr, &prefixlen, ifname) == 3) {
+        // Is this the interface we're looking for?
+        if (strcmp(name, ifname)) {
+            continue;
+        }
+
+        // Put the colons back into the address.
+        for (i = 0, j = 0; i < 32; i++, j++) {
+            addrstr[j] = rawaddrstr[i];
+            if (i % 4 == 3) {
+                addrstr[++j] = ':';
+            }
+        }
+        addrstr[j - 1] = '\0';
+
+        // Don't delete the link-local address as well, or it will disable IPv6
+        // on the interface.
+        if (strncmp(addrstr, "fe80:", 5) == 0) {
+            continue;
+        }
+
+        ret = ifc_del_address(ifname, addrstr, prefixlen);
+        if (ret) {
+            LOGE("Deleting address %s/%d on %s: %s", addrstr, prefixlen, ifname,
+                 strerror(-ret));
+            lasterror = ret;
+        }
+    }
+
+    fclose(f);
+    return lasterror;
+}
+
+/*
+ * Clears IPv4 addresses on the specified interface.
+ */
+void ifc_clear_ipv4_addresses(const char *name) {
+    unsigned count, addr;
+    ifc_init();
+    for (count=0, addr=1;((addr != 0) && (count < 255)); count++) {
+        if (ifc_get_addr(name, &addr) < 0)
+            break;
+        if (addr)
+            ifc_set_addr(name, 0);
+    }
+    ifc_close();
+}
+
+/*
+ * Clears all IP addresses on the specified interface.
+ */
+int ifc_clear_addresses(const char *name) {
+    ifc_clear_ipv4_addresses(name);
+    return ifc_clear_ipv6_addresses(name);
+}
+
 int ifc_set_hwaddr(const char *name, const void *ptr)
 {
     int r;
@@ -739,7 +945,7 @@
       struct in_addr gw)
 {
     int i =ifc_act_on_ipv4_route(SIOCADDRT, ifname, dst, prefix_length, gw);
-    printerr("ifc_add_ipv4_route(%s, xx, %d, xx) = %d", ifname, prefix_length, i);
+    if (DBG) printerr("ifc_add_ipv4_route(%s, xx, %d, xx) = %d", ifname, prefix_length, i);
     return i;
 }
 
@@ -755,7 +961,7 @@
 int ifc_add_route(const char *ifname, const char *dst, int prefix_length, const char *gw)
 {
     int i = ifc_act_on_route(SIOCADDRT, ifname, dst, prefix_length, gw);
-    printerr("ifc_add_route(%s, %s, %d, %s) = %d", ifname, dst, prefix_length, gw, i);
+    if (DBG) printerr("ifc_add_route(%s, %s, %d, %s) = %d", ifname, dst, prefix_length, gw, i);
     return i;
 }
 
diff --git a/libnl_2/genl/genl.c b/libnl_2/genl/genl.c
index dd20717..2442993 100644
--- a/libnl_2/genl/genl.c
+++ b/libnl_2/genl/genl.c
@@ -112,6 +112,7 @@
 	nlmhdr.nlmsg_pid = sock->s_local.nl_pid;
 
 	/* Generic netlink header */
+	memset(&gmhhdr, 0, sizeof(gmhhdr));
 	gmhhdr.cmd = CTRL_CMD_GETFAMILY;
 	gmhhdr.version = CTRL_ATTR_FAMILY_ID;
 
@@ -221,9 +222,11 @@
 
 				/* Save the family id */
 				else if (nl80211_flag &&
-					nla->nla_type == CTRL_ATTR_FAMILY_ID)
-					nl80211_genl_id = \
+					nla->nla_type == CTRL_ATTR_FAMILY_ID) {
+					nl80211_genl_id =
 						*((int *)nla_data(nla));
+					nl80211_flag = 0;
+				}
 
 			}
 
diff --git a/libsysutils/src/SocketClient.cpp b/libsysutils/src/SocketClient.cpp
index 90ca52e..722dcb2 100644
--- a/libsysutils/src/SocketClient.cpp
+++ b/libsysutils/src/SocketClient.cpp
@@ -10,8 +10,9 @@
 
 #include <sysutils/SocketClient.h>
 
-SocketClient::SocketClient(int socket)
+SocketClient::SocketClient(int socket, bool owned)
         : mSocket(socket)
+        , mSocketOwned(owned)
         , mPid(-1)
         , mUid(-1)
         , mGid(-1)
@@ -32,6 +33,13 @@
     }
 }
 
+SocketClient::~SocketClient()
+{
+    if (mSocketOwned) {
+        close(mSocket);
+    }
+}
+
 int SocketClient::sendMsg(int code, const char *msg, bool addErrno) {
     char *buf;
     const char* arg;
diff --git a/libsysutils/src/SocketListener.cpp b/libsysutils/src/SocketListener.cpp
index fcad624..3f871ea 100644
--- a/libsysutils/src/SocketListener.cpp
+++ b/libsysutils/src/SocketListener.cpp
@@ -79,7 +79,7 @@
         SLOGE("Unable to listen on socket (%s)", strerror(errno));
         return -1;
     } else if (!mListen)
-        mClients->push_back(new SocketClient(mSock));
+        mClients->push_back(new SocketClient(mSock, false));
 
     if (pipe(mCtrlPipe)) {
         SLOGE("pipe failed (%s)", strerror(errno));
@@ -191,7 +191,7 @@
                 continue;
             }
             pthread_mutex_lock(&mClientsLock);
-            mClients->push_back(new SocketClient(c));
+            mClients->push_back(new SocketClient(c, true));
             pthread_mutex_unlock(&mClientsLock);
         }
 
@@ -225,12 +225,8 @@
                     }
                 }
                 pthread_mutex_unlock(&mClientsLock);
-                /* Destroy the client */
-                int socket = c->getSocket();
-                if (c->decRef()) {
-                    // Note: 'c' is deleted memory at this point.
-                    close(socket);
-                }
+                /* Remove our reference to the client */
+                c->decRef();
             }
         }
     }
diff --git a/logcat/logcat.cpp b/logcat/logcat.cpp
index 96b68ef..4cd2151 100644
--- a/logcat/logcat.cpp
+++ b/logcat/logcat.cpp
@@ -323,7 +323,7 @@
 
                 // the caller requested to just dump the log and exit
                 if (g_nonblock) {
-                    exit(0);
+                    return;
                 }
             } else {
                 // print all that aren't the last in their list
@@ -765,10 +765,10 @@
     }
 
     if (getLogSize) {
-        return 0;
+        exit(0);
     }
     if (clearLog) {
-        return 0;
+        exit(0);
     }
 
     //LOG_EVENT_INT(10, 12345);
diff --git a/netcfg/netcfg.c b/netcfg/netcfg.c
index c520075..3738f24 100644
--- a/netcfg/netcfg.c
+++ b/netcfg/netcfg.c
@@ -50,8 +50,9 @@
 
 int dump_interface(const char *name)
 {
-    unsigned addr, prefixLength, flags;
+    unsigned addr, flags;
     unsigned char hwbuf[ETH_ALEN];
+    int prefixLength;
 
     if(ifc_get_info(name, &addr, &prefixLength, &flags)) {
         return 0;
diff --git a/rootdir/etc/init.goldfish.rc b/rootdir/etc/init.goldfish.rc
index 1ac09ca..83b7f8a 100644
--- a/rootdir/etc/init.goldfish.rc
+++ b/rootdir/etc/init.goldfish.rc
@@ -52,6 +52,18 @@
     group root
     oneshot
 
+# The qemu-props program is used to set various system
+# properties on boot. It must be run early during the boot
+# process to avoid race conditions with other daemons that
+# might read them (e.g. surface flinger), so define it in
+# class 'core'
+#
+service qemu-props /system/bin/qemu-props
+    class core
+    user root
+    group root
+    oneshot
+
 service qemud /system/bin/qemud
     socket qemud    stream 666
     oneshot
diff --git a/rootdir/etc/init.goldfish.sh b/rootdir/etc/init.goldfish.sh
index 1156dd7..ece75b4 100755
--- a/rootdir/etc/init.goldfish.sh
+++ b/rootdir/etc/init.goldfish.sh
@@ -57,10 +57,6 @@
     ;;
 esac
 
-# call 'qemu-props' to set system properties from the emulator.
-#
-/system/bin/qemu-props
-
 # set up the second interface (for inter-emulator connections)
 # if required
 my_ip=`getprop net.shared_net_ip`