am 4f4ccaa1: am 1404c27b: Merge "system/core/init: set proper permissions for tpa2018d1 (CDMA)" into eclair

Merge commit '4f4ccaa1bd079ebc67a97709bbb7ab5ada7449d5'

* commit '4f4ccaa1bd079ebc67a97709bbb7ab5ada7449d5':
  system/core/init: set proper permissions for tpa2018d1 (CDMA)
diff --git a/adb/commandline.c b/adb/commandline.c
index 7cd77e0..5756752 100644
--- a/adb/commandline.c
+++ b/adb/commandline.c
@@ -97,7 +97,7 @@
         "                                 returns an error if more than one emulator is running.\n"
         " -s <serial number>            - directs command to the USB device or emulator with\n"
         "                                 the given serial number. Overrides ANDROID_SERIAL\n"
-        "                                 envivornment variable.\n"
+        "                                 environment variable.\n"
         " -p <product name or path>     - simple product name like 'sooner', or\n"
         "                                 a relative/absolute path to a product\n"
         "                                 out directory like 'out/target/product/sooner'.\n"
@@ -110,7 +110,7 @@
         "\n"
         "device commands:\n"
         "  adb push <local> <remote>    - copy file/dir to device\n"
-        "  adb pull <remote> <local>    - copy file/dir from device\n"
+        "  adb pull <remote> [<local>]  - copy file/dir from device\n"
         "  adb sync [ <directory> ]     - copy host->device only if changed\n"
         "                                 (see 'adb help all')\n"
         "  adb shell                    - run remote shell interactively\n"
@@ -951,10 +951,8 @@
     }
 
     if(!strcmp(argv[0], "bugreport")) {
-        if (argc != 1) {
-            return 1;
-        }
-        do_cmd(ttype, serial, "shell", "dumpstate", "-", 0);
+        if (argc != 1) return usage();
+        do_cmd(ttype, serial, "shell", "bugreport", 0);
         return 0;
     }
 
@@ -1022,8 +1020,13 @@
     }
 
     if(!strcmp(argv[0], "pull")) {
-        if(argc != 3) return usage();
-        return do_sync_pull(argv[1], argv[2]);
+        if (argc == 2) {
+            return do_sync_pull(argv[1], ".");
+        } else if (argc == 3) {
+            return do_sync_pull(argv[1], argv[2]);
+        } else {
+            return usage();
+        }
     }
 
     if(!strcmp(argv[0], "install")) {
diff --git a/adb/usb_linux.c b/adb/usb_linux.c
index 863af1d..66ee317 100644
--- a/adb/usb_linux.c
+++ b/adb/usb_linux.c
@@ -150,13 +150,13 @@
         while((de = readdir(devdir))) {
             unsigned char devdesc[256];
             unsigned char* bufptr = devdesc;
+            unsigned char* bufend;
             struct usb_device_descriptor* device;
             struct usb_config_descriptor* config;
             struct usb_interface_descriptor* interface;
             struct usb_endpoint_descriptor *ep1, *ep2;
             unsigned zero_mask = 0;
             unsigned vid, pid;
-            int i, interfaces;
             size_t desclength;
 
             if(badname(de->d_name)) continue;
@@ -173,6 +173,7 @@
             }
 
             desclength = adb_read(fd, devdesc, sizeof(devdesc));
+            bufend = bufptr + desclength;
 
                 // should have device and configuration descriptors, and atleast two endpoints
             if (desclength < USB_DT_DEVICE_SIZE + USB_DT_CONFIG_SIZE) {
@@ -203,75 +204,73 @@
                 continue;
             }
 
-                // loop through all the interfaces and look for the ADB interface
-            interfaces = config->bNumInterfaces;
-            for (i = 0; i < interfaces; i++) {
-                if (bufptr + USB_DT_ENDPOINT_SIZE > devdesc + desclength)
-                    break;
+                // loop through all the descriptors and look for the ADB interface
+            while (bufptr < bufend) {
+                unsigned char length = bufptr[0];
+                unsigned char type = bufptr[1];
 
-                interface = (struct usb_interface_descriptor *)bufptr;
-                bufptr += USB_DT_INTERFACE_SIZE;
-                if (interface->bLength != USB_DT_INTERFACE_SIZE ||
-                    interface->bDescriptorType != USB_DT_INTERFACE) {
-                    D("usb_interface_descriptor not found\n");
-                    break;
-                }
+                if (type == USB_DT_INTERFACE) {
+                    interface = (struct usb_interface_descriptor *)bufptr;
+                    bufptr += length;
 
-                DBGX("bInterfaceClass: %d,  bInterfaceSubClass: %d,"
-                     "bInterfaceProtocol: %d, bNumEndpoints: %d\n",
-                     interface->bInterfaceClass, interface->bInterfaceSubClass,
-                     interface->bInterfaceProtocol, interface->bNumEndpoints);
-
-                if (interface->bNumEndpoints == 2 &&
-                        is_adb_interface(vid, pid, interface->bInterfaceClass,
-                        interface->bInterfaceSubClass, interface->bInterfaceProtocol))  {
-
-                    DBGX("looking for bulk endpoints\n");
-                        // looks like ADB...
-                    ep1 = (struct usb_endpoint_descriptor *)bufptr;
-                    bufptr += USB_DT_ENDPOINT_SIZE;
-                    ep2 = (struct usb_endpoint_descriptor *)bufptr;
-                    bufptr += USB_DT_ENDPOINT_SIZE;
-
-                    if (bufptr > devdesc + desclength ||
-                        ep1->bLength != USB_DT_ENDPOINT_SIZE ||
-                        ep1->bDescriptorType != USB_DT_ENDPOINT ||
-                        ep2->bLength != USB_DT_ENDPOINT_SIZE ||
-                        ep2->bDescriptorType != USB_DT_ENDPOINT) {
-                        D("endpoints not found\n");
+                    if (length != USB_DT_INTERFACE_SIZE) {
+                        D("interface descriptor has wrong size\n");
                         break;
                     }
 
-                        // both endpoints should be bulk
-                    if (ep1->bmAttributes != USB_ENDPOINT_XFER_BULK ||
-                        ep2->bmAttributes != USB_ENDPOINT_XFER_BULK) {
-                        D("bulk endpoints not found\n");
-                        continue;
+                    DBGX("bInterfaceClass: %d,  bInterfaceSubClass: %d,"
+                         "bInterfaceProtocol: %d, bNumEndpoints: %d\n",
+                         interface->bInterfaceClass, interface->bInterfaceSubClass,
+                         interface->bInterfaceProtocol, interface->bNumEndpoints);
+
+                    if (interface->bNumEndpoints == 2 &&
+                            is_adb_interface(vid, pid, interface->bInterfaceClass,
+                            interface->bInterfaceSubClass, interface->bInterfaceProtocol))  {
+
+                        DBGX("looking for bulk endpoints\n");
+                            // looks like ADB...
+                        ep1 = (struct usb_endpoint_descriptor *)bufptr;
+                        bufptr += USB_DT_ENDPOINT_SIZE;
+                        ep2 = (struct usb_endpoint_descriptor *)bufptr;
+                        bufptr += USB_DT_ENDPOINT_SIZE;
+
+                        if (bufptr > devdesc + desclength ||
+                            ep1->bLength != USB_DT_ENDPOINT_SIZE ||
+                            ep1->bDescriptorType != USB_DT_ENDPOINT ||
+                            ep2->bLength != USB_DT_ENDPOINT_SIZE ||
+                            ep2->bDescriptorType != USB_DT_ENDPOINT) {
+                            D("endpoints not found\n");
+                            break;
+                        }
+
+                            // both endpoints should be bulk
+                        if (ep1->bmAttributes != USB_ENDPOINT_XFER_BULK ||
+                            ep2->bmAttributes != USB_ENDPOINT_XFER_BULK) {
+                            D("bulk endpoints not found\n");
+                            continue;
+                        }
+                            /* aproto 01 needs 0 termination */
+                        if(interface->bInterfaceProtocol == 0x01) {
+                            zero_mask = ep1->wMaxPacketSize - 1;
+                        }
+
+                            // we have a match.  now we just need to figure out which is in and which is out.
+                        if (ep1->bEndpointAddress & USB_ENDPOINT_DIR_MASK) {
+                            local_ep_in = ep1->bEndpointAddress;
+                            local_ep_out = ep2->bEndpointAddress;
+                        } else {
+                            local_ep_in = ep2->bEndpointAddress;
+                            local_ep_out = ep1->bEndpointAddress;
+                        }
+
+                        register_device_callback(devname, local_ep_in, local_ep_out,
+                                interface->bInterfaceNumber, device->iSerialNumber, zero_mask);
+                        break;
                     }
-
-                        /* aproto 01 needs 0 termination */
-                    if(interface->bInterfaceProtocol == 0x01) {
-                        zero_mask = ep1->wMaxPacketSize - 1;
-                    }
-
-                        // we have a match.  now we just need to figure out which is in and which is out.
-                    if (ep1->bEndpointAddress & USB_ENDPOINT_DIR_MASK) {
-                        local_ep_in = ep1->bEndpointAddress;
-                        local_ep_out = ep2->bEndpointAddress;
-                    } else {
-                        local_ep_in = ep2->bEndpointAddress;
-                        local_ep_out = ep1->bEndpointAddress;
-                    }
-
-                    register_device_callback(devname, local_ep_in, local_ep_out,
-                            interface->bInterfaceNumber, device->iSerialNumber, zero_mask);
-
-                    break;
                 } else {
-                    // seek next interface descriptor
-                    bufptr += (USB_DT_ENDPOINT_SIZE * interface->bNumEndpoints);
-                 }
-            } // end of for
+                    bufptr += length;
+                }
+            } // end of while
 
             adb_close(fd);
         } // end of devdir while
diff --git a/adb/usb_vendors.c b/adb/usb_vendors.c
index 9b8c972..73bf418 100644
--- a/adb/usb_vendors.c
+++ b/adb/usb_vendors.c
@@ -55,6 +55,8 @@
 #define VENDOR_ID_FOXCONN       0x0489
 // Dell's USB Vendor ID
 #define VENDOR_ID_DELL          0x413c
+// Nvidia's USB Vendor ID
+#define VENDOR_ID_NVIDIA        0x0955
 // Garmin-Asus's USB Vendor ID
 #define VENDOR_ID_GARMIN_ASUS   0x091E
 
@@ -71,6 +73,7 @@
     VENDOR_ID_SONY_ERICSSON,
     VENDOR_ID_FOXCONN,
     VENDOR_ID_DELL,
+    VENDOR_ID_NVIDIA,
     VENDOR_ID_GARMIN_ASUS,
 };
 
diff --git a/debuggerd/Android.mk b/debuggerd/Android.mk
index b22e1a8..b86f2a5 100644
--- a/debuggerd/Android.mk
+++ b/debuggerd/Android.mk
@@ -14,13 +14,23 @@
 include $(BUILD_EXECUTABLE)
 
 include $(CLEAR_VARS)
-LOCAL_SRC_FILES := crasher.c 
+LOCAL_SRC_FILES := crasher.c
 LOCAL_SRC_FILES += crashglue.S
-LOCAL_MODULE := crasher 
+LOCAL_MODULE := crasher
 LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES)
 LOCAL_MODULE_TAGS := eng
 #LOCAL_FORCE_STATIC_EXECUTABLE := true
 LOCAL_SHARED_LIBRARIES := libcutils libc
 include $(BUILD_EXECUTABLE)
 
+ifeq ($(TARGET_ARCH_VARIANT),armv7-a)
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := vfp-crasher.c vfp.S
+LOCAL_MODULE := vfp-crasher
+LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES)
+LOCAL_MODULE_TAGS := eng
+LOCAL_SHARED_LIBRARIES := libcutils libc
+include $(BUILD_EXECUTABLE)
+endif # TARGET_ARCH_VARIANT == armv7-a
+
 endif # TARGET_ARCH == arm
diff --git a/debuggerd/crashglue.S b/debuggerd/crashglue.S
index 888951b..0c1fd9b 100644
--- a/debuggerd/crashglue.S
+++ b/debuggerd/crashglue.S
@@ -1,5 +1,7 @@
 .globl crash1
+.type crash1, %function
 .globl crashnostack
+.type crashnostack, %function
 		
 crash1:
 	ldr r0, =0xa5a50000
@@ -25,4 +27,4 @@
 	mov sp, #0
 	mov r0, #0
 	ldr r0, [r0]
-	b .
\ No newline at end of file
+	b .
diff --git a/debuggerd/debuggerd.c b/debuggerd/debuggerd.c
index 996e6c2..7b987cf 100644
--- a/debuggerd/debuggerd.c
+++ b/debuggerd/debuggerd.c
@@ -120,7 +120,7 @@
 
 void dump_stack_and_code(int tfd, int pid, mapinfo *map,
                          int unwind_depth, unsigned int sp_list[],
-                         int frame0_pc_sane, bool at_fault)
+                         bool at_fault)
 {
     unsigned int sp, pc, p, end, data;
     struct pt_regs r;
@@ -132,19 +132,11 @@
     sp = r.ARM_sp;
     pc = r.ARM_pc;
 
-    /* Died because calling the weeds - dump
-     * the code around the PC in the next frame instead.
-     */
-    if (frame0_pc_sane == 0) {
-        pc = r.ARM_lr;
-    }
-
-    _LOG(tfd, only_in_tombstone,
-         "\ncode around %s:\n", frame0_pc_sane ? "pc" : "lr");
+    _LOG(tfd, only_in_tombstone, "\ncode around pc:\n");
 
     end = p = pc & ~3;
-    p -= 16;
-    end += 16;
+    p -= 32;
+    end += 32;
 
     /* Dump the code around PC as:
      *  addr       contents
@@ -163,12 +155,12 @@
         _LOG(tfd, only_in_tombstone, "%s\n", code_buffer);
     }
 
-    if (frame0_pc_sane) {
+    if ((unsigned) r.ARM_lr != pc) {
         _LOG(tfd, only_in_tombstone, "\ncode around lr:\n");
 
         end = p = r.ARM_lr & ~3;
-        p -= 16;
-        end += 16;
+        p -= 32;
+        end += 32;
 
         /* Dump the code around LR as:
          *  addr       contents
@@ -285,6 +277,24 @@
     _LOG(tfd, only_in_tombstone,
          " ip %08x  sp %08x  lr %08x  pc %08x  cpsr %08x\n",
          r.ARM_ip, r.ARM_sp, r.ARM_lr, r.ARM_pc, r.ARM_cpsr);
+
+#if __ARM_NEON__
+    struct user_vfp vfp_regs;
+    int i;
+
+    if(ptrace(PTRACE_GETVFPREGS, pid, 0, &vfp_regs)) {
+        _LOG(tfd, only_in_tombstone,
+             "cannot get registers: %s\n", strerror(errno));
+        return;
+    }
+
+    for (i = 0; i < 32; i += 2) {
+        _LOG(tfd, only_in_tombstone,
+             " d%-2d %016llx  d%-2d %016llx\n",
+              i, vfp_regs.fpregs[i], i+1, vfp_regs.fpregs[i+1]);
+    }
+    _LOG(tfd, only_in_tombstone, " scr %08lx\n\n", vfp_regs.fpscr);
+#endif
 }
 
 const char *get_signame(int sig)
@@ -417,8 +427,7 @@
         dump_pc_and_lr(tfd, tid, milist, stack_depth, at_fault);
     }
 
-    dump_stack_and_code(tfd, tid, milist, stack_depth, sp_list, frame0_pc_sane,
-                        at_fault);
+    dump_stack_and_code(tfd, tid, milist, stack_depth, sp_list, at_fault);
 
     while(milist) {
         mapinfo *next = milist->next;
@@ -606,15 +615,16 @@
     (void)tid;
     /* First log a helpful message */
     LOG(    "********************************************************\n"
-            "* process %d crashed. debuggerd waiting for gdbserver   \n"
-            "*                                                       \n"
-            "*     adb shell gdbserver :port --attach %d &           \n"
-            "*                                                       \n"
-            "* and press the HOME key.                               \n"
+            "* Process %d has been suspended while crashing.  To\n"
+            "* attach gdbserver for a gdb connection on port 5039:\n"
+            "*\n"
+            "*     adb shell gdbserver :5039 --attach %d &\n"
+            "*\n"
+            "* Press HOME key to let the process continue crashing.\n"
             "********************************************************\n",
             cr->pid, cr->pid);
 
-    /* wait for HOME key */
+    /* wait for HOME key (TODO: something useful for devices w/o HOME key) */
     if (init_getevent() == 0) {
         int ms = 1200 / 10;
         int dit = 1;
@@ -698,7 +708,7 @@
 
     sprintf(buf,"/proc/%d/task/%d", cr.pid, tid);
     if(stat(buf, &s)) {
-        LOG("tid %d does not exist in pid %d. ignorning debug request\n",
+        LOG("tid %d does not exist in pid %d. ignoring debug request\n",
             tid, cr.pid);
         close(fd);
         return;
diff --git a/debuggerd/vfp-crasher.c b/debuggerd/vfp-crasher.c
new file mode 100644
index 0000000..7a19cdd
--- /dev/null
+++ b/debuggerd/vfp-crasher.c
@@ -0,0 +1,7 @@
+int main()
+{
+  extern void crash(void);
+
+  crash();
+  return 0;
+}
diff --git a/debuggerd/vfp.S b/debuggerd/vfp.S
new file mode 100644
index 0000000..2192415
--- /dev/null
+++ b/debuggerd/vfp.S
@@ -0,0 +1,41 @@
+    .text
+    .align 2
+    .global crash
+    .type crash, %function
+crash:
+    fconstd   d0, #0
+    fconstd   d1, #1
+    fconstd   d2, #2
+    fconstd   d3, #3
+    fconstd   d4, #4
+    fconstd   d5, #5
+    fconstd   d6, #6
+    fconstd   d7, #7
+    fconstd   d8, #8
+    fconstd   d9, #9
+    fconstd   d10, #10
+    fconstd   d11, #11
+    fconstd   d12, #12
+    fconstd   d13, #13
+    fconstd   d14, #14
+    fconstd   d15, #15
+    fconstd   d16, #16
+    fconstd   d17, #17
+    fconstd   d18, #18
+    fconstd   d19, #19
+    fconstd   d20, #20
+    fconstd   d21, #21
+    fconstd   d22, #22
+    fconstd   d23, #23
+    fconstd   d24, #24
+    fconstd   d25, #25
+    fconstd   d26, #26
+    fconstd   d27, #27
+    fconstd   d28, #28
+    fconstd   d29, #29
+    fconstd   d30, #30
+    fconstd   d31, #31
+    mov       r0, #0
+    str       r0, [r0]
+    bx        lr
+
diff --git a/fastboot/fastboot.c b/fastboot/fastboot.c
index 1308f26..aedfce1 100644
--- a/fastboot/fastboot.c
+++ b/fastboot/fastboot.c
@@ -149,8 +149,9 @@
     if(!(vendor_id && (info->dev_vendor == vendor_id)) &&
        (info->dev_vendor != 0x18d1) &&  // Google
        (info->dev_vendor != 0x0451) &&
-       (info->dev_vendor != 0x22b8) &&  // Motorola
        (info->dev_vendor != 0x0502) &&
+       (info->dev_vendor != 0x22b8) &&  // Motorola
+       (info->dev_vendor != 0x0955) &&  // Nvidia
        (info->dev_vendor != 0x413c) &&  // DELL
        (info->dev_vendor != 0x0bb4))    // HTC
             return -1;
@@ -167,6 +168,9 @@
 {
     if (match_fastboot(info) == 0) {
         char* serial = info->serial_number;
+        if (!info->writable) {
+            serial = "no permissions"; // like "adb devices"
+        }
         if (!serial[0]) {
             serial = "????????????";
         }
@@ -556,6 +560,8 @@
         return 0;
     }
 
+    serial = getenv("ANDROID_SERIAL");
+
     while (argc > 0) {
         if(!strcmp(*argv, "-w")) {
             wants_wipe = 1;
diff --git a/fastboot/usb.h b/fastboot/usb.h
index f3ec5bf..cc157d5 100644
--- a/fastboot/usb.h
+++ b/fastboot/usb.h
@@ -50,6 +50,8 @@
     unsigned char has_bulk_in;
     unsigned char has_bulk_out;
     
+    unsigned char writable;
+
     char serial_number[256];
 };
   
diff --git a/fastboot/usb_linux.c b/fastboot/usb_linux.c
index 3b40ba7..2ce53eb 100644
--- a/fastboot/usb_linux.c
+++ b/fastboot/usb_linux.c
@@ -89,7 +89,8 @@
     return 0;
 }
 
-static int filter_usb_device(int fd, char *ptr, int len, ifc_match_func callback,
+static int filter_usb_device(int fd, char *ptr, int len, int writable,
+                             ifc_match_func callback,
                              int *ept_in_id, int *ept_out_id, int *ifc_id)
 {
     struct usb_device_descriptor *dev;
@@ -119,7 +120,8 @@
     info.dev_class = dev->bDeviceClass;
     info.dev_subclass = dev->bDeviceSubClass;
     info.dev_protocol = dev->bDeviceProtocol;
-
+    info.writable = writable;
+    
     // read device serial number (if there is one)
     info.serial_number[0] = 0;
     if (dev->iSerialNumber) {
@@ -201,6 +203,7 @@
     DIR *busdir, *devdir;
     struct dirent *de;
     int fd;
+    int writable;
     
     busdir = opendir(base);
     if(busdir == 0) return 0;
@@ -219,13 +222,20 @@
             sprintf(devname, "%s/%s", busname, de->d_name);
 
 //            DBG("[ scanning %s ]\n", devname);
+            writable = 1;
             if((fd = open(devname, O_RDWR)) < 0) {
-                continue;
+                // Check if we have read-only access, so we can give a helpful
+                // diagnostic like "adb devices" does.
+                writable = 0;
+                if((fd = open(devname, O_RDONLY)) < 0) {
+                    continue;
+                }
             }
 
             n = read(fd, desc, sizeof(desc));
             
-            if(filter_usb_device(fd, desc, n, callback, &in, &out, &ifc) == 0){
+            if(filter_usb_device(fd, desc, n, writable, callback,
+                                 &in, &out, &ifc) == 0) {
                 usb = calloc(1, sizeof(usb_handle));
                 strcpy(usb->fname, devname);
                 usb->ep_in = in;
@@ -375,5 +385,3 @@
 {
     return find_usb_device("/dev/bus/usb", callback);
 }
-
-
diff --git a/fastboot/usb_osx.c b/fastboot/usb_osx.c
index d6a8260..0b0512d 100644
--- a/fastboot/usb_osx.c
+++ b/fastboot/usb_osx.c
@@ -351,6 +351,7 @@
         // device has no serial number
         handle->info.serial_number[0] = 0;
     }
+    handle->info.writable = 1;
 
     if (try_interfaces(dev, handle)) {
         goto error;
@@ -416,8 +417,6 @@
             break;
         }
 
-        usb_ifc_info info;
-
         if (try_device(device, &h) != 0) {
             IOObjectRelease(device);
             ret = -1;
diff --git a/fastboot/usb_windows.c b/fastboot/usb_windows.c
index 9c0a9cb..54008a4 100644
--- a/fastboot/usb_windows.c
+++ b/fastboot/usb_windows.c
@@ -301,6 +301,7 @@
     info.ifc_class = interf_desc.bInterfaceClass;
     info.ifc_subclass = interf_desc.bInterfaceSubClass;
     info.ifc_protocol = interf_desc.bInterfaceProtocol;
+    info.writable = 1;
     
     // read serial number (if there is one)
     unsigned long serial_number_len = sizeof(info.serial_number);
diff --git a/include/android/bitmap.h b/include/android/bitmap.h
new file mode 100644
index 0000000..5078277
--- /dev/null
+++ b/include/android/bitmap.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_BITMAP_H
+#define ANDROID_BITMAP_H
+
+#include <stdint.h>
+#include <jni.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define ANDROID_BITMAP_RESUT_SUCCESS            0
+#define ANDROID_BITMAP_RESULT_BAD_PARAMETER     -1
+#define ANDROID_BITMAP_RESULT_JNI_EXCEPTION     -2
+#define ANDROID_BITMAP_RESULT_ALLOCATION_FAILED -3
+
+enum AndroidBitmapFormat {
+    ANDROID_BITMAP_FORMAT_NONE      = 0,
+    ANDROID_BITMAP_FORMAT_RGBA_8888 = 1,
+    ANDROID_BITMAP_FORMAT_RGB_565   = 4,
+    ANDROID_BITMAP_FORMAT_RGBA_4444 = 7,
+    ANDROID_BITMAP_FORMAT_A_8       = 8,
+};
+
+typedef struct {
+    uint32_t    width;
+    uint32_t    height;
+    uint32_t    stride;
+    int32_t     format;
+    uint32_t    flags;      // 0 for now
+} AndroidBitmapInfo;
+
+/**
+ * Given a java bitmap object, fill out the AndroidBitmap struct for it.
+ * If the call fails, the info parameter will be ignored
+ */
+int AndroidBitmap_getInfo(JNIEnv* env, jobject jbitmap,
+                          AndroidBitmapInfo* info);
+
+/**
+ * Given a java bitmap object, attempt to lock the pixel address.
+ * Locking will ensure that the memory for the pixels will not move
+ * until the unlockPixels call, and ensure that, if the pixels had been
+ * previously purged, they will have been restored.
+ *
+ * If this call succeeds, it must be balanced by a call to
+ * AndroidBitmap_unlockPixels, after which time the address of the pixels should
+ * no longer be used.
+ *
+ * If this succeeds, *addrPtr will be set to the pixel address. If the call
+ * fails, addrPtr will be ignored.
+ */
+int AndroidBitmap_lockPixels(JNIEnv* env, jobject jbitmap, void** addrPtr);
+
+/**
+ * Call this to balanace a successful call to AndroidBitmap_lockPixels
+ */
+int AndroidBitmap_unlockPixels(JNIEnv* env, jobject jbitmap);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/arch/darwin-x86/AndroidConfig.h b/include/arch/darwin-x86/AndroidConfig.h
index 363a8f7..3aa0cd1 100644
--- a/include/arch/darwin-x86/AndroidConfig.h
+++ b/include/arch/darwin-x86/AndroidConfig.h
@@ -256,6 +256,16 @@
 #define HAVE_STRLCPY 1
 
 /*
+ * Define if the open_memstream() function exists on the system.
+ */
+/* #define HAVE_OPEN_MEMSTREAM 1 */
+
+/*
+ * Define if the BSD funopen() function exists on the system.
+ */
+#define HAVE_FUNOPEN 1
+
+/*
  * Define if writev() exists
  */
 #define HAVE_WRITEV 1
diff --git a/include/arch/freebsd-x86/AndroidConfig.h b/include/arch/freebsd-x86/AndroidConfig.h
index b01a854..57d5024 100644
--- a/include/arch/freebsd-x86/AndroidConfig.h
+++ b/include/arch/freebsd-x86/AndroidConfig.h
@@ -295,6 +295,16 @@
 #define HAVE_STRLCPY 1
 
 /*
+ * Define if the open_memstream() function exists on the system.
+ */
+/* #define HAVE_OPEN_MEMSTREAM 1 */
+
+/*
+ * Define if the BSD funopen() function exists on the system.
+ */
+#define HAVE_FUNOPEN 1
+
+/*
  * Define if prctl() exists
  */
 /* #define HAVE_PRCTL 1 */
diff --git a/include/arch/linux-arm/AndroidConfig.h b/include/arch/linux-arm/AndroidConfig.h
index 26547a2..f51ddb1 100644
--- a/include/arch/linux-arm/AndroidConfig.h
+++ b/include/arch/linux-arm/AndroidConfig.h
@@ -298,6 +298,16 @@
 #define HAVE_STRLCPY 1
 
 /*
+ * Define if the open_memstream() function exists on the system.
+ */
+/* #define HAVE_OPEN_MEMSTREAM 1 */
+
+/*
+ * Define if the BSD funopen() function exists on the system.
+ */
+#define HAVE_FUNOPEN 1
+
+/*
  * Define if prctl() exists
  */
 #define HAVE_PRCTL 1
diff --git a/include/arch/linux-sh/AndroidConfig.h b/include/arch/linux-sh/AndroidConfig.h
index 67ac277..5e93990 100644
--- a/include/arch/linux-sh/AndroidConfig.h
+++ b/include/arch/linux-sh/AndroidConfig.h
@@ -303,6 +303,16 @@
 #define HAVE_STRLCPY 1
 
 /*
+ * Define if the open_memstream() function exists on the system.
+ */
+/* #define HAVE_OPEN_MEMSTREAM 1 */
+
+/*
+ * Define if the BSD funopen() function exists on the system.
+ */
+#define HAVE_FUNOPEN 1
+
+/*
  * Define if prctl() exists
  */
 #define HAVE_PRCTL 1
diff --git a/include/arch/linux-x86/AndroidConfig.h b/include/arch/linux-x86/AndroidConfig.h
index 31bdb5f..b0fe90a 100644
--- a/include/arch/linux-x86/AndroidConfig.h
+++ b/include/arch/linux-x86/AndroidConfig.h
@@ -279,6 +279,16 @@
 /* #define HAVE_STRLCPY 1 */
 
 /*
+ * Define if the open_memstream() function exists on the system.
+ */
+#define HAVE_OPEN_MEMSTREAM 1
+
+/*
+ * Define if the BSD funopen() function exists on the system.
+ */
+/* #define HAVE_FUNOPEN 1 */
+
+/*
  * Define if prctl() exists
  */
 #define HAVE_PRCTL 1
diff --git a/include/arch/target_linux-x86/AndroidConfig.h b/include/arch/target_linux-x86/AndroidConfig.h
index d89d054..4db3e72 100644
--- a/include/arch/target_linux-x86/AndroidConfig.h
+++ b/include/arch/target_linux-x86/AndroidConfig.h
@@ -289,6 +289,16 @@
 #define HAVE_STRLCPY 1
 
 /*
+ * Define if the open_memstream() function exists on the system.
+ */
+/* #define HAVE_OPEN_MEMSTREAM 1 */
+
+/*
+ * Define if the BSD funopen() function exists on the system.
+ */
+#define HAVE_FUNOPEN 1
+
+/*
  * Define if prctl() exists
  */
 #define HAVE_PRCTL 1
diff --git a/include/arch/windows/AndroidConfig.h b/include/arch/windows/AndroidConfig.h
index 0fc4955..1b6ece1 100644
--- a/include/arch/windows/AndroidConfig.h
+++ b/include/arch/windows/AndroidConfig.h
@@ -272,6 +272,16 @@
 /* #define HAVE_STRLCPY 1 */
 
 /*
+ * Define if the open_memstream() function exists on the system.
+ */
+/* #define HAVE_OPEN_MEMSTREAM 1 */
+
+/*
+ * Define if the BSD funopen() function exists on the system.
+ */
+/* #define HAVE_FUNOPEN 1 */
+
+/*
  * Define if <winsock2.h> exists.
  * Only MinGW has it.
  */
diff --git a/include/cutils/adb_networking.h b/include/cutils/open_memstream.h
old mode 100755
new mode 100644
similarity index 63%
rename from include/cutils/adb_networking.h
rename to include/cutils/open_memstream.h
index 409d577..b7998be
--- a/include/cutils/adb_networking.h
+++ b/include/cutils/open_memstream.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006 The Android Open Source Project
+ * Copyright (C) 2010 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,22 +14,23 @@
  * limitations under the License.
  */
 
-#ifndef _ADB_NETWORKING_H
-#define _ADB_NETWORKING_H 1
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <sys/socket.h>
+#ifndef __CUTILS_OPEN_MEMSTREAM_H__
+#define __CUTILS_OPEN_MEMSTREAM_H__
+
+#include <stdio.h>
+
+#ifndef HAVE_OPEN_MEMSTREAM
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-extern int adb_networking_connect_fd(int fd, struct sockaddr_in *p_address);
-extern int adb_networking_gethostbyname(const char *name, struct in_addr *p_out_addr);
+FILE* open_memstream(char** bufp, size_t* sizep);
 
 #ifdef __cplusplus
 }
 #endif
 
-#endif /*_ADB_NETWORKING_H*/
+#endif /*!HAVE_OPEN_MEMSTREAM*/
 
+#endif /*__CUTILS_OPEN_MEMSTREAM_H__*/
diff --git a/include/sysutils/NetlinkEvent.h b/include/sysutils/NetlinkEvent.h
index 95e83a3..b329b09 100644
--- a/include/sysutils/NetlinkEvent.h
+++ b/include/sysutils/NetlinkEvent.h
@@ -39,6 +39,8 @@
 
     const char *getSubsystem() { return mSubsystem; }
     int getAction() { return mAction; }
+
+    void dump();
 };
 
 #endif
diff --git a/init/devices.c b/init/devices.c
index 1dffcd4..bde906b 100644
--- a/init/devices.c
+++ b/init/devices.c
@@ -307,8 +307,15 @@
 
     mode = get_device_perm(path, &uid, &gid) | (block ? S_IFBLK : S_IFCHR);
     dev = (major << 8) | minor;
+    /* Temporarily change egid to avoid race condition setting the gid of the
+     * device node. Unforunately changing the euid would prevent creation of
+     * some device nodes, so the uid has to be set with chown() and is still
+     * racy. Fixing the gid race at least fixed the issue with system_server
+     * opening dynamic input devices under the AID_INPUT gid. */
+    setegid(gid);
     mknod(path, mode, dev);
-    chown(path, uid, gid);
+    chown(path, uid, -1);
+    setegid(AID_ROOT);
 }
 
 #if LOG_UEVENTS
diff --git a/init/init.c b/init/init.c
index f76eb36..16a3530 100755
--- a/init/init.c
+++ b/init/init.c
@@ -767,21 +767,31 @@
 void handle_keychord(int fd)
 {
     struct service *svc;
+    char* debuggable;
+    char* adb_enabled;
     int ret;
     __u16 id;
 
-    ret = read(fd, &id, sizeof(id));
-    if (ret != sizeof(id)) {
-        ERROR("could not read keychord id\n");
-        return;
-    }
+    // only handle keychords if ro.debuggable is set or adb is enabled.
+    // the logic here is that bugreports should be enabled in userdebug or eng builds
+    // and on user builds for users that are developers.
+    debuggable = property_get("ro.debuggable");
+    adb_enabled = property_get("init.svc.adbd");
+    if ((debuggable && !strcmp(debuggable, "1")) ||
+        (adb_enabled && !strcmp(adb_enabled, "running"))) {
+        ret = read(fd, &id, sizeof(id));
+        if (ret != sizeof(id)) {
+            ERROR("could not read keychord id\n");
+            return;
+        }
 
-    svc = service_find_by_keychord(id);
-    if (svc) {
-        INFO("starting service %s from keychord\n", svc->name);
-        service_start(svc, NULL);
-    } else {
-        ERROR("service for keychord %d not found\n", id);
+        svc = service_find_by_keychord(id);
+        if (svc) {
+            INFO("starting service %s from keychord\n", svc->name);
+            service_start(svc, NULL);
+        } else {
+            ERROR("service for keychord %d not found\n", id);
+        }
     }
 }
 
@@ -853,10 +863,7 @@
     property_init();
     
     // only listen for keychords if ro.debuggable is true
-    debuggable = property_get("ro.debuggable");
-    if (debuggable && !strcmp(debuggable, "1")) {
-        keychord_fd = open_keychord();
-    }
+    keychord_fd = open_keychord();
 
     if (console[0]) {
         snprintf(tmp, sizeof(tmp), "/dev/%s", console);
diff --git a/init/property_service.c b/init/property_service.c
index 7db7c2c..d2505dd 100644
--- a/init/property_service.c
+++ b/init/property_service.c
@@ -77,6 +77,7 @@
     { "service.adb.root", AID_SHELL,    0 },
     { "persist.sys.",     AID_SYSTEM,   0 },
     { "persist.service.", AID_SYSTEM,   0 },
+    { "persist.security.", AID_SYSTEM,   0 },
     { NULL, 0, 0 }
 };
 
diff --git a/libacc/Android.mk b/libacc/Android.mk
index 2b4998e..5101e16 100644
--- a/libacc/Android.mk
+++ b/libacc/Android.mk
@@ -11,7 +11,7 @@
 
 include $(BUILD_SHARED_LIBRARY)
 
-# Shared library for host
+# Static library for host
 # ========================================================
 
 include $(CLEAR_VARS)
@@ -23,7 +23,7 @@
 LOCAL_STATIC_LIBRARIES := libcutils
 LOCAL_LDLIBS := -ldl
 
-include $(BUILD_HOST_SHARED_LIBRARY)
+include $(BUILD_HOST_STATIC_LIBRARY)
 
 # Build children
 # ========================================================
diff --git a/libacc/FEATURES b/libacc/FEATURES
index 97a876d..20f9d98 100644
--- a/libacc/FEATURES
+++ b/libacc/FEATURES
@@ -21,7 +21,7 @@
 
         * Pointer indirection ('*') is supported.
 
-        * Square brackets can be used for pointer arithmetic.
+        * Square brackets are supported.
 
         * '=' and <op>= are supported.
 
@@ -37,11 +37,14 @@
         + variables can be initialized in declarations.
         + Only ANSI-style function declarations are supported.
            - "..." is not supported.
-        - short is not supported
+        - short is supported
         - const is not supported
-        - arrays are not supported
+        - signed and unsigned are not supported.
+        - arrays are supported
         - long doubles are not supported
-        - structs are not supported
+        - structs and unions are supported
+        - typedef is supported
+        - explicit storage class specifiers are not supported: register, auto, static, extern
 
     - Unknown functions and variables are bound at compile time by calling
       back to the caller. For the 'acc' command-line tool unknown functions
@@ -66,9 +69,12 @@
 
     - Float and double constants are supported.
 
-    - '#define' is supported without function like arguments. No macro
-      recursion is tolerated. Other preprocessor directives are
-      ignored.
+    - '#define' is supported without function like arguments.
+    - Macro recursion is allowed.
+    - Self-referential macros are handled as in gcc.
+    - '#pragma' is supported. The pragma text is passed to a callback function,
+       and is used to implement meta-information.
+    - Other preprocessor directives are ignored.
 
     - C Strings and C character constants are supported. All ANSI C
       character escapes are supported.
diff --git a/libacc/acc.cpp b/libacc/acc.cpp
index 808752e..8f33b0b 100644
--- a/libacc/acc.cpp
+++ b/libacc/acc.cpp
@@ -82,9 +82,7 @@
 
     ~Vector() {
         if (mpBase) {
-            for(size_t i = 0; i < mUsed; i++)  {
-                mpBase[mUsed].~E();
-            }
+            clear();
             free(mpBase);
         }
     }
@@ -110,10 +108,20 @@
         * ensure(1) = item;
     }
 
-    size_t size() {
+    inline size_t size() {
         return mUsed;
     }
 
+    void clear() {
+         if (mpBase) {
+             size_t used = mUsed;
+             for(size_t i = 0; i < used; i++) {
+                 mpBase[i].~E();
+             }
+         }
+         mUsed = 0;
+     }
+
 private:
     E* ensure(int n) {
         size_t newUsed = mUsed + n;
@@ -151,6 +159,7 @@
 class Compiler : public ErrorSink {
     typedef int tokenid_t;
     enum TypeTag {
+        TY_UNKNOWN =     -1,
         TY_INT,       // 0
         TY_CHAR,      // 1
         TY_SHORT,     // 2
@@ -164,8 +173,18 @@
         TY_PARAM      // 10
     };
 
+    enum StorageClass {
+        SC_DEFAULT,  // 0
+        SC_AUTO,     // 1
+        SC_REGISTER, // 2
+        SC_STATIC,   // 3
+        SC_EXTERN,   // 4
+        SC_TYPEDEF   // 5
+    };
+
     struct Type {
         TypeTag tag;
+        StorageClass  storageClass;
         tokenid_t id; // For function arguments, global vars, local vars, struct elements
         tokenid_t structTag; // For structs the name of the struct
         int length; // length of array, offset of struct element. -1 means struct is forward defined
@@ -3898,6 +3917,16 @@
         Vector<Mark> mLevelStack;
     };
 
+    struct MacroState {
+        tokenid_t name; // Name of the current macro we are expanding
+        char* dptr; // point to macro text during macro playback
+        int dch; // Saves old value of ch during a macro playback
+    };
+
+#define MACRO_NESTING_MAX 32
+    MacroState macroState[MACRO_NESTING_MAX];
+    int macroLevel; // -1 means not playing any macro.
+
     int ch; // Current input character, or EOF
     tokenid_t tok;      // token
     intptr_t tokc;    // token extra info
@@ -3909,8 +3938,6 @@
     char* glo;  // global variable index
     String mTokenString;
     bool mbSuppressMacroExpansion;
-    char* dptr; // Macro state: Points to macro text during macro playback.
-    int dch;    // Macro state: Saves old value of ch during a macro playback.
     char* pGlobalBase;
     ACCSymbolLookupFn mpSymbolLookupFn;
     void* mpSymbolLookupContext;
@@ -4018,9 +4045,6 @@
 
     static const int LOCAL = 0x200;
 
-    static const int SYM_FORWARD = 0;
-    static const int SYM_DEFINE = 1;
-
     /* tokens in string heap */
     static const int TAG_TOK = ' ';
 
@@ -4102,11 +4126,17 @@
     }
 
     void inp() {
-        if (dptr) {
-            ch = *dptr++;
+        // Close any totally empty macros. We leave them on the stack until now
+        // so that we know which macros are being expanded when checking if the
+        // last token in the macro is a macro that's already being expanded.
+        while (macroLevel >= 0 && macroState[macroLevel].dptr == NULL) {
+            macroLevel--;
+        }
+        if (macroLevel >= 0) {
+            ch = *macroState[macroLevel].dptr++;
             if (ch == 0) {
-                dptr = 0;
-                ch = dch;
+                ch = macroState[macroLevel].dch;
+                macroState[macroLevel].dptr = NULL; // This macro's done
             }
         } else {
             if (mbBumpLine) {
@@ -4271,6 +4301,15 @@
         // fprintf(stderr, "float constant: %s (%d) %g\n", pText, tok, tokd);
     }
 
+    bool currentlyBeingExpanded(tokenid_t id) {
+        for (int i = 0; i <= macroLevel; i++) {
+            if (macroState[macroLevel].name == id) {
+                return true;
+            }
+        }
+        return false;
+    }
+
     void next() {
         int l, a;
 
@@ -4352,12 +4391,22 @@
             if (! mbSuppressMacroExpansion) {
                 // Is this a macro?
                 char* pMacroDefinition = mTokenTable[tok].mpMacroDefinition;
-                if (pMacroDefinition) {
+                if (pMacroDefinition && !currentlyBeingExpanded(tok)) {
                     // Yes, it is a macro
-                    dptr = pMacroDefinition;
-                    dch = ch;
-                    inp();
-                    next();
+#if 0
+                    printf("Expanding macro %s -> %s",
+                            mTokenString.getUnwrapped(), pMacroDefinition);
+#endif
+                    if (macroLevel >= MACRO_NESTING_MAX-1) {
+                        error("Too many levels of macro recursion.");
+                    } else {
+                        macroLevel++;
+                        macroState[macroLevel].name = tok;
+                        macroState[macroLevel].dptr = pMacroDefinition;
+                        macroState[macroLevel].dch = ch;
+                        inp();
+                        next();
+                    }
                 }
             }
         } else {
@@ -4443,9 +4492,7 @@
         next();
         mbSuppressMacroExpansion = false;
         tokenid_t name = tok;
-        String* pName = new String();
         if (ch == '(') {
-            delete pName;
             error("Defines with arguments not supported");
             return;
         }
@@ -4473,6 +4520,13 @@
         memcpy(pDefn, value.getUnwrapped(), value.len());
         pDefn[value.len()] = 0;
         mTokenTable[name].mpMacroDefinition = pDefn;
+#if 0
+        {
+            String buf;
+            decodeToken(buf, name, true);
+            fprintf(stderr, "define %s = \"%s\"\n", buf.getUnwrapped(), pDefn);
+        }
+#endif
     }
 
     void doPragma() {
@@ -4771,57 +4825,59 @@
                 Type* pDecl = NULL;
                 VariableInfo* pVI = NULL;
                 Type* pFn = pGen->getR0Type();
-                assert(pFn->tag == TY_POINTER);
-                assert(pFn->pHead->tag == TY_FUNC);
-                pDecl = pFn->pHead;
-                pGen->pushR0();
-                Type* pArgList = pDecl->pTail;
-                bool varArgs = pArgList == NULL;
-                /* push args and invert order */
-                a = pGen->beginFunctionCallArguments();
-                int l = 0;
-                int argCount = 0;
-                while (tok != ')' && tok != EOF) {
-                    if (! varArgs && !pArgList) {
-                        error("Unexpected argument.");
-                    }
-                    expr();
-                    pGen->forceR0RVal();
-                    Type* pTargetType;
-                    if (pArgList) {
-                        pTargetType = pArgList->pHead;
-                        pArgList = pArgList->pTail;
-                    } else {
-                        // This is a ... function, just pass arguments in their
-                        // natural type.
-                        pTargetType = pGen->getR0Type();
-                        if (pTargetType->tag == TY_FLOAT) {
-                            pTargetType = mkpDouble;
-                        } else if (pTargetType->tag == TY_ARRAY) {
-                            // Pass arrays by pointer.
-                            pTargetType = pTargetType->pTail;
+                if (pFn->tag == TY_POINTER && pFn->pHead->tag == TY_FUNC) {
+                    pDecl = pFn->pHead;
+                    pGen->pushR0();
+                    Type* pArgList = pDecl->pTail;
+                    bool varArgs = pArgList == NULL;
+                    /* push args and invert order */
+                    a = pGen->beginFunctionCallArguments();
+                    int l = 0;
+                    int argCount = 0;
+                    while (tok != ')' && tok != EOF) {
+                        if (! varArgs && !pArgList) {
+                            error("Unexpected argument.");
                         }
+                        expr();
+                        pGen->forceR0RVal();
+                        Type* pTargetType;
+                        if (pArgList) {
+                            pTargetType = pArgList->pHead;
+                            pArgList = pArgList->pTail;
+                        } else {
+                            // This is a ... function, just pass arguments in their
+                            // natural type.
+                            pTargetType = pGen->getR0Type();
+                            if (pTargetType->tag == TY_FLOAT) {
+                                pTargetType = mkpDouble;
+                            } else if (pTargetType->tag == TY_ARRAY) {
+                                // Pass arrays by pointer.
+                                pTargetType = pTargetType->pTail;
+                            }
+                        }
+                        if (pTargetType->tag == TY_VOID) {
+                            error("Can't pass void value for argument %d",
+                                  argCount + 1);
+                        } else {
+                            l += pGen->storeR0ToArg(l, pTargetType);
+                        }
+                        if (accept(',')) {
+                            // fine
+                        } else if ( tok != ')') {
+                            error("Expected ',' or ')'");
+                        }
+                        argCount += 1;
                     }
-                    if (pTargetType->tag == TY_VOID) {
-                        error("Can't pass void value for argument %d",
-                              argCount + 1);
-                    } else {
-                        l += pGen->storeR0ToArg(l, pTargetType);
+                    if (! varArgs && pArgList) {
+                        error("Expected more argument(s). Saw %d", argCount);
                     }
-                    if (accept(',')) {
-                        // fine
-                    } else if ( tok != ')') {
-                        error("Expected ',' or ')'");
-                    }
-                    argCount += 1;
+                    pGen->endFunctionCallArguments(pDecl, a, l);
+                    skip(')');
+                    pGen->callIndirect(l, pDecl);
+                    pGen->adjustStackAfterCall(pDecl, l, true);
+                } else {
+                    error("Expected a function value to left of '('.");
                 }
-                if (! varArgs && pArgList) {
-                    error("Expected more argument(s). Saw %d", argCount);
-                }
-                pGen->endFunctionCallArguments(pDecl, a, l);
-                skip(')');
-                pGen->callIndirect(l, pDecl);
-                pGen->adjustStackAfterCall(pDecl, l, true);
             } else {
                 break;
             }
@@ -4957,11 +5013,11 @@
         return pGen->gtst(0, 0);
     }
 
-    void block(intptr_t l, bool outermostFunctionBlock) {
+    void block(intptr_t* breakLabel, intptr_t continueAddress, bool outermostFunctionBlock) {
         intptr_t a, n, t;
 
         Type* pBaseType;
-        if ((pBaseType = acceptPrimitiveType())) {
+        if ((pBaseType = acceptPrimitiveType(true))) {
             /* declarations */
             localDeclarations(pBaseType);
         } else if (tok == TOK_IF) {
@@ -4969,12 +5025,12 @@
             skip('(');
             a = test_expr();
             skip(')');
-            block(l, false);
+            block(breakLabel, continueAddress, false);
             if (tok == TOK_ELSE) {
                 next();
                 n = pGen->gjmp(0); /* jmp */
                 pGen->gsym(a);
-                block(l, false);
+                block(breakLabel, continueAddress, false);
                 pGen->gsym(n); /* patch else jmp */
             } else {
                 pGen->gsym(a); /* patch if test */
@@ -5004,7 +5060,7 @@
                 }
             }
             skip(')');
-            block((intptr_t) &a, false);
+            block(&a, n, false);
             pGen->gjmp(n - pCodeBuf->getPC() - pGen->jumpOffset()); /* jmp */
             pGen->gsym(a);
         } else if (tok == '{') {
@@ -5013,7 +5069,7 @@
             }
             next();
             while (tok != '}' && tok != EOF)
-                block(l, false);
+                block(breakLabel, continueAddress, false);
             skip('}');
             if (! outermostFunctionBlock) {
                 mLocals.popLevel();
@@ -5035,7 +5091,17 @@
                 }
                 rsym = pGen->gjmp(rsym); /* jmp */
             } else if (accept(TOK_BREAK)) {
-                *(int *) l = pGen->gjmp(*(int *) l);
+                if (breakLabel) {
+                    *breakLabel = pGen->gjmp(*breakLabel);
+                } else {
+                    error("break statement must be within a for, do, while, or switch statement");
+                }
+            } else if (accept(TOK_CONTINUE)) {
+                if (continueAddress) {
+                    pGen->gjmp(continueAddress - pCodeBuf->getPC() - pGen->jumpOffset());
+                } else {
+                    error("continue statement must be within a for, do, or while statement");
+                }
             } else if (tok != ';')
                 commaExpr();
             skip(';');
@@ -5067,9 +5133,10 @@
     }
 
     Type* createType(TypeTag tag, Type* pHead, Type* pTail) {
-        assert(tag >= TY_INT && tag <= TY_PARAM);
+        assert(tag >= TY_UNKNOWN && tag <= TY_PARAM);
         Type* pType = (Type*) mpCurrentArena->alloc(sizeof(Type));
         memset(pType, 0, sizeof(*pType));
+        pType->storageClass = SC_DEFAULT;
         pType->tag = tag;
         pType->pHead = pHead;
         pType->pTail = pTail;
@@ -5232,38 +5299,124 @@
         fprintf(stderr, "%s\n", buffer.getUnwrapped());
     }
 
-    Type* acceptPrimitiveType() {
-        Type* pType;
-        if (tok == TOK_INT) {
-            pType = mkpInt;
-        } else if (tok == TOK_SHORT) {
-            pType = mkpShort;
-        } else if (tok == TOK_CHAR) {
-            pType = mkpChar;
-        } else if (tok == TOK_VOID) {
-            pType = mkpVoid;
-        } else if (tok == TOK_FLOAT) {
-            pType = mkpFloat;
-        } else if (tok == TOK_DOUBLE) {
-            pType = mkpDouble;
-        } else if (tok == TOK_STRUCT || tok == TOK_UNION) {
-            return acceptStruct();
+    void insertTypeSpecifier(Type** ppType, TypeTag tag) {
+        if (! *ppType) {
+            *ppType = createType(tag, NULL, NULL);
         } else {
-            return NULL;
+            if ((*ppType)->tag != TY_UNKNOWN) {
+                error("Only one type specifier allowed.");
+            } else {
+                (*ppType)->tag = tag;
+            }
         }
-        next();
+    }
+
+    void insertStorageClass(Type** ppType, StorageClass storageClass) {
+        if (! *ppType) {
+            *ppType = createType(TY_UNKNOWN, NULL, NULL);
+        }
+        if ((*ppType)->storageClass != SC_DEFAULT) {
+            error("Only one storage class allowed.");
+        } else {
+            (*ppType)->storageClass = storageClass;
+        }
+    }
+
+    Type* acceptPrimitiveType(bool allowStorageClass) {
+        Type* pType = NULL;
+        for (bool keepGoing = true; keepGoing;) {
+            switch(tok) {
+            case TOK_AUTO:
+                insertStorageClass(&pType, SC_AUTO);
+                break;
+            case TOK_REGISTER:
+                insertStorageClass(&pType, SC_REGISTER);
+                break;
+            case TOK_STATIC:
+                insertStorageClass(&pType, SC_STATIC);
+                break;
+            case TOK_EXTERN:
+                insertStorageClass(&pType, SC_EXTERN);
+                break;
+            case TOK_TYPEDEF:
+                insertStorageClass(&pType, SC_TYPEDEF);
+                break;
+            case TOK_INT:
+                insertTypeSpecifier(&pType, TY_INT);
+                break;
+            case TOK_SHORT:
+                insertTypeSpecifier(&pType, TY_SHORT);
+                break;
+            case TOK_CHAR:
+                insertTypeSpecifier(&pType, TY_CHAR);
+                break;
+            case TOK_VOID:
+                insertTypeSpecifier(&pType, TY_VOID);
+                break;
+            case TOK_FLOAT:
+                insertTypeSpecifier(&pType, TY_FLOAT);
+                break;
+            case TOK_DOUBLE:
+                insertTypeSpecifier(&pType, TY_DOUBLE);
+                break;
+            case TOK_STRUCT:
+            case TOK_UNION:
+            {
+                insertTypeSpecifier(&pType, TY_STRUCT);
+                bool isStruct = (tok == TOK_STRUCT);
+                next();
+                pType = acceptStruct(pType, isStruct);
+                keepGoing = false;
+            }
+                break;
+            default:
+                // Is it a typedef?
+                if (isSymbol(tok)) {
+                    VariableInfo* pV = VI(tok);
+                    if (pV && pV->pType->storageClass == SC_TYPEDEF) {
+                        if (! pType) {
+                            pType = createType(TY_UNKNOWN, NULL, NULL);
+                        }
+                        StorageClass storageClass = pType->storageClass;
+                        *pType = *pV->pType;
+                        pType->storageClass = storageClass;
+                    } else {
+                        keepGoing = false;
+                    }
+                } else {
+                    keepGoing = false;
+                }
+            }
+            if (keepGoing) {
+                next();
+            }
+        }
+        if (pType) {
+            if (pType->tag == TY_UNKNOWN) {
+                pType->tag = TY_INT;
+            }
+            if (allowStorageClass) {
+                switch(pType->storageClass) {
+                case SC_AUTO: error("auto not supported."); break;
+                case SC_REGISTER: error("register not supported."); break;
+                case SC_STATIC: error("static not supported."); break;
+                case SC_EXTERN: error("extern not supported."); break;
+                default: break;
+                }
+            } else {
+                if (pType->storageClass != SC_DEFAULT) {
+                    error("An explicit storage class is not allowed in this type declaration");
+                }
+            }
+        }
         return pType;
     }
 
-    Type* acceptStruct() {
-        assert(tok == TOK_STRUCT || tok == TOK_UNION);
-        bool isStruct = tok == TOK_STRUCT;
-        next();
+    Type* acceptStruct(Type* pStructType, bool isStruct) {
         tokenid_t structTag = acceptSymbol();
         bool isDeclaration = accept('{');
         bool fail = false;
 
-        Type* pStructType = createType(TY_STRUCT, NULL, NULL);
         if (structTag) {
             Token* pToken = &mTokenTable[structTag];
             VariableInfo* pStructInfo = pToken->mpStructInfo;
@@ -5292,9 +5445,11 @@
             if (needToDeclare) {
                 // This is a new struct name
                 pToken->mpStructInfo = mpCurrentSymbolStack->addStructTag(structTag);
+                StorageClass storageClass = pStructType->storageClass;
                 pStructType = createType(TY_STRUCT, NULL, NULL);
                 pStructType->structTag = structTag;
                 pStructType->pHead = pStructType;
+                pStructType->storageClass = storageClass;
                 if (! isDeclaration) {
                     // A forward declaration
                     pStructType->length = -1;
@@ -5312,7 +5467,7 @@
             size_t structAlignment = 0;
             Type** pParamHolder = & pStructType->pHead->pTail;
             while (tok != '}' && tok != EOF) {
-                Type* pPrimitiveType = expectPrimitiveType();
+                Type* pPrimitiveType = expectPrimitiveType(false);
                 if (pPrimitiveType) {
                     while (tok != ';' && tok != EOF) {
                         Type* pItem = acceptDeclaration(pPrimitiveType, true, false);
@@ -5375,6 +5530,7 @@
     Type* acceptDeclaration(Type* pType, bool nameAllowed, bool nameRequired) {
         tokenid_t declName = 0;
         bool reportFailure = false;
+        StorageClass storageClass = pType->storageClass;
         pType = acceptDecl2(pType, declName, nameAllowed,
                                   nameRequired, reportFailure);
         if (declName) {
@@ -5383,6 +5539,7 @@
             pType = createType(pType->tag, pType->pHead, pType->pTail);
             *pType = *pOldType;
             pType->id = declName;
+            pType->storageClass = storageClass;
         } else if (nameRequired) {
             error("Expected a variable name");
         }
@@ -5407,7 +5564,7 @@
 
     /* Used for accepting types that appear in casts */
     Type* acceptCastTypeDeclaration() {
-        Type* pType = acceptPrimitiveType();
+        Type* pType = acceptPrimitiveType(false);
         if (pType) {
             pType = acceptDeclaration(pType, false, false);
         }
@@ -5495,7 +5652,7 @@
         Type* pHead = NULL;
         Type* pTail = NULL;
         for(;;) {
-            Type* pBaseArg = acceptPrimitiveType();
+            Type* pBaseArg = acceptPrimitiveType(false);
             if (pBaseArg) {
                 Type* pArg = acceptDeclaration(pBaseArg, nameAllowed, false);
                 if (pArg) {
@@ -5516,8 +5673,8 @@
         return pHead;
     }
 
-    Type* expectPrimitiveType() {
-        Type* pType = acceptPrimitiveType();
+    Type* expectPrimitiveType(bool allowStorageClass) {
+        Type* pType = acceptPrimitiveType(allowStorageClass);
         if (!pType) {
             String buf;
             decodeToken(buf, tok, true);
@@ -5585,7 +5742,7 @@
                         break;
                     }
                     // Else it's a forward declaration of a function.
-                } else {
+                } else if (pDecl->storageClass != SC_TYPEDEF) {
                     int variableAddress = 0;
                     size_t alignment = pGen->alignmentOf(pDecl);
                     assert(alignment > 0);
@@ -5610,7 +5767,7 @@
                     next();
             }
             skip(';');
-            pBaseType = acceptPrimitiveType();
+            pBaseType = acceptPrimitiveType(true);
         }
     }
 
@@ -5622,8 +5779,12 @@
         if (token == EOF ) {
             buffer.printf("EOF");
         } else if (token == TOK_NUM) {
-            buffer.printf("numeric constant");
-        } else if (token >= 0 && token < 256) {
+            buffer.printf("numeric constant %d(0x%x)", tokc, tokc);
+        } else if (token == TOK_NUM_FLOAT) {
+            buffer.printf("numeric constant float %g", tokd);
+        } else if (token == TOK_NUM_DOUBLE) {
+            buffer.printf("numeric constant double %g", tokd);
+        }  else if (token >= 0 && token < 256) {
             if (token < 32) {
                 buffer.printf("'\\x%02x'", token);
             } else {
@@ -5670,7 +5831,7 @@
     void globalDeclarations() {
         mpCurrentSymbolStack = &mGlobals;
         while (tok != EOF) {
-            Type* pBaseType = expectPrimitiveType();
+            Type* pBaseType = expectPrimitiveType(true);
             if (!pBaseType) {
                 break;
             }
@@ -5687,7 +5848,6 @@
                 skip(';');
                 continue;
             }
-
             if (! isDefined(pDecl->id)) {
                 addGlobalSymbol(pDecl);
             }
@@ -5698,19 +5858,23 @@
             if (pDecl->tag < TY_FUNC) {
                 // it's a variable declaration
                 for(;;) {
-                    if (name && !name->pAddress) {
-                        name->pAddress = (int*) allocGlobalSpace(
-                                                   pGen->alignmentOf(name->pType),
-                                                   pGen->sizeOf(name->pType));
-                    }
-                    if (accept('=')) {
-                        if (tok == TOK_NUM) {
-                            if (name) {
-                                * (int*) name->pAddress = tokc;
+                    if (pDecl->storageClass == SC_TYPEDEF) {
+                        // Do not allocate storage.
+                    } else {
+                        if (name && !name->pAddress) {
+                            name->pAddress = (int*) allocGlobalSpace(
+                                                       pGen->alignmentOf(name->pType),
+                                                       pGen->sizeOf(name->pType));
+                        }
+                        if (accept('=')) {
+                            if (tok == TOK_NUM) {
+                                if (name) {
+                                    * (int*) name->pAddress = tokc;
+                                }
+                                next();
+                            } else {
+                                error("Expected an integer constant");
                             }
-                            next();
-                        } else {
-                            error("Expected an integer constant");
                         }
                     }
                     if (!accept(',')) {
@@ -5763,7 +5927,7 @@
                     rsym = loc = 0;
                     pReturnType = pDecl->pHead;
                     a = pGen->functionEntry(pDecl);
-                    block(0, true);
+                    block(0, 0, true);
                     pGen->gsym(rsym);
                     pGen->functionExit(pDecl, a, loc);
                     mLocals.popLevel();
@@ -5830,8 +5994,7 @@
         rsym = 0;
         loc = 0;
         glo = 0;
-        dptr = 0;
-        dch = 0;
+        macroLevel = -1;
         file = 0;
         pGlobalBase = 0;
         pCodeBuf = 0;
diff --git a/libacc/tests/Android.mk b/libacc/tests/Android.mk
index e9fbe03..6ddfa74 100644
--- a/libacc/tests/Android.mk
+++ b/libacc/tests/Android.mk
@@ -8,9 +8,13 @@
 LOCAL_SRC_FILES:= \
 	main.cpp
 
-LOCAL_SHARED_LIBRARIES := \
-    libacc
+LOCAL_STATIC_LIBRARIES := \
+    libacc \
+    libcutils
 
+LOCAL_LDLIBS := -ldl
+
+    
 LOCAL_MODULE_TAGS := tests
 
 include $(BUILD_HOST_EXECUTABLE)
@@ -25,7 +29,8 @@
     disassem.cpp
 
 LOCAL_SHARED_LIBRARIES := \
-    libacc
+    libacc \
+    libdl
 
 LOCAL_CFLAGS := -O0 -g 
 
@@ -41,8 +46,11 @@
 LOCAL_SRC_FILES:= \
 	runtimeTest.cpp
 
-LOCAL_SHARED_LIBRARIES := \
-    libacc
+LOCAL_STATIC_LIBRARIES := \
+    libacc \
+    libcutils
+
+LOCAL_LDLIBS := -ldl
 
 LOCAL_MODULE_TAGS := tests
 
@@ -57,7 +65,8 @@
 	runtimeTest.cpp
 
 LOCAL_SHARED_LIBRARIES := \
-    libacc
+    libacc \
+    libdl
 
 LOCAL_CFLAGS := -O0 -g 
 
diff --git a/libacc/tests/data/continue.c b/libacc/tests/data/continue.c
new file mode 100644
index 0000000..d8b8e36
--- /dev/null
+++ b/libacc/tests/data/continue.c
@@ -0,0 +1,13 @@
+int main() {
+    int i, j, sum;
+    sum = 0;
+    for (i = 0; i < 10; i++) {
+        if (i & 1) continue;
+        for (j = 0; j < 10; j++) {
+            if (j & 1) continue;
+            sum += i * j;
+        }
+    }
+    return sum;
+}
+
diff --git a/libacc/tests/data/macros.c b/libacc/tests/data/macros.c
new file mode 100644
index 0000000..50e54dc
--- /dev/null
+++ b/libacc/tests/data/macros.c
@@ -0,0 +1,10 @@
+#define A B + B
+#define B C
+
+int main() {
+    int C = 3;
+    printf("A = %d\n", A);
+#define C 5
+    printf("A = %d\n", A);
+    return 0;
+}
diff --git a/libacc/tests/data/typedef.c b/libacc/tests/data/typedef.c
new file mode 100644
index 0000000..c392f6a
--- /dev/null
+++ b/libacc/tests/data/typedef.c
@@ -0,0 +1,40 @@
+typedef short COORD;
+typedef struct Point {
+    COORD x;
+    COORD y;
+} Point;
+
+void add(Point* result, Point* a, Point* b) {
+    result->x = a->x + b->x;
+    result->y = a->y + b->y;
+}
+
+void print(Point* p) {
+    printf("(%d, %d)", p->x, p->y);
+}
+
+void set(Point* p, int x, int y) {
+    p->x = x;
+    p->y = y;
+}
+
+int main() {
+    typedef char* String;
+    String s = "x = %d\n";
+    {
+       typedef int item;
+       item x = 3;
+       printf(s, x);
+    }
+    Point a, b, c;
+    set(&a, 1,2);
+    set(&b, 3,4);
+    add(&c, &a, &b);
+    print(&c);
+    printf(" = ");
+    print(&a);
+    printf(" + ");
+    print(&b);
+    printf("\n");
+    return 0;
+}
diff --git a/libacc/tests/test.py b/libacc/tests/test.py
index d984301..1b444c7 100644
--- a/libacc/tests/test.py
+++ b/libacc/tests/test.py
@@ -10,6 +10,7 @@
 gUseArm = True
 gUseX86 = True
 gRunOTCCOutput = True
+gCompileOTCCANSI = True
 
 
 def parseArgv():
@@ -59,7 +60,12 @@
 
 def checkEnvironment():
     global gRunOTCCOutput
-    gRunOTCCOutput = uname() == "Linux" and unameM() != "x86_64" and outputCanRun()
+    global gCompileOTCCANSI
+    osName = uname()
+    gRunOTCCOutput = osName == "Linux" and unameM() != "x86_64" and outputCanRun()
+    # OSX doesn't have stdin/stdout/stderr accessible through dll load symbols, so
+    # we can't compile the ANSI version of the OTCC compiler on OS X.
+    gCompileOTCCANSI = osName == "Linux"
 
 def adb(args):
     return runCmd(["adb"] + args)
@@ -180,13 +186,19 @@
     def testCompileReturnVal(self):
         self.compileCheck(["data/returnval-ansi.c"], "")
 
-    def testCompileOTCCANSII(self):
-        self.compileCheck(["data/otcc-ansi.c"], "", "", ['x86'])
+    def testCompileOTCCANSI(self):
+        global gCompileOTCCANSI
+        if gCompileOTCCANSI:
+            self.compileCheck(["data/otcc-ansi.c"], "", "", ['x86'])
 
     def testRunReturnVal(self):
         self.compileCheck(["-R", "data/returnval-ansi.c"],
         "Executing compiled code:\nresult: 42\n")
 
+    def testContinue(self):
+        self.compileCheck(["-R", "data/continue.c"],
+        "Executing compiled code:\nresult: 400\n")
+
     def testStringLiteralConcatenation(self):
         self.compileCheck(["-R", "data/testStringConcat.c"],
         "Executing compiled code:\nresult: 13\n", "Hello, world\n")
@@ -311,6 +323,12 @@
 result: 0""", """a = 99, b = 41
 ga = 100, gb = 44""")
 
+    def testTypedef(self):
+        self.compileCheck(["-R", "data/typedef.c"], """Executing compiled code:
+result: 0""", """x = 3
+(4, 6) = (1, 2) + (3, 4)
+""")
+
     def testPointerArithmetic(self):
         self.compileCheck(["-R", "data/pointers.c"], """Executing compiled code:
 result: 0""", """Pointer difference: 1 4
@@ -373,6 +391,12 @@
 Total bad: 0
 """)
 
+    def testMacros(self):
+        self.compileCheck(["-R", "data/macros.c"], """Executing compiled code:
+result: 0""", """A = 6
+A = 10
+""")
+
     def testpointers2(self):
         self.compileCheck(["-R", "data/pointers2.c"], """Executing compiled code:
 result: 0""", """a = 0, *pa = 0
diff --git a/libcutils/Android.mk b/libcutils/Android.mk
index 6418590..93933e2 100644
--- a/libcutils/Android.mk
+++ b/libcutils/Android.mk
@@ -31,6 +31,7 @@
 	config_utils.c \
 	cpu_info.c \
 	load_file.c \
+	open_memstream.c \
 	strdup16to8.c \
 	strdup8to16.c \
 	record_stream.c \
@@ -65,7 +66,6 @@
         mspace.c \
         selector.c \
         tztime.c \
-        adb_networking.c \
         zygote.c
 
     commonHostSources += \
diff --git a/libcutils/adb_networking.c b/libcutils/adb_networking.c
deleted file mode 100644
index d819d44..0000000
--- a/libcutils/adb_networking.c
+++ /dev/null
@@ -1,172 +0,0 @@
-/* libs/utils/adb_networking.c
-**
-** Copyright 2006, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License"); 
-** you may not use this file except in compliance with the License. 
-** You may obtain a copy of the License at 
-**
-**     http://www.apache.org/licenses/LICENSE-2.0 
-**
-** Unless required by applicable law or agreed to in writing, software 
-** distributed under the License is distributed on an "AS IS" BASIS, 
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
-** See the License for the specific language governing permissions and 
-** limitations under the License.
-*/
-
-#define ADB_PORT 5037
-
-#define _GNU_SOURCE     /* for asprintf */
-#include <stdio.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <string.h>
-
-#include <cutils/adb_networking.h>
-#include <cutils/sockets.h>
-#include <cutils/properties.h>
-
-#define ADB_RESPONSE_SIZE 4
-
-/**
- * Unfortunately, java.net.Socket wants to create it's filedescriptor early
- * So, this function takes an fd that must be an unconnected
- * PF_LOCAL SOCK_STREAM
- */
-int adb_networking_connect_fd(int fd, struct sockaddr_in *p_address)
-{
-    struct sockaddr_in local_addr;
-    socklen_t alen;
-    char *cmd;
-    char buf[ADB_RESPONSE_SIZE + 1];
-    ssize_t count_read;
-    int ret;
-    int err;
-    /* for impl of inet_ntoa below*/
-    union {
-        uint8_t  b[4];
-        uint32_t l;
-    } a;
-
-    /* First, connect to adb */
-   
-    memset(&local_addr, 0, sizeof(local_addr));
-    local_addr.sin_family = AF_INET;
-    local_addr.sin_port = htons(ADB_PORT);
-    local_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
-
-    do {
-        err = connect(fd, (struct sockaddr *) &local_addr, sizeof(local_addr));
-    } while (err < 0 && errno == EINTR);
-
-    if (err < 0) {
-        return -1;
-    }
-
-    a.l = p_address->sin_addr.s_addr;
-
-    // compose the command
-    asprintf(&cmd, "tcp:%u:%u.%u.%u.%u", 
-                (unsigned int)ntohs(p_address->sin_port), 
-                a.b[0],a.b[1],a.b[2],a.b[3]);
-
-    // buf is now the ascii hex length of cmd
-    snprintf(buf, sizeof(buf), "%04X", strlen(cmd));
-
-    // write the 4-byte length
-    do {
-        err = write(fd, buf, 4);        
-    } while (err < 0 && errno == EINTR);
-
-    // write the command
-    do {
-        err = write(fd, cmd, strlen(cmd));        
-    } while (err < 0 && errno == EINTR);
-
-    // read the result
-    do {
-        count_read = read(fd, buf, sizeof(buf) - 1);
-    } while (count_read < 0 && errno != EINTR);
-
-    if (count_read == ADB_RESPONSE_SIZE 
-            && 0 == strncmp(buf, "OKAY", ADB_RESPONSE_SIZE)) {
-        ret = 0;
-    } else {
-        /* what errno here? <shrug? */
-        errno = ENETUNREACH;
-        ret = -1;
-    }
-
-    free(cmd);
-    
-    return ret;
-}
-
-/**
- * Fills in *p_out_addr and returns 0 on success
- * Memset's *p_out_addr and returns -1 on fail
- */
-
-int adb_networking_gethostbyname(const char *name, struct in_addr *p_out_addr)
-{
-    int fd;
-    char *cmd = NULL;
-    char buf[ADB_RESPONSE_SIZE + 1];
-    int err;
-    ssize_t count_read;
-    
-    fd = socket_loopback_client(ADB_PORT, SOCK_STREAM);
-
-    if (fd < 0) {
-        return -1;
-    }
-
-    // compose the command
-    asprintf(&cmd, "dns:%s", name);
-
-    // buf is now the ascii hex length of cmd
-    snprintf(buf, sizeof(buf), "%04X", strlen(cmd));
-
-    // write the 4-byte length
-    do {
-        err = write(fd, buf, 4);        
-    } while (err < 0 && errno == EINTR);
-
-    // write the command
-    do {
-        err = write(fd, cmd, strlen(cmd));        
-    } while (err < 0 && errno == EINTR);
-
-    // read the result
-    do {
-        count_read = read(fd, buf, ADB_RESPONSE_SIZE);
-    } while (count_read < 0 && errno != EINTR);
-
-    if (count_read != ADB_RESPONSE_SIZE 
-            || 0 != strncmp(buf, "OKAY", ADB_RESPONSE_SIZE)) {
-        goto error;
-    }
-
-    // read the actual IP address
-    do {
-        count_read = read(fd, &(p_out_addr->s_addr), sizeof(p_out_addr->s_addr));
-    } while (count_read < 0 && errno != EINTR);
-
-    if (count_read != 4) {
-        goto error;
-    }
-
-    free(cmd);
-    close(fd);
-    return 0;
-error:
-    free(cmd);
-    close(fd);
-    memset(p_out_addr, 0, sizeof(struct in_addr));
-    return -1;
-}
-
diff --git a/libcutils/atomic-android-arm.S b/libcutils/atomic-android-arm.S
index da5c26b..1dd2363 100644
--- a/libcutils/atomic-android-arm.S
+++ b/libcutils/atomic-android-arm.S
@@ -24,17 +24,25 @@
 	.align
 	
     .global android_atomic_write
+    .type android_atomic_write, %function
 
 	.global android_atomic_inc
+	.type android_atomic_inc, %function
 	.global android_atomic_dec
+	.type android_atomic_dec, %function
     
 	.global android_atomic_add
+	.type android_atomic_add, %function
 	.global android_atomic_and
+	.type android_atomic_and, %function
 	.global android_atomic_or
+	.type android_atomic_or, %function
     
     .global android_atomic_swap
+    .type android_atomic_swap, %function
 	
 	.global android_atomic_cmpxchg
+	.type android_atomic_cmpxchg, %function
 
 /*
  * ----------------------------------------------------------------------------
diff --git a/libcutils/atomic-android-armv6.S b/libcutils/atomic-android-armv6.S
index a713089..1574c9c 100644
--- a/libcutils/atomic-android-armv6.S
+++ b/libcutils/atomic-android-armv6.S
@@ -19,17 +19,25 @@
     .align
     
     .global android_atomic_write
+    .type android_atomic_write, %function
     
     .global android_atomic_inc
+    .type android_atomic_inc, %function
     .global android_atomic_dec
+    .type android_atomic_dec, %function
     
     .global android_atomic_add
+    .type android_atomic_add, %function
     .global android_atomic_and
+    .type android_atomic_and, %function
     .global android_atomic_or
+    .type android_atomic_or, %function
     
     .global android_atomic_swap
+    .type android_atomic_swap, %function
     
     .global android_atomic_cmpxchg
+    .type android_atomic_cmpxchg, %function
     
 
 
diff --git a/libcutils/mspace.c b/libcutils/mspace.c
index 8fd5de7..2110b43 100644
--- a/libcutils/mspace.c
+++ b/libcutils/mspace.c
@@ -179,7 +179,8 @@
 
   /* Create the mspace, pointing to the memory we just reserved.
    */
-  m = create_mspace_with_base(base + sizeof(*cs), starting_capacity, locked);
+  m = create_mspace_with_base((char *)base + sizeof(*cs), starting_capacity,
+                              locked);
   if (m == (mspace)0)
     goto error;
 
diff --git a/libcutils/open_memstream.c b/libcutils/open_memstream.c
new file mode 100644
index 0000000..5b4388a
--- /dev/null
+++ b/libcutils/open_memstream.c
@@ -0,0 +1,381 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef HAVE_OPEN_MEMSTREAM
+
+/*
+ * Implementation of the POSIX open_memstream() function, which Linux has
+ * but BSD lacks.
+ *
+ * Summary:
+ * - Works like a file-backed FILE* opened with fopen(name, "w"), but the
+ *   backing is a chunk of memory rather than a file.
+ * - The buffer expands as you write more data.  Seeking past the end
+ *   of the file and then writing to it zero-fills the gap.
+ * - The values at "*bufp" and "*sizep" should be considered read-only,
+ *   and are only valid immediately after an fflush() or fclose().
+ * - A '\0' is maintained just past the end of the file. This is not included
+ *   in "*sizep".  (The behavior w.r.t. fseek() is not clearly defined.
+ *   The spec says the null byte is written when a write() advances EOF,
+ *   but it looks like glibc ensures the null byte is always found at EOF,
+ *   even if you just seeked backwards.  The example on the opengroup.org
+ *   page suggests that this is the expected behavior.  The null must be
+ *   present after a no-op fflush(), which we can't see, so we have to save
+ *   and restore it.  Annoying, but allows file truncation.)
+ * - After fclose(), the caller must eventually free(*bufp).
+ *
+ * This is built out of funopen(), which BSD has but Linux lacks.  There is
+ * no flush() operator, so we need to keep the user pointers up to date
+ * after each operation.
+ *
+ * I don't think Windows has any of the above, but we don't need to use
+ * them there, so we just supply a stub.
+ */
+#include <cutils/open_memstream.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+
+#if 0
+# define DBUG(x) printf x
+#else
+# define DBUG(x) ((void)0)
+#endif
+
+#ifdef HAVE_FUNOPEN
+
+/*
+ * Definition of a seekable, write-only memory stream.
+ */
+typedef struct {
+    char**      bufp;       /* pointer to buffer pointer */
+    size_t*     sizep;      /* pointer to eof */
+
+    size_t      allocSize;  /* size of buffer */
+    size_t      eof;        /* furthest point we've written to */
+    size_t      offset;     /* current write offset */
+    char        saved;      /* required by NUL handling */
+} MemStream;
+
+#define kInitialSize    1024
+
+/*
+ * Ensure that we have enough storage to write "size" bytes at the
+ * current offset.  We also have to take into account the extra '\0'
+ * that we maintain just past EOF.
+ *
+ * Returns 0 on success.
+ */
+static int ensureCapacity(MemStream* stream, int writeSize)
+{
+    DBUG(("+++ ensureCap off=%d size=%d\n", stream->offset, writeSize));
+
+    size_t neededSize = stream->offset + writeSize + 1;
+    if (neededSize <= stream->allocSize)
+        return 0;
+
+    size_t newSize;
+
+    if (stream->allocSize == 0) {
+        newSize = kInitialSize;
+    } else {
+        newSize = stream->allocSize;
+        newSize += newSize / 2;             /* expand by 3/2 */
+    }
+
+    if (newSize < neededSize)
+        newSize = neededSize;
+    DBUG(("+++ realloc %p->%p to size=%d\n",
+        stream->bufp, *stream->bufp, newSize));
+    char* newBuf = (char*) realloc(*stream->bufp, newSize);
+    if (newBuf == NULL)
+        return -1;
+
+    *stream->bufp = newBuf;
+    stream->allocSize = newSize;
+    return 0;
+}
+
+/*
+ * Write data to a memstream, expanding the buffer if necessary.
+ *
+ * If we previously seeked beyond EOF, zero-fill the gap.
+ *
+ * Returns the number of bytes written.
+ */
+static int write_memstream(void* cookie, const char* buf, int size)
+{
+    MemStream* stream = (MemStream*) cookie;
+
+    if (ensureCapacity(stream, size) < 0)
+        return -1;
+
+    /* seeked past EOF earlier? */
+    if (stream->eof < stream->offset) {
+        DBUG(("+++ zero-fill gap from %d to %d\n",
+            stream->eof, stream->offset-1));
+        memset(*stream->bufp + stream->eof, '\0',
+            stream->offset - stream->eof);
+    }
+
+    /* copy data, advance write pointer */
+    memcpy(*stream->bufp + stream->offset, buf, size);
+    stream->offset += size;
+
+    if (stream->offset > stream->eof) {
+        /* EOF has advanced, update it and append null byte */
+        DBUG(("+++ EOF advanced to %d, appending nul\n", stream->offset));
+        assert(stream->offset < stream->allocSize);
+        stream->eof = stream->offset;
+    } else {
+        /* within previously-written area; save char we're about to stomp */
+        DBUG(("+++ within written area, saving '%c' at %d\n",
+            *(*stream->bufp + stream->offset), stream->offset));
+        stream->saved = *(*stream->bufp + stream->offset);
+    }
+    *(*stream->bufp + stream->offset) = '\0';
+    *stream->sizep = stream->offset;
+
+    return size;
+}
+
+/*
+ * Seek within a memstream.
+ *
+ * Returns the new offset, or -1 on failure.
+ */
+static fpos_t seek_memstream(void* cookie, fpos_t offset, int whence)
+{
+    MemStream* stream = (MemStream*) cookie;
+    off_t newPosn = (off_t) offset;
+
+    if (whence == SEEK_CUR) {
+        newPosn += stream->offset;
+    } else if (whence == SEEK_END) {
+        newPosn += stream->eof;
+    }
+
+    if (newPosn < 0 || ((fpos_t)((size_t) newPosn)) != newPosn) {
+        /* bad offset - negative or huge */
+        DBUG(("+++ bogus seek offset %ld\n", (long) newPosn));
+        errno = EINVAL;
+        return (fpos_t) -1;
+    }
+
+    if (stream->offset < stream->eof) {
+        /*
+         * We were pointing to an area we'd already written to, which means
+         * we stomped on a character and must now restore it.
+         */
+        DBUG(("+++ restoring char '%c' at %d\n",
+            stream->saved, stream->offset));
+        *(*stream->bufp + stream->offset) = stream->saved;
+    }
+
+    stream->offset = (size_t) newPosn;
+
+    if (stream->offset < stream->eof) {
+        /*
+         * We're seeked backward into the stream.  Preserve the character
+         * at EOF and stomp it with a NUL.
+         */
+        stream->saved = *(*stream->bufp + stream->offset);
+        *(*stream->bufp + stream->offset) = '\0';
+        *stream->sizep = stream->offset;
+    } else {
+        /*
+         * We're positioned at, or possibly beyond, the EOF.  We want to
+         * publish the current EOF, not the current position.
+         */
+        *stream->sizep = stream->eof;
+    }
+
+    return newPosn;
+}
+
+/*
+ * Close the memstream.  We free everything but the data buffer.
+ */
+static int close_memstream(void* cookie)
+{
+    free(cookie);
+    return 0;
+}
+
+/*
+ * Prepare a memstream.
+ */
+FILE* open_memstream(char** bufp, size_t* sizep)
+{
+    FILE* fp;
+    MemStream* stream;
+
+    if (bufp == NULL || sizep == NULL) {
+        errno = EINVAL;
+        return NULL;
+    }
+
+    stream = (MemStream*) calloc(1, sizeof(MemStream));
+    if (stream == NULL)
+        return NULL;
+
+    fp = funopen(stream,
+        NULL, write_memstream, seek_memstream, close_memstream);
+    if (fp == NULL) {
+        free(stream);
+        return NULL;
+    }
+
+    *sizep = 0;
+    *bufp = NULL;
+    stream->bufp = bufp;
+    stream->sizep = sizep;
+
+    return fp;
+}
+
+#else /*not HAVE_FUNOPEN*/
+FILE* open_memstream(char** bufp, size_t* sizep)
+{
+    abort();
+}
+#endif /*HAVE_FUNOPEN*/
+
+
+
+#if 0
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/*
+ * Simple regression test.
+ *
+ * To test on desktop Linux with valgrind, it's possible to make a simple
+ * change to open_memstream() to use fopencookie instead:
+ *
+ *  cookie_io_functions_t iofuncs =
+ *      { NULL, write_memstream, seek_memstream, close_memstream };
+ *  fp = fopencookie(stream, "w", iofuncs);
+ *
+ * (Some tweaks to seek_memstream are also required, as that takes a
+ * pointer to an offset rather than an offset, and returns 0 or -1.)
+ */
+int testMemStream(void)
+{
+    FILE *stream;
+    char *buf;
+    size_t len;
+    off_t eob;
+
+    printf("Test1\n");
+
+    /* std example */
+    stream = open_memstream(&buf, &len);
+    fprintf(stream, "hello my world");
+    fflush(stream);
+    printf("buf=%s, len=%zu\n", buf, len);
+    eob = ftello(stream);
+    fseeko(stream, 0, SEEK_SET);
+    fprintf(stream, "good-bye");
+    fseeko(stream, eob, SEEK_SET);
+    fclose(stream);
+    printf("buf=%s, len=%zu\n", buf, len);
+    free(buf);
+
+    printf("Test2\n");
+
+    /* std example without final seek-to-end */
+    stream = open_memstream(&buf, &len);
+    fprintf(stream, "hello my world");
+    fflush(stream);
+    printf("buf=%s, len=%zu\n", buf, len);
+    eob = ftello(stream);
+    fseeko(stream, 0, SEEK_SET);
+    fprintf(stream, "good-bye");
+    //fseeko(stream, eob, SEEK_SET);
+    fclose(stream);
+    printf("buf=%s, len=%zu\n", buf, len);
+    free(buf);
+
+    printf("Test3\n");
+
+    /* fancy example; should expand buffer with writes */
+    static const int kCmpLen = 1024 + 128;
+    char* cmp = malloc(kCmpLen);
+    memset(cmp, 0, 1024);
+    memset(cmp+1024, 0xff, kCmpLen-1024);
+    sprintf(cmp, "This-is-a-tes1234");
+    sprintf(cmp + 1022, "abcdef");
+
+    stream = open_memstream (&buf, &len);
+    setvbuf(stream, NULL, _IONBF, 0);   /* note: crashes in glibc with this */
+    fprintf(stream, "This-is-a-test");
+    fseek(stream, -1, SEEK_CUR);    /* broken in glibc; can use {13,SEEK_SET} */
+    fprintf(stream, "1234");
+    fseek(stream, 1022, SEEK_SET);
+    fputc('a', stream);
+    fputc('b', stream);
+    fputc('c', stream);
+    fputc('d', stream);
+    fputc('e', stream);
+    fputc('f', stream);
+    fflush(stream);
+
+    if (memcmp(buf, cmp, len+1) != 0) {
+        printf("mismatch\n");
+    } else {
+        printf("match\n");
+    }
+
+    printf("Test4\n");
+    stream = open_memstream (&buf, &len);
+    fseek(stream, 5000, SEEK_SET);
+    fseek(stream, 4096, SEEK_SET);
+    fseek(stream, -1, SEEK_SET);        /* should have no effect */
+    fputc('x', stream);
+    if (ftell(stream) == 4097)
+        printf("good\n");
+    else
+        printf("BAD: offset is %ld\n", ftell(stream));
+
+    printf("DONE\n");
+
+    return 0;
+}
+
+/* expected output:
+Test1
+buf=hello my world, len=14
+buf=good-bye world, len=14
+Test2
+buf=hello my world, len=14
+buf=good-bye, len=8
+Test3
+match
+Test4
+good
+DONE
+*/
+
+#endif
+
+#endif /*!HAVE_OPEN_MEMSTREAM*/
diff --git a/libjnigraphics/Android.mk b/libjnigraphics/Android.mk
new file mode 100644
index 0000000..9458f28
--- /dev/null
+++ b/libjnigraphics/Android.mk
@@ -0,0 +1,35 @@
+BASE_PATH := $(call my-dir)
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_PRELINK_MODULE := false
+
+# setup for skia optimizations
+#
+ifneq ($(ARCH_ARM_HAVE_VFP),true)
+	LOCAL_CFLAGS += -DSK_SOFTWARE_FLOAT
+endif
+
+ifeq ($(ARCH_ARM_HAVE_NEON),true)
+	LOCAL_CFLAGS += -D__ARM_HAVE_NEON
+endif
+
+# our source files
+#
+LOCAL_SRC_FILES:= \
+	bitmap.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+    libandroid_runtime \
+    libskia
+
+LOCAL_C_INCLUDES += \
+	external/skia/include/core \
+	frameworks/base/core/jni/android/graphics \
+    dalvik/libnativehelper/include/nativehelper
+
+LOCAL_MODULE:= libjnigraphics
+
+include $(BUILD_SHARED_LIBRARY)
+
diff --git a/libjnigraphics/bitmap.cpp b/libjnigraphics/bitmap.cpp
new file mode 100644
index 0000000..fd73430
--- /dev/null
+++ b/libjnigraphics/bitmap.cpp
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android/bitmap.h>
+#include <GraphicsJNI.h>
+
+int AndroidBitmap_getInfo(JNIEnv* env, jobject jbitmap,
+                          AndroidBitmapInfo* info) {
+    if (NULL == env || NULL == jbitmap) {
+        return ANDROID_BITMAP_RESULT_BAD_PARAMETER;
+    }
+
+    SkBitmap* bm = GraphicsJNI::getNativeBitmap(env, jbitmap);
+    if (NULL == bm) {
+        return ANDROID_BITMAP_RESULT_JNI_EXCEPTION;
+    }
+
+    if (info) {
+        info->width     = bm->width();
+        info->height    = bm->height();
+        info->stride    = bm->rowBytes();
+        info->flags     = 0;
+
+        switch (bm->config()) {
+            case SkBitmap::kARGB_8888_Config:
+                info->format = ANDROID_BITMAP_FORMAT_RGBA_8888;
+                break;
+            case SkBitmap::kRGB_565_Config:
+                info->format = ANDROID_BITMAP_FORMAT_RGB_565;
+                break;
+            case SkBitmap::kARGB_4444_Config:
+                info->format = ANDROID_BITMAP_FORMAT_RGBA_4444;
+                break;
+            case SkBitmap::kA8_Config:
+                info->format = ANDROID_BITMAP_FORMAT_A_8;
+                break;
+            default:
+                info->format = ANDROID_BITMAP_FORMAT_NONE;
+                break;
+        }
+    }
+    return ANDROID_BITMAP_RESUT_SUCCESS;
+}
+
+int AndroidBitmap_lockPixels(JNIEnv* env, jobject jbitmap, void** addrPtr) {
+    if (NULL == env || NULL == jbitmap) {
+        return ANDROID_BITMAP_RESULT_BAD_PARAMETER;
+    }
+
+    SkBitmap* bm = GraphicsJNI::getNativeBitmap(env, jbitmap);
+    if (NULL == bm) {
+        return ANDROID_BITMAP_RESULT_JNI_EXCEPTION;
+    }
+
+    bm->lockPixels();
+    void* addr = bm->getPixels();
+    if (NULL == addr) {
+        bm->unlockPixels();
+        return ANDROID_BITMAP_RESULT_ALLOCATION_FAILED;
+    }
+
+    if (addrPtr) {
+        *addrPtr = addr;
+    }
+    return ANDROID_BITMAP_RESUT_SUCCESS;
+}
+
+int AndroidBitmap_unlockPixels(JNIEnv* env, jobject jbitmap) {
+    if (NULL == env || NULL == jbitmap) {
+        return ANDROID_BITMAP_RESULT_BAD_PARAMETER;
+    }
+
+    SkBitmap* bm = GraphicsJNI::getNativeBitmap(env, jbitmap);
+    if (NULL == bm) {
+        return ANDROID_BITMAP_RESULT_JNI_EXCEPTION;
+    }
+
+    bm->unlockPixels();
+    return ANDROID_BITMAP_RESUT_SUCCESS;
+}
+
diff --git a/libmincrypt/tools/DumpPublicKey.java b/libmincrypt/tools/DumpPublicKey.java
index c9e7e4d..d2935e0 100644
--- a/libmincrypt/tools/DumpPublicKey.java
+++ b/libmincrypt/tools/DumpPublicKey.java
@@ -77,7 +77,7 @@
         // Write out modulus as little endian array of integers.
         result.append(",{");
         for (int i = 0; i < nwords; ++i) {
-            int n = N.mod(B).intValue();
+            long n = N.mod(B).longValue();
             result.append(n);
 
             if (i != nwords - 1) {
@@ -91,7 +91,7 @@
         // Write R^2 as little endian array of integers.
         result.append(",{");
         for (int i = 0; i < nwords; ++i) {
-            int rr = RR.mod(B).intValue();
+            long rr = RR.mod(B).longValue();
             result.append(rr);
 
             if (i != nwords - 1) {
diff --git a/libnetutils/dhcp_utils.c b/libnetutils/dhcp_utils.c
index bad2e2f..0f8a6c4 100644
--- a/libnetutils/dhcp_utils.c
+++ b/libnetutils/dhcp_utils.c
@@ -24,8 +24,9 @@
 
 #include <cutils/properties.h>
 
-static const char DAEMON_NAME[]       = "dhcpcd";
-static const char DAEMON_PROP_NAME[]  = "init.svc.dhcpcd";
+static const char DAEMON_NAME[]        = "dhcpcd";
+static const char DAEMON_PROP_NAME[]   = "init.svc.dhcpcd";
+static const char HOSTNAME_PROP_NAME[] = "net.hostname";
 static const char DHCP_PROP_NAME_PREFIX[]  = "dhcp";
 static const int  NAP_TIME = 1;   /* wait for 1 second at a time */
                                   /* when polling for property values */
@@ -129,6 +130,7 @@
 {
     char result_prop_name[PROPERTY_KEY_MAX];
     char prop_value[PROPERTY_VALUE_MAX] = {'\0'};
+    char daemon_cmd[PROPERTY_VALUE_MAX * 2];
     const char *ctrl_prop = "ctl.start";
     const char *desired_status = "running";
 
@@ -139,7 +141,13 @@
     property_set(result_prop_name, "");
 
     /* Start the daemon and wait until it's ready */
-    property_set(ctrl_prop, DAEMON_NAME);
+    if (property_get(HOSTNAME_PROP_NAME, prop_value, NULL) && (prop_value[0] != '\0'))
+        snprintf(daemon_cmd, sizeof(daemon_cmd), "%s:-h %s %s", DAEMON_NAME,
+                 prop_value, interface);
+    else
+        snprintf(daemon_cmd, sizeof(daemon_cmd), "%s:%s", DAEMON_NAME, interface);
+    memset(prop_value, '\0', PROPERTY_VALUE_MAX);
+    property_set(ctrl_prop, daemon_cmd);
     if (wait_for_property(DAEMON_PROP_NAME, desired_status, 10) < 0) {
         snprintf(errmsg, sizeof(errmsg), "%s", "Timed out waiting for dhcpcd to start");
         return -1;
diff --git a/libsysutils/src/NetlinkEvent.cpp b/libsysutils/src/NetlinkEvent.cpp
index 5f959a7..1550d83 100644
--- a/libsysutils/src/NetlinkEvent.cpp
+++ b/libsysutils/src/NetlinkEvent.cpp
@@ -46,6 +46,16 @@
     }
 }
 
+void NetlinkEvent::dump() {
+    int i;
+
+    for (i = 0; i < NL_PARAMS_MAX; i++) {
+        if (!mParams[i])
+            break;
+        LOGD("NL param '%s'\n", mParams[i]);
+    }
+}
+
 bool NetlinkEvent::decode(char *buffer, int size) {
     char *s = buffer;
     char *end;
diff --git a/logcat/Android.mk b/logcat/Android.mk
index 5a9f12d..7b8eb01 100644
--- a/logcat/Android.mk
+++ b/logcat/Android.mk
@@ -3,24 +3,10 @@
 LOCAL_PATH:= $(call my-dir)
 include $(CLEAR_VARS)
 
-LOCAL_SRC_FILES:= logcat.cpp
+LOCAL_SRC_FILES:= logcat.cpp event.logtags
 
 LOCAL_SHARED_LIBRARIES := liblog
 
 LOCAL_MODULE:= logcat
 
 include $(BUILD_EXECUTABLE)
-
-########################
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := event-log-tags
-
-# This will install the file in /system/etc
-#
-LOCAL_MODULE_CLASS := ETC
-
-LOCAL_SRC_FILES := $(LOCAL_MODULE)
-LOCAL_PREBUILT_STRIP_COMMENTS := 1
-
-include $(BUILD_PREBUILT)
diff --git a/logcat/event-log-tags b/logcat/event-log-tags
deleted file mode 100644
index 5c4c962..0000000
--- a/logcat/event-log-tags
+++ /dev/null
@@ -1,404 +0,0 @@
-# The entries in this file map a sparse set of log tag numbers to tag names.
-# This is installed on the device, in /system/etc, and parsed by logcat.
-#
-# Tag numbers are decimal integers, from 0 to 2^31.  (Let's leave the
-# negative values alone for now.)
-#
-# Tag names are one or more ASCII letters and numbers or underscores, i.e.
-# "[A-Z][a-z][0-9]_".  Do not include spaces or punctuation (the former
-# impacts log readability, the latter makes regex searches more annoying).
-#
-# Tag numbers and names are separated by whitespace.  Blank lines and lines
-# starting with '#' are ignored.
-#
-# Optionally, after the tag names can be put a description for the value(s)
-# of the tag. Description are in the format
-#    (<name>|data type[|data unit])
-# Multiple values are separated by commas.
-#
-# The data type is a number from the following values:
-# 1: int
-# 2: long
-# 3: string
-# 4: list
-#
-# The data unit is a number taken from the following list:
-# 1: Number of objects
-# 2: Number of bytes
-# 3: Number of milliseconds
-# 4: Number of allocations
-# 5: Id
-# 6: Percent
-# Default value for data of type int/long is 2 (bytes).
-#
-# TODO: generate ".java" and ".h" files with integer constants from this file.
-
-# These are used for testing, do not modify without updating
-# tests/framework-tests/src/android/util/EventLogFunctionalTest.java.
-42    answer (to life the universe etc|3)
-314   pi
-2718  e
-
-2719 configuration_changed (config mask|1|5)
-# "account" is the java hash of the account name
-2720 sync (id|3),(event|1|5),(source|1|5),(account|1|5)
-2721 cpu (total|1|6),(user|1|6),(system|1|6),(iowait|1|6),(irq|1|6),(softirq|1|6)
-2722 battery_level (level|1|6),(voltage|1|1),(temperature|1|1)
-2723 battery_status (status|1|5),(health|1|5),(present|1|5),(plugged|1|5),(technology|3)
-# This is logged when the device is being forced to sleep (typically by
-# the user pressing the power button).
-2724 power_sleep_requested (wakeLocksCleared|1|1)
-# This is logged when the screen on broadcast has completed
-2725 power_screen_broadcast_send (wakelockCount|1|1)
-# This is logged when the screen broadcast has completed
-2726 power_screen_broadcast_done (on|1|5),(broadcastDuration|2|3),(wakelockCount|1|1)
-# This is logged when the screen on broadcast has completed
-2727 power_screen_broadcast_stop (which|1|5),(wakelockCount|1|1)
-# This is logged when the screen is turned on or off.
-2728 power_screen_state (offOrOn|1|5),(becauseOfUser|1|5),(totalTouchDownTime|2|3),(touchCycles|1|1)
-# This is logged when the partial wake lock (keeping the device awake
-# regardless of whether the screen is off) is acquired or released.
-2729 power_partial_wake_state (releasedorAcquired|1|5),(tag|3)
-# This is logged when battery goes from discharging to charging.
-# It lets us count the total amount of time between charges and the discharge level
-2730 battery_discharge (duration|2|3),(minLevel|1|6),(maxLevel|1|6)
-#
-# Leave IDs through 2739 for more power logs
-#
-
-# This event is logged when the location service uploads location data.
-2740 location_controller
-# This event is logged when someone is deciding to force a garbage collection
-2741 force_gc (reason|3)
-# This event is logged on each tickle
-2742 tickle (authority|3)
-# What happens in a sync operation (bytes sent and received, and
-# operation details)
-2743 sync_details (authority|3),(send|1|2),(recv|1|2),(details|3)
-
-# The disk space free on the /data partition, in bytes
-2744 free_storage_changed (data|2|2)
-# Device low memory notification and disk space free on the /data partition, in bytes at that time
-2745 low_storage (data|2|2)
-# disk space free on the /data, /system, and /cache partitions in bytes
-2746 free_storage_left (data|2|2),(system|2|2),(cache|2|2)
-
-# contacts aggregation: time and number of contacts.
-# count is negative for query phase, positive for merge phase
-2747 contacts_aggregation (aggregation time|2|3), (count|1|1)
-
-# when a NotificationManager.notify is called
-2750 notification_enqueue (pkg|3),(id|1|5),(notification|3)
-# when someone tries to cancel a notification, the notification manager sometimes
-# calls this with flags too
-2751 notification_cancel (pkg|3),(id|1|5),(required_flags|1)
-# when someone tries to cancel all of the notifications for a particular package
-2752 notification_cancel_all (pkg|3),(required_flags|1)
-
-# This event is logged when GTalkService encounters important events
-2800 gtalkservice (eventType|1)
-# This event is logged for GTalk connection state changes. The status field is an int, but
-# it really contains 4 separate values, each taking up a byte
-#     (eventType << 24) + (connection state << 16) + (connection error << 8) + network state
-2801 gtalk_connection (status|1)
-
-2802 watchdog (Service|3)
-2803 watchdog_proc_pss (Process|3),(Pid|1|5),(Pss|1|2)
-2804 watchdog_soft_reset (Process|3),(Pid|1|5),(MaxPss|1|2),(Pss|1|2),(Skip|3)
-2805 watchdog_hard_reset (Process|3),(Pid|1|5),(MaxPss|1|2),(Pss|1|2)
-2806 watchdog_pss_stats (EmptyPss|1|2),(EmptyCount|1|1),(BackgroundPss|1|2),(BackgroundCount|1|1),(ServicePss|1|2),(ServiceCount|1|1),(VisiblePss|1|2),(VisibleCount|1|1),(ForegroundPss|1|2),(ForegroundCount|1|1),(NoPssCount|1|1)
-2807 watchdog_proc_stats (DeathsInOne|1|1),(DeathsInTwo|1|1),(DeathsInThree|1|1),(DeathsInFour|1|1),(DeathsInFive|1|1)
-2808 watchdog_scheduled_reboot (Now|2|1),(Interval|1|3),(StartTime|1|3),(Window|1|3),(Skip|3)
-2809 watchdog_meminfo (MemFree|1|2),(Buffers|1|2),(Cached|1|2),(Active|1|2),(Inactive|1|2),(AnonPages|1|2),(Mapped|1|2),(Slab|1|2),(SReclaimable|1|2),(SUnreclaim|1|2),(PageTables|1|2)
-2810 watchdog_vmstat (runtime|2|3),(pgfree|1|1),(pgactivate|1|1),(pgdeactivate|1|1),(pgfault|1|1),(pgmajfault|1|1)
-2811 watchdog_requested_reboot (NoWait|1|1),(ScheduleInterval|1|3),(RecheckInterval|1|3),(StartTime|1|3),(Window|1|3),(MinScreenOff|1|3),(MinNextAlarm|1|3)
-
-2820 backup_data_changed (Package|3)
-2821 backup_start (Transport|3)
-2822 backup_transport_failure (Package|3)
-2823 backup_agent_failure (Package|3),(Message|3)
-2824 backup_package (Package|3),(Size|1|2)
-2825 backup_success (Packages|1|1),(Time|1|3)
-2826 backup_reset (Transport|3)
-2827 backup_initialize
-
-2830 restore_start (Transport|3),(Source|2|5)
-2831 restore_transport_failure
-2832 restore_agent_failure (Package|3),(Message|3)
-2833 restore_package (Package|3),(Size|1|2)
-2834 restore_success (Packages|1|1),(Time|1|3)
-
-# Device boot timings.  We include monotonic clock values because the
-# intrinsic event log times are wall-clock.
-#
-# Runtime starts:
-3000 boot_progress_start (time|2|3)
-# SystemServer.run() starts:
-3010 boot_progress_system_run (time|2|3)
-# ZygoteInit class preloading starts:
-3020 boot_progress_preload_start (time|2|3)
-# ZygoteInit class preloading ends:
-3030 boot_progress_preload_end (time|2|3)
-# ActivityManagerService.systemReady() starts:
-3040 boot_progress_ams_ready (time|2|3)
-# ActivityManagerService calls enableScreenAfterBoot():
-3050 boot_progress_enable_screen (time|2|3)
-# Package Manager starts:
-3060 boot_progress_pms_start (time|2|3)
-# Package Manager .apk scan starts:
-3070 boot_progress_pms_system_scan_start (time|2|3)
-# Package Manager .apk scan starts:
-3080 boot_progress_pms_data_scan_start (time|2|3)
-# Package Manager .apk scan ends:
-3090 boot_progress_pms_scan_end (time|2|3)
-# Package Manager ready:
-3100 boot_progress_pms_ready (time|2|3)
-# + check activity_launch_time for Home app
-
-# This event is logged when GTalk connection is closed.
-# The status field is an int, but contains 2 different values, it's represented as
-#
-#     (networkType << 8) + connection error
-#
-# the possible error values are
-#
-# no_error=0, no_network=1, connection_failed=2, unknown_host=3, auth_failed=4,
-# auth_expired=5, heart_beat_timeout=6, server_error=7, server_reject_rate_limiting=8, unknown=10
-#
-# duration is the connection duration.
-4000 gtalk_conn_close (status|1),(duration|1)
-
-# This event is logged for GTalk heartbeat resets
-# interval_and_nt contains both the heartbeat interval and the network type, It's represented as
-#     (networkType << 16) + interval
-# interval is in seconds; network type can be 0 (mobile) or 1 (wifi); ip is the host ip addr.
-4001 gtalk_heartbeat_reset (interval_and_nt|1),(ip|3)
-
-# dvm_gc_info: LIST (LONG, LONG, LONG)
-#
-# First LONG:
-#
-#    [63]    1
-#    [62-24] ASCII process identifier
-#    [23-12] GC time in ms
-#    [11- 0] Bytes freed
-#
-# Second LONG (aggregated heap info):
-#
-#    [63-62] 10
-#    [61-60] Reserved; must be zero
-#    [59-48] Objects freed
-#    [47-36] Actual size (current footprint)
-#    [35-24] Allowed size (current hard max)
-#    [23-12] Objects allocated
-#    [11- 0] Bytes allocated
-#
-# Third LONG (zygote heap info):
-#
-#    [63-62] 11
-#    [61-60] Reserved; must be zero
-#    [59-48] Soft limit
-#    [47-36] Actual size (current footprint)
-#    [35-24] Allowed size (current hard max)
-#    [23-12] Objects allocated
-#    [11- 0] Bytes allocated
-#
-# Fourth LONG:
-#
-#    [63-48] Reserved; must be zero
-#    [47-36] dlmallocFootprint
-#    [35-24] mallinfo: total allocated space
-#    [23-12] External byte limit
-#    [11- 0] External bytes allocated
-#
-# See HeapDebug.c
-#
-20001 dvm_gc_info (custom|2),(custom|2),(custom|2),(custom|2)
-20002 dvm_gc_madvise_info (total|1|2),(zygote|1|2)
-
-# Do not change these names without updating the checkin_events setting in
-# google3/googledata/wireless/android/provisioning/gservices.config !!
-#
-# An activity is being finished:
-30001 am_finish_activity (Token|1|5),(Task ID|1|5),(Component Name|3),(Reason|3)
-# A task is being brought to the front of the screen:
-30002 am_task_to_front (Task|1|5)
-# An existing activity is being given a new intent:
-30003 am_new_intent (Token|1|5),(Task ID|1|5),(Component Name|3),(Action|3),(MIME Type|3),(URI|3),(Flags|1|5)
-# A new task is being created:
-30004 am_create_task (Task ID|1|5)
-# A new activity is being created in an existing task:
-30005 am_create_activity (Token|1|5),(Task ID|1|5),(Component Name|3),(Action|3),(MIME Type|3),(URI|3),(Flags|1|5)
-# An activity has been resumed into the foreground but was not already running:
-30006 am_restart_activity (Token|1|5),(Task ID|1|5),(Component Name|3)
-# An activity has been resumed and is now in the foreground:
-30007 am_resume_activity (Token|1|5),(Task ID|1|5),(Component Name|3)
-# Application Not Responding
-30008 anr (pid|1|5),(Package Name|3),(reason|3)
-# Activity launch time
-30009 activity_launch_time (Token|1|5),(Component Name|3),(time|2|3)
-# Application process bound to work
-30010 am_proc_bound (PID|1|5),(Process Name|3)
-# Application process died
-30011 am_proc_died (PID|1|5),(Process Name|3)
-# The Activity Manager failed to pause the given activity.
-30012 am_failed_to_pause (Token|1|5),(Wanting to pause|3),(Currently pausing|3)
-# Attempting to pause the current activity
-30013 am_pause_activity (Token|1|5),(Component Name|3)
-# Application process has been started
-30014 am_proc_start (PID|1|5),(UID|1|5),(Process Name|3),(Type|3),(Component|3)
-# An application process has been marked as bad
-30015 am_proc_bad (UID|1|5),(Process Name|3)
-# An application process that was bad is now marked as good
-30016 am_proc_good (UID|1|5),(Process Name|3)
-# Reporting to applications that memory is low
-30017 am_low_memory (Num Processes|1|1)
-# An activity is being destroyed:
-30018 am_destroy_activity (Token|1|5),(Task ID|1|5),(Component Name|3)
-# An activity has been relaunched, resumed, and is now in the foreground:
-30019 am_relaunch_resume_activity (Token|1|5),(Task ID|1|5),(Component Name|3)
-# An activity has been relaunched:
-30020 am_relaunch_activity (Token|1|5),(Task ID|1|5),(Component Name|3)
-# The activity's onPause has been called.
-30021 am_on_paused_called (Component Name|3)
-# The activity's onResume has been called.
-30022 am_on_resume_called (Component Name|3)
-# Kill a process to reclaim memory.
-30023 am_kill_for_memory (PID|1|5),(Process Name|3),(OomAdj|1|5)
-# Discard an undelivered serialized broadcast (timeout/ANR/crash)
-30024 am_broadcast_discard_filter (Broadcast|1|5),(Action|3),(Receiver Number|1|1),(BroadcastFilter|1|5)
-30025 am_broadcast_discard_app (Broadcast|1|5),(Action|3),(Receiver Number|1|1),(App|3)
-# A service is being created
-30030 am_create_service (Service Record|1|5),(Name|3),(Intent|3),(PID|1|5)
-# A service is being destroyed
-30031 am_destroy_service (Service Record|1|5),(Name|3),(PID|1|5)
-# A process has crashed too many times, it is being cleared
-30032 am_process_crashed_too_much (Name|3),(PID|1|5)
-# An unknown process is trying to attach to the activity manager
-30033 am_drop_process (PID|1|5)
-# A service has crashed too many times, it is being stopped
-30034 am_service_crashed_too_much (Crash Count|1|1),(Component Name|3),(PID|1|5)
-# A service is going to be restarted after its process went away
-30035 am_schedule_service_restart (Component Name|3),(Time|2|3)
-# A client was waiting for a content provider, but its process was lost
-30036 am_provider_lost_process (Package Name|3),(UID|1|5),(Name|3)
-# The activity manager gave up on a new process taking too long to start
-30037 am_process_start_timeout (PID|1|5),(UID|1|5),(Process Name|3)
-
-# Out of memory for surfaces.
-31000 wm_no_surface_memory (Window|3),(PID|1|5),(Operation|3)
-
-# Re-connecting to input method service because we haven't received its interface
-32000 imf_force_reconnect_ime (IME|4),(Time Since Connect|2|3),(Showing|1|1)
-
-75000 sqlite_mem_alarm_current (current|1|2)
-75001 sqlite_mem_alarm_max (max|1|2)
-75002 sqlite_mem_alarm_alloc_attempt (attempts|1|4)
-75003 sqlite_mem_released (Memory released|1|2)
-75004 sqlite_db_corrupt (Database file corrupt|3)
-
-40000 checkin (Check in time|2|3)
-
-50000 menu_item_selected (Menu type where 0 is options and 1 is context|1|5),(Menu item title|3)
-50001 menu_opened (Menu type where 0 is options and 1 is context|1|5)
-# Connectivity state changed:
-# [31-13] Reserved for future use
-# [12- 9] Network subtype (for mobile network, as defined by TelephonyManager)
-# [ 8- 3] Detailed state ordinal (as defined by NetworkInfo.DetailedState)
-# [ 2- 0] Network type (as defined by ConnectivityManager)
-50020 connectivity_state_changed (custom|1|5)
-
-# Wi-Fi network state changed:
-# [31- 6] Reserved for future use
-# [ 5- 0] Detailed state ordinal (as defined by NetworkInfo.DetailedState)
-50021 wifi_network_state_changed (network_state|1|5)
-
-# Wi-Fi supplicant state changed:
-# [31- 6] Reserved for future use
-# [ 5- 0] Supplicant state ordinal (as defined by SupplicantState)
-50022 wifi_supplicant_state_changed (supplicant_state|1|5)
-
-# Wi-Fi driver state changed:
-# [31- 1] Reserved for future use
-# [ 0- 0] Driver start (1) or stopped (0)
-50023 wifi_driver_state_changed (driver_state|1|5)
-
-# Wi-Fi interface configuration state changed:
-# [31- 1] Reserved for future use
-# [ 0- 0] Interface configuration succeeded (1) or failed (0)
-50024 wifi_interface_configuration_state_changed (IP_configuration|1|5)
-
-# Wi-Fi supplicant connection state changed:
-# [31- 2] Reserved for future use
-# [ 1- 0] Connected to supplicant (1) or disconnected from supplicant (0),
-#         or supplicant died (2)
-50025 wifi_supplicant_connection_state_changed (connected|1|5)
-
-# PDP Context has a bad DNS address
-50100 pdp_bad_dns_address (dns_address|3)
-
-# For data connection on PDP context, reached the data-out-without-data-in
-# packet count that triggers a countdown to radio restart
-50101 pdp_radio_reset_countdown_triggered (out_packet_count|1|1)
-
-# Radio restart - timed out with no incoming packets.
-50102 pdp_radio_reset (out_packet_count|1|1)
-
-# PDP context reset - timed out with no incoming packets.
-50103 pdp_context_reset (out_packet_count|1|1)
-
-# Reregister to data network - timed out with no incoming packets.
-50104 pdp_reregister_network (out_packet_count|1|1)
-
-# PDP Setup failures
-50105 pdp_setup_fail (cause|1|5), (cid|1|5), (network_type|1|5)
-
-# Call drops
-50106 call_drop (cause|1|5), (cid|1|5), (network_type|1|5)
-
-# Data network registration failed after successful voice registration
-50107 data_network_registration_fail (op_numeric|1|5), (cid|1|5)
-
-# Suspicious status of data connection while radio poweroff
-50108 data_network_status_on_radio_off (dc_state|3), (enable|1|5)
-
-# PDP drop caused by network
-50109 pdp_network_drop (cid|1|5), (network_type|1|5)
-
-# CDMA data network setup failure
-50110 cdma_data_setup_failed (cause|1|5), (cid|1|5), (network_type|1|5)
-
-# CDMA data network drop
-50111 cdma_data_drop (cid|1|5), (network_type|1|5)
-
-# GSM radio access technology switched
-50112 gsm_rat_switched (cid|1|5), (network_from|1|5), (network_to|1|5)
-
-# Do not change these names without updating tag in:
-#//device/dalvik/libcore/luni/src/main/native/org_apache_harmony_luni_platform_OSNetworkSystem.c
-51000 socket_stats (send|1|2),(recv|1|2),(ip|1|5),(port|1|5),(close|1|5)
-
-# db stats.  0 is query, 1 is write (may become more fine grained in the
-# future)
-52000 db_operation (name|3),(op_type|1|5),(time|2|3)
-
-# http request/response stats
-52001 http_stats (useragent|3),(response|2|3),(processing|2|3),(tx|1|2),(rx|1|2)
-60000 viewroot_draw (Draw time|1|3)
-60001 viewroot_layout (Layout time|1|3)
-60002 view_build_drawing_cache (View created drawing cache|1|5)
-60003 view_use_drawing_cache (View drawn using bitmap cache|1|5)
-
-# 0 for screen off, 1 for screen on, 2 for key-guard done
-70000 screen_toggled (screen_state|1|5)
-
-# browser stats for diary study
-70101 browser_zoom_level_change (start level|1|5),(end level|1|5),(time|2|3)
-70102 browser_double_tap_duration (duration|1|3),(time|2|3)
-
-# aggregation service
-70200 aggregation (aggregation time|2|3)
-70201 aggregation_test (field1|1|2),(field2|1|2),(field3|1|2),(field4|1|2),(field5|1|2)
-
-# NOTE - the range 1000000-2000000 is reserved for partners and others who
-# want to define their own log tags without conflicting with the core platform.
diff --git a/logcat/event.logtags b/logcat/event.logtags
new file mode 100644
index 0000000..2459604
--- /dev/null
+++ b/logcat/event.logtags
@@ -0,0 +1,245 @@
+# The entries in this file map a sparse set of log tag numbers to tag names.
+# This is installed on the device, in /system/etc, and parsed by logcat.
+#
+# Tag numbers are decimal integers, from 0 to 2^31.  (Let's leave the
+# negative values alone for now.)
+#
+# Tag names are one or more ASCII letters and numbers or underscores, i.e.
+# "[A-Z][a-z][0-9]_".  Do not include spaces or punctuation (the former
+# impacts log readability, the latter makes regex searches more annoying).
+#
+# Tag numbers and names are separated by whitespace.  Blank lines and lines
+# starting with '#' are ignored.
+#
+# Optionally, after the tag names can be put a description for the value(s)
+# of the tag. Description are in the format
+#    (<name>|data type[|data unit])
+# Multiple values are separated by commas.
+#
+# The data type is a number from the following values:
+# 1: int
+# 2: long
+# 3: string
+# 4: list
+#
+# The data unit is a number taken from the following list:
+# 1: Number of objects
+# 2: Number of bytes
+# 3: Number of milliseconds
+# 4: Number of allocations
+# 5: Id
+# 6: Percent
+# Default value for data of type int/long is 2 (bytes).
+#
+# TODO: generate ".java" and ".h" files with integer constants from this file.
+
+# These are used for testing, do not modify without updating
+# tests/framework-tests/src/android/util/EventLogFunctionalTest.java.
+42    answer (to life the universe etc|3)
+314   pi
+2718  e
+
+# "account" is the java hash of the account name
+2720 sync (id|3),(event|1|5),(source|1|5),(account|1|5)
+
+# This event is logged when the location service uploads location data.
+2740 location_controller
+# This event is logged when someone is deciding to force a garbage collection
+2741 force_gc (reason|3)
+# This event is logged on each tickle
+2742 tickle (authority|3)
+# What happens in a sync operation (bytes sent and received, and
+# operation details)
+2743 sync_details (authority|3),(send|1|2),(recv|1|2),(details|3)
+
+# contacts aggregation: time and number of contacts.
+# count is negative for query phase, positive for merge phase
+2747 contacts_aggregation (aggregation time|2|3), (count|1|1)
+
+# This event is logged when GTalkService encounters important events
+2800 gtalkservice (eventType|1)
+# This event is logged for GTalk connection state changes. The status field is an int, but
+# it really contains 4 separate values, each taking up a byte
+#     (eventType << 24) + (connection state << 16) + (connection error << 8) + network state
+2801 gtalk_connection (status|1)
+
+# Device boot timings.  We include monotonic clock values because the
+# intrinsic event log times are wall-clock.
+#
+# Runtime starts:
+3000 boot_progress_start (time|2|3)
+# ZygoteInit class preloading starts:
+3020 boot_progress_preload_start (time|2|3)
+# ZygoteInit class preloading ends:
+3030 boot_progress_preload_end (time|2|3)
+
+# This event is logged when GTalk connection is closed.
+# The status field is an int, but contains 2 different values, it's represented as
+#
+#     (networkType << 8) + connection error
+#
+# the possible error values are
+#
+# no_error=0, no_network=1, connection_failed=2, unknown_host=3, auth_failed=4,
+# auth_expired=5, heart_beat_timeout=6, server_error=7, server_reject_rate_limiting=8, unknown=10
+#
+# duration is the connection duration.
+4000 gtalk_conn_close (status|1),(duration|1)
+
+# This event is logged for GTalk heartbeat resets
+# interval_and_nt contains both the heartbeat interval and the network type, It's represented as
+#     (networkType << 16) + interval
+# interval is in seconds; network type can be 0 (mobile) or 1 (wifi); ip is the host ip addr.
+4001 gtalk_heartbeat_reset (interval_and_nt|1),(ip|3)
+
+# dvm_gc_info: LIST (LONG, LONG, LONG)
+#
+# First LONG:
+#
+#    [63]    1
+#    [62-24] ASCII process identifier
+#    [23-12] GC time in ms
+#    [11- 0] Bytes freed
+#
+# Second LONG (aggregated heap info):
+#
+#    [63-62] 10
+#    [61-60] Reserved; must be zero
+#    [59-48] Objects freed
+#    [47-36] Actual size (current footprint)
+#    [35-24] Allowed size (current hard max)
+#    [23-12] Objects allocated
+#    [11- 0] Bytes allocated
+#
+# Third LONG (zygote heap info):
+#
+#    [63-62] 11
+#    [61-60] Reserved; must be zero
+#    [59-48] Soft limit
+#    [47-36] Actual size (current footprint)
+#    [35-24] Allowed size (current hard max)
+#    [23-12] Objects allocated
+#    [11- 0] Bytes allocated
+#
+# Fourth LONG:
+#
+#    [63-48] Reserved; must be zero
+#    [47-36] dlmallocFootprint
+#    [35-24] mallinfo: total allocated space
+#    [23-12] External byte limit
+#    [11- 0] External bytes allocated
+#
+# See HeapDebug.c
+#
+20001 dvm_gc_info (custom|2),(custom|2),(custom|2),(custom|2)
+20002 dvm_gc_madvise_info (total|1|2),(zygote|1|2)
+
+75000 sqlite_mem_alarm_current (current|1|2)
+75001 sqlite_mem_alarm_max (max|1|2)
+75002 sqlite_mem_alarm_alloc_attempt (attempts|1|4)
+75003 sqlite_mem_released (Memory released|1|2)
+75004 sqlite_db_corrupt (Database file corrupt|3)
+
+40000 checkin (Check in time|2|3)
+
+50000 menu_item_selected (Menu type where 0 is options and 1 is context|1|5),(Menu item title|3)
+50001 menu_opened (Menu type where 0 is options and 1 is context|1|5)
+
+# Wi-Fi network state changed:
+# [31- 6] Reserved for future use
+# [ 5- 0] Detailed state ordinal (as defined by NetworkInfo.DetailedState)
+50021 wifi_network_state_changed (network_state|1|5)
+
+# Wi-Fi supplicant state changed:
+# [31- 6] Reserved for future use
+# [ 5- 0] Supplicant state ordinal (as defined by SupplicantState)
+50022 wifi_supplicant_state_changed (supplicant_state|1|5)
+
+# Wi-Fi driver state changed:
+# [31- 1] Reserved for future use
+# [ 0- 0] Driver start (1) or stopped (0)
+50023 wifi_driver_state_changed (driver_state|1|5)
+
+# Wi-Fi interface configuration state changed:
+# [31- 1] Reserved for future use
+# [ 0- 0] Interface configuration succeeded (1) or failed (0)
+50024 wifi_interface_configuration_state_changed (IP_configuration|1|5)
+
+# Wi-Fi supplicant connection state changed:
+# [31- 2] Reserved for future use
+# [ 1- 0] Connected to supplicant (1) or disconnected from supplicant (0),
+#         or supplicant died (2)
+50025 wifi_supplicant_connection_state_changed (connected|1|5)
+
+# PDP Context has a bad DNS address
+50100 pdp_bad_dns_address (dns_address|3)
+
+# For data connection on PDP context, reached the data-out-without-data-in
+# packet count that triggers a countdown to radio restart
+50101 pdp_radio_reset_countdown_triggered (out_packet_count|1|1)
+
+# Radio restart - timed out with no incoming packets.
+50102 pdp_radio_reset (out_packet_count|1|1)
+
+# PDP context reset - timed out with no incoming packets.
+50103 pdp_context_reset (out_packet_count|1|1)
+
+# Reregister to data network - timed out with no incoming packets.
+50104 pdp_reregister_network (out_packet_count|1|1)
+
+# PDP Setup failures
+50105 pdp_setup_fail (cause|1|5), (cid|1|5), (network_type|1|5)
+
+# Call drops
+50106 call_drop (cause|1|5), (cid|1|5), (network_type|1|5)
+
+# Data network registration failed after successful voice registration
+50107 data_network_registration_fail (op_numeric|1|5), (cid|1|5)
+
+# Suspicious status of data connection while radio poweroff
+50108 data_network_status_on_radio_off (dc_state|3), (enable|1|5)
+
+# PDP drop caused by network
+50109 pdp_network_drop (cid|1|5), (network_type|1|5)
+
+# CDMA data network setup failure
+50110 cdma_data_setup_failed (cause|1|5), (cid|1|5), (network_type|1|5)
+
+# CDMA data network drop
+50111 cdma_data_drop (cid|1|5), (network_type|1|5)
+
+# GSM radio access technology switched
+50112 gsm_rat_switched (cid|1|5), (network_from|1|5), (network_to|1|5)
+
+# Do not change these names without updating tag in:
+#//device/dalvik/libcore/luni/src/main/native/org_apache_harmony_luni_platform_OSNetworkSystem.c
+51000 socket_stats (send|1|2),(recv|1|2),(ip|1|5),(port|1|5),(close|1|5)
+
+# Database operation samples.
+# db: the filename of the database
+# sql: the executed query (without query args)
+# time: cpu time millis (not wall time), including lock acquisition
+# blocking_package: if this is on a main thread, the package name, otherwise ""
+# sample_percent: the percent likelihood this query was logged
+52000 db_operation (db|3),(sql|3),(time|1|3),(blocking_package|3),(sample_percent|1|6)
+
+# http request/response stats
+52001 http_stats (useragent|3),(response|2|3),(processing|2|3),(tx|1|2),(rx|1|2)
+60000 viewroot_draw (Draw time|1|3)
+60001 viewroot_layout (Layout time|1|3)
+60002 view_build_drawing_cache (View created drawing cache|1|5)
+60003 view_use_drawing_cache (View drawn using bitmap cache|1|5)
+
+# 0 for screen off, 1 for screen on, 2 for key-guard done
+70000 screen_toggled (screen_state|1|5)
+
+# browser stats for diary study
+70101 browser_zoom_level_change (start level|1|5),(end level|1|5),(time|2|3)
+70102 browser_double_tap_duration (duration|1|3),(time|2|3)
+
+# aggregation service
+70200 aggregation (aggregation time|2|3)
+70201 aggregation_test (field1|1|2),(field2|1|2),(field3|1|2),(field4|1|2),(field5|1|2)
+
+# NOTE - the range 1000000-2000000 is reserved for partners and others who
+# want to define their own log tags without conflicting with the core platform.
diff --git a/rootdir/Android.mk b/rootdir/Android.mk
index 3bb2262..7ac991c 100644
--- a/rootdir/Android.mk
+++ b/rootdir/Android.mk
@@ -8,7 +8,7 @@
 	etc/hosts
 
 ifeq ($(TARGET_PRODUCT),generic)
-copy_from += etc/vold.conf
+copy_from += etc/vold.fstab
 endif
 
 # the /system/etc/init.goldfish.sh is needed to enable emulator support
diff --git a/rootdir/etc/vold.conf b/rootdir/etc/vold.conf
deleted file mode 100644
index 4e04509..0000000
--- a/rootdir/etc/vold.conf
+++ /dev/null
@@ -1,10 +0,0 @@
-## vold configuration file for the 'generic' target
-
-volume_sdcard {
-    ## This is the direct uevent device path to the SD slot on the device
-    media_path     /devices/platform/goldfish_mmc.0/mmc_host/mmc0
-
-    media_type     mmc
-    mount_point    /sdcard
-    ums_path       /devices/platform/usb_mass_storage/lun0
-}
diff --git a/rootdir/etc/vold.fstab b/rootdir/etc/vold.fstab
new file mode 100644
index 0000000..16065e9
--- /dev/null
+++ b/rootdir/etc/vold.fstab
@@ -0,0 +1,24 @@
+## Vold 2.0 Generic fstab
+## - San Mehat (san@android.com)
+## 
+
+#######################
+## Regular device mount
+##
+## Format: dev_mount <label> <mount_point> <part> <sysfs_path1...> 
+## label        - Label for the volume
+## mount_point  - Where the volume will be mounted
+## part         - Partition # (1 based), or 'auto' for first usable partition.
+## <sysfs_path> - List of sysfs paths to source devices
+######################
+
+## Example of a standard sdcard mount for the emulator / Dream
+# Mounts the first usable partition of the specified device
+dev_mount sdcard /sdcard auto /devices/platform/goldfish_mmc.0 /devices/platform/msm_sdcc.2/mmc_host/mmc1
+
+## Example of a dual card setup
+# dev_mount left_sdcard  /sdcard1  auto /devices/platform/goldfish_mmc.0 /devices/platform/msm_sdcc.2/mmc_host/mmc1
+# dev_mount right_sdcard /sdcard2  auto /devices/platform/goldfish_mmc.1 /devices/platform/msm_sdcc.3/mmc_host/mmc1
+
+## Example of specifying a specific partition for mounts
+# dev_mount sdcard /sdcard 2 /devices/platform/goldfish_mmc.0 /devices/platform/msm_sdcc.2/mmc_host/mmc1
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 925347d..3430261 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -19,14 +19,16 @@
     symlink /system/etc /etc
     symlink /sys/kernel/debug /d
 
-# create mountpoints and mount tmpfs on sqlite_stmt_journals
+# create mountpoints
     mkdir /sdcard 0000 system system
     mkdir /system
     mkdir /data 0771 system system
     mkdir /cache 0770 system cache
     mkdir /config 0500 root root
-    mkdir /sqlite_stmt_journals 01777 root root
-    mount tmpfs tmpfs /sqlite_stmt_journals size=4m
+
+# create Android Secure External Cache mount tree
+    mkdir /asec  0700 system system
+    mount tmpfs tmpfs /asec mode=0755
 
     mount rootfs rootfs / ro remount
 
@@ -41,7 +43,7 @@
 # Create cgroup mount points for process groups
     mkdir /dev/cpuctl
     mount cgroup none /dev/cpuctl cpu
-    chown sytem system /dev/cpuctl
+    chown system system /dev/cpuctl
     chown system system /dev/cpuctl/tasks
     chmod 0777 /dev/cpuctl/tasks
     write /dev/cpuctl/cpu.shares 1024
@@ -92,7 +94,7 @@
     chmod 0770 /cache
 
     # This may have been created by the recovery system with odd permissions
-    chown system system /cache/recovery
+    chown system cache /cache/recovery
     chmod 0770 /cache/recovery
 
     #change permissions on vmallocinfo so we can grab it from bugreports
@@ -104,6 +106,7 @@
     mkdir /data/misc/bluetoothd 0770 bluetooth bluetooth
     mkdir /data/misc/keystore 0700 keystore keystore
     mkdir /data/misc/vpn 0770 system system
+    mkdir /data/misc/systemkeys 0700 system system
     mkdir /data/misc/vpn/profiles 0770 system system
     # give system access to wpa_supplicant.conf for backup and restore
     mkdir /data/misc/wifi 0770 wifi wifi
@@ -116,6 +119,12 @@
     mkdir /data/app 0771 system system
     mkdir /data/property 0700 root root
 
+    # STOPSHIP: Temporary Encrypted File Systems workaround
+    mkdir /data/secure 0771 system system
+    mkdir /data/secure/data 0771 system system
+    mkdir /data/secure/misc 01771 system misc
+    mkdir /data/securemisc/vpn 0770 system system
+    mkdir /data/secure/misc/vpn/profiles 0770 system system
 
     # create dalvik-cache and double-check the perms
     mkdir /data/dalvik-cache 0771 system system
@@ -256,6 +265,9 @@
 service vold /system/bin/vold
     socket vold stream 0660 root mount
 
+service netd /system/bin/netd
+    socket netd stream 0660 root system
+
 service nexus /system/bin/nexus
     socket nexus stream 0660 root system
     disabled
diff --git a/sh/miscbltin.c b/sh/miscbltin.c
index 1a8e252..d89029a 100644
--- a/sh/miscbltin.c
+++ b/sh/miscbltin.c
@@ -277,8 +277,6 @@
 	return 0;
 }
 
-typedef unsigned long rlim_t;
-
 #if 1
 /*
  * ulimit builtin
diff --git a/toolbox/Android.mk b/toolbox/Android.mk
index 70b13dc..122a544 100644
--- a/toolbox/Android.mk
+++ b/toolbox/Android.mk
@@ -50,7 +50,8 @@
 	top \
 	iftop \
 	id \
-	vmstat
+	vmstat \
+	nandread
 
 LOCAL_SRC_FILES:= \
 	toolbox.c \
diff --git a/toolbox/ls.c b/toolbox/ls.c
index b221074..f340a83 100644
--- a/toolbox/ls.c
+++ b/toolbox/ls.c
@@ -86,15 +86,50 @@
     }
 }
 
-static int listfile_size(const char *path, int flags)
+static int show_total_size(const char *dirname, DIR *d, int flags)
+{
+    struct dirent *de;
+    char tmp[1024];
+    struct stat s;
+    int sum = 0;
+
+    /* run through the directory and sum up the file block sizes */
+    while ((de = readdir(d)) != 0) {
+        if (strcmp(de->d_name, ".") == 0 || strcmp(de->d_name, "..") == 0)
+            continue;
+        if (de->d_name[0] == '.' && (flags & LIST_ALL) == 0)
+            continue;
+
+        if (strcmp(dirname, "/") == 0)
+            snprintf(tmp, sizeof(tmp), "/%s", de->d_name);
+        else
+            snprintf(tmp, sizeof(tmp), "%s/%s", dirname, de->d_name);
+
+        if (lstat(tmp, &s) < 0) {
+            fprintf(stderr, "stat failed on %s: %s\n", tmp, strerror(errno));
+            rewinddir(d);
+            return -1;
+        }
+
+        sum += s.st_blocks / 2;
+    }
+
+    printf("total %d\n", sum);
+    rewinddir(d);
+    return 0;
+}
+
+static int listfile_size(const char *path, const char *filename, int flags)
 {
     struct stat s;
 
-    if (lstat(path, &s) < 0)
+    if (lstat(path, &s) < 0) {
+        fprintf(stderr, "lstat '%s' failed: %s\n", path, strerror(errno));
         return -1;
+    }
 
     /* blocks are 512 bytes, we want output to be KB */
-    printf("%lld %s\n", s.st_blocks / 2, path);
+    printf("%lld %s\n", s.st_blocks / 2, filename);
     return 0;
 }
 
@@ -189,7 +224,7 @@
     if ((flags & LIST_LONG) != 0) {
         return listfile_long(pathname, flags);
     } else /*((flags & LIST_SIZE) != 0)*/ {
-        return listfile_size(pathname, flags);
+        return listfile_size(pathname, filename, flags);
     }
 }
 
@@ -198,13 +233,17 @@
     char tmp[4096];
     DIR *d;
     struct dirent *de;
-    
+
     d = opendir(name);
     if(d == 0) {
         fprintf(stderr, "opendir failed, %s\n", strerror(errno));
         return -1;
     }
 
+    if ((flags & LIST_SIZE) != 0) {
+        show_total_size(name, d, flags);
+    }
+
     while((de = readdir(d)) != 0){
         if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) continue;
         if(de->d_name[0] == '.' && (flags & LIST_ALL) == 0) continue;
diff --git a/toolbox/nandread.c b/toolbox/nandread.c
new file mode 100644
index 0000000..aacccdb
--- /dev/null
+++ b/toolbox/nandread.c
@@ -0,0 +1,256 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+
+#include <mtd/mtd-user.h>
+#include <sys/ioctl.h>
+
+int test_empty(const char *buf, size_t size)
+{
+    while(size--) {
+        if (*buf++ != 0xff)
+            return 0;
+    }
+    return 1;
+}
+
+int nandread_main(int argc, char **argv)
+{
+    char *devname = NULL;
+    char *filename = NULL;
+    char *statusfilename = NULL;
+    char *statusext = ".stat";
+    int fd;
+    int outfd = -1;
+    FILE *statusfile = NULL;
+    int ret;
+    int verbose = 0;
+    void *buffer;
+    loff_t pos, opos;
+    int c;
+    int i;
+    int empty_pages = 0;
+    int page_count = 0;
+    int bad_block;
+    uint32_t *oob_data;
+    uint8_t *oob_fixed;
+    size_t spare_size = 64;
+    struct mtd_info_user mtdinfo;
+    struct mtd_ecc_stats initial_ecc, last_ecc, ecc;
+    struct mtd_oob_buf oobbuf;
+    struct nand_ecclayout ecclayout;
+
+    do {
+        c = getopt(argc, argv, "d:f:s:hv");
+        if (c == EOF)
+            break;
+        switch (c) {
+        case 'd':
+            devname = optarg;
+            break;
+        case 'f':
+            filename = optarg;
+            break;
+        case 's':
+            spare_size = atoi(optarg);
+            break;
+        case 'v':
+            verbose++;
+            break;
+        case 'h':
+            fprintf(stderr, "%s [-d <dev>] [-f file] [-s sparesize] [-vh]\n"
+                    "  -d <dev>   Read from <dev>\n"
+                    "  -f <file>  Write to <file>\n"
+                    "  -s <size>  Number of spare bytes in file (default 64)\n"
+                    "  -v         Print info\n"
+                    "  -h         Print help\n", argv[0]);
+            return -1;
+        case '?':
+            fprintf(stderr, "%s: invalid option -%c\n",
+                argv[0], optopt);
+            exit(1);
+        }
+    } while (1);
+
+    if (optind < argc) {
+        fprintf(stderr, "%s: extra arguments\n", argv[0]);
+        return 1;
+    }
+    if (!devname) {
+        fprintf(stderr, "%s: specify device name\n", argv[0]);
+        return 1;
+    }
+
+    fd = open(devname, O_RDONLY);
+    if (fd < 0) {
+        fprintf(stderr, "cannot open %s, %s\n", devname, strerror(errno));
+        return 1;
+    }
+
+    if (filename) {
+        outfd = creat(filename, 0666);
+        if (outfd < 0) {
+            fprintf(stderr, "cannot open %s, %s\n", filename, strerror(errno));
+            return 1;
+        }
+        statusfilename = malloc(strlen(filename) + strlen(statusext) + 1);
+        strcpy(statusfilename, filename);
+        strcat(statusfilename, statusext);
+        statusfile = fopen(statusfilename, "w+");
+        if (!statusfile) {
+            fprintf(stderr, "cannot open %s, %s\n", statusfilename, strerror(errno));
+            return 1;
+        }
+    }
+
+    ret = ioctl(fd, MEMGETINFO, &mtdinfo);
+    if (ret) {
+        fprintf(stderr, "failed get mtd info for %s, %s\n",
+                devname, strerror(errno));
+        return 1;
+    }
+
+    if (verbose) {
+        printf("size: %u\n", mtdinfo.size);
+        printf("erase size: %u\n", mtdinfo.erasesize);
+        printf("write size: %u\n", mtdinfo.writesize);
+        printf("oob size: %u\n", mtdinfo.oobsize);
+    }
+
+    buffer = malloc(mtdinfo.writesize + mtdinfo.oobsize + spare_size);
+    if (!buffer) {
+        fprintf(stderr, "failed allocate readbuffer size %u\n",
+                mtdinfo.writesize + mtdinfo.oobsize);
+        return 1;
+    }
+
+    oobbuf.length = mtdinfo.oobsize;
+    oob_data = (uint32_t *)((uint8_t *)buffer + mtdinfo.writesize);
+    memset(oob_data, 0xff, spare_size);
+    oobbuf.ptr = (uint8_t *)oob_data + spare_size;
+
+    ret = ioctl(fd, ECCGETLAYOUT, &ecclayout);
+    if (ret) {
+        fprintf(stderr, "failed get ecc layout for %s, %s\n",
+                devname, strerror(errno));
+        return 1;
+    }
+    if (verbose) {
+        printf("ecc bytes: %u\n", ecclayout.eccbytes);
+        printf("oobavail: %u\n", ecclayout.oobavail);
+    }
+    if (ecclayout.oobavail > spare_size)
+        printf("oobavail, %d > image spare size, %d\n", ecclayout.oobavail, spare_size);
+
+    ret = ioctl(fd, ECCGETSTATS, &initial_ecc);
+    if (ret) {
+        fprintf(stderr, "failed get ecc stats for %s, %s\n",
+                devname, strerror(errno));
+        return 1;
+    }
+    last_ecc = initial_ecc;
+
+    if (verbose) {
+        printf("initial ecc corrected: %u\n", initial_ecc.corrected);
+        printf("initial ecc failed: %u\n", initial_ecc.failed);
+        printf("initial ecc badblocks: %u\n", initial_ecc.badblocks);
+        printf("initial ecc bbtblocks: %u\n", initial_ecc.bbtblocks);
+    }
+
+    for (pos = 0, opos = 0; pos < mtdinfo.size; pos += mtdinfo.writesize) {
+        bad_block = 0;
+        if (verbose > 3)
+            printf("reading at %llx\n", pos);
+        lseek64(fd, pos, SEEK_SET);
+        ret = read(fd, buffer, mtdinfo.writesize);
+        if (ret < (int)mtdinfo.writesize) {
+            fprintf(stderr, "short read at %llx, %d\n", pos, ret);
+            bad_block = 2;
+        }
+        oobbuf.start = pos;
+        ret = ioctl(fd, MEMREADOOB, &oobbuf);
+        if (ret) {
+            fprintf(stderr, "failed to read oob data at %llx, %d\n", pos, ret);
+            bad_block = 2;
+        }
+        ret = ioctl(fd, ECCGETSTATS, &ecc);
+        if (ret) {
+            fprintf(stderr, "failed get ecc stats for %s, %s\n",
+                    devname, strerror(errno));
+            return 1;
+        }
+        ret = ioctl(fd, MEMGETBADBLOCK, &pos);
+        if (ret && errno != EOPNOTSUPP) {
+            printf("badblock at %llx\n", pos);
+            bad_block = 1;
+        }
+        if (ecc.corrected != last_ecc.corrected)
+            printf("ecc corrected, %u, at %llx\n", ecc.corrected - last_ecc.corrected, pos);
+        if (ecc.failed != last_ecc.failed)
+            printf("ecc failed, %u, at %llx\n", ecc.failed - last_ecc.failed, pos);
+        if (ecc.badblocks != last_ecc.badblocks)
+            printf("ecc badblocks, %u, at %llx\n", ecc.badblocks - last_ecc.badblocks, pos);
+        if (ecc.bbtblocks != last_ecc.bbtblocks)
+            printf("ecc bbtblocks, %u, at %llx\n", ecc.bbtblocks - last_ecc.bbtblocks, pos);
+
+        oob_fixed = (uint8_t *)oob_data;
+        for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES; i++) {
+            int len = ecclayout.oobfree[i].length;
+            if (oob_fixed + len > oobbuf.ptr)
+                len = oobbuf.ptr - oob_fixed;
+            if (len) {
+                memcpy(oob_fixed, oobbuf.ptr + ecclayout.oobfree[i].offset, len);
+                oob_fixed += len;
+            }
+        }
+
+        if (outfd >= 0) {
+            ret = write(outfd, buffer, mtdinfo.writesize + spare_size);
+            if (ret < (int)(mtdinfo.writesize + spare_size)) {
+                fprintf(stderr, "short write at %llx, %d\n", pos, ret);
+                close(outfd);
+                outfd = -1;
+            }
+            if (ecc.corrected != last_ecc.corrected)
+                fprintf(statusfile, "%08llx: ecc corrected\n", opos);
+            if (ecc.failed != last_ecc.failed)
+                fprintf(statusfile, "%08llx: ecc failed\n", opos);
+            if (bad_block == 1)
+                fprintf(statusfile, "%08llx: badblock\n", opos);
+            if (bad_block == 2)
+                fprintf(statusfile, "%08llx: read error\n", opos);
+            opos += mtdinfo.writesize + spare_size;
+        }
+
+        last_ecc = ecc;
+        page_count++;
+        if (test_empty(buffer, mtdinfo.writesize + mtdinfo.oobsize + spare_size))
+            empty_pages++;
+        else if (verbose > 2 || (verbose > 1 && !(pos & (mtdinfo.erasesize - 1))))
+            printf("page at %llx (%d oobbytes): %08x %08x %08x %08x "
+                   "%08x %08x %08x %08x\n", pos, oobbuf.start,
+                   oob_data[0], oob_data[1], oob_data[2], oob_data[3],
+                   oob_data[4], oob_data[5], oob_data[6], oob_data[7]);
+    }
+
+    if (outfd >= 0) {
+        fprintf(statusfile, "read %d pages, %d empty\n", page_count, empty_pages);
+        fprintf(statusfile, "total ecc corrected, %u\n", ecc.corrected - initial_ecc.corrected);
+        fprintf(statusfile, "total ecc failed, %u\n", ecc.failed - initial_ecc.failed);
+        fprintf(statusfile, "total ecc badblocks, %u\n", ecc.badblocks - initial_ecc.badblocks);
+        fprintf(statusfile, "total ecc bbtblocks, %u\n", ecc.bbtblocks - initial_ecc.bbtblocks);
+    }
+    if (verbose) {
+        printf("total ecc corrected, %u\n", ecc.corrected - initial_ecc.corrected);
+        printf("total ecc failed, %u\n", ecc.failed - initial_ecc.failed);
+        printf("total ecc badblocks, %u\n", ecc.badblocks - initial_ecc.badblocks);
+        printf("total ecc bbtblocks, %u\n", ecc.bbtblocks - initial_ecc.bbtblocks);
+    }
+    printf("read %d pages, %d empty\n", page_count, empty_pages);
+
+    return 0;
+}
+
diff --git a/toolbox/newfs_msdos.c b/toolbox/newfs_msdos.c
index 4483cc0..8e611c6 100644
--- a/toolbox/newfs_msdos.c
+++ b/toolbox/newfs_msdos.c
@@ -235,35 +235,6 @@
 static void usage(void);
 
 #ifdef ANDROID
-static void err(int val, const char *fmt, ...) {
-    va_list ap;
-    va_start(ap, fmt);
-    char *fmt2;
-    asprintf(&fmt2, "%s\n", fmt);
-    vfprintf(stderr, fmt2, ap);
-    free(fmt2);
-    va_end(ap);
-}
-
-static void errx(int val, const char *fmt, ...) {
-    va_list ap;
-    va_start(ap, fmt);
-    char *fmt2;
-    asprintf(&fmt2, "%s\n", fmt);
-    vfprintf(stderr, fmt2, ap);
-    free(fmt2);
-    va_end(ap);
-}
-
-static void warnx(const char *fmt, ...) {
-    va_list ap;
-    va_start(ap, fmt);
-    char *fmt2;
-    asprintf(&fmt2, "%s\n", fmt);
-    vfprintf(stderr, fmt2, ap);
-    free(fmt2);
-    va_end(ap);
-}
 #define powerof2(x)     ((((x) - 1) & (x)) == 0)
 #define howmany(x, y)   (((x) + ((y) - 1)) / (y))
 #define MAX(x,y) ((x) > (y) ? (x) : (y))
@@ -745,8 +716,10 @@
 	    }
 	    if ((n = write(fd, img, bpb.bps)) == -1)
 		err(1, "%s", fname);
-	    if ((unsigned)n != bpb.bps)
+	    if ((unsigned)n != bpb.bps) {
 		errx(1, "%s: can't write sector %u", fname, lsn);
+                exit(1);
+            }
 	}
     }
     return 0;
@@ -811,20 +784,31 @@
     struct hd_geometry geom;
 
     if (ioctl(fd, BLKSSZGET, &bpb->bps)) {
-        fprintf(stderr, "Error getting bytes / sector (%s)", strerror(errno));
+        fprintf(stderr, "Error getting bytes / sector (%s)\n", strerror(errno));
         exit(1);
     }
 
     ckgeom(fname, bpb->bps, "bytes/sector");
 
     if (ioctl(fd, BLKGETSIZE, &bpb->bsec)) {
-        fprintf(stderr, "Error getting blocksize (%s)", strerror(errno));
+        fprintf(stderr, "Error getting blocksize (%s)\n", strerror(errno));
         exit(1);
     }
 
     if (ioctl(fd, HDIO_GETGEO, &geom)) {
-        fprintf(stderr, "Error getting gemoetry (%s)", strerror(errno));
-        exit(1);
+        fprintf(stderr, "Error getting gemoetry (%s) - trying sane values\n", strerror(errno));
+        geom.heads = 64;
+        geom.sectors = 63;
+    }
+
+    if (!geom.heads) {
+        printf("Bogus heads from kernel - setting sane value\n");
+        geom.heads = 64;
+    }
+
+    if (!geom.sectors) {
+        printf("Bogus sectors from kernel - setting sane value\n");
+        geom.sectors = 63;
     }
 
     bpb->spt = geom.sectors;
diff --git a/vold/Android.mk b/vold/Android.mk
index 3dd9f87..1288626 100644
--- a/vold/Android.mk
+++ b/vold/Android.mk
@@ -1,3 +1,6 @@
+BUILD_VOLD := false
+ifeq ($(BUILD_VOLD),true)
+
 LOCAL_PATH:= $(call my-dir)
 
 include $(CLEAR_VARS)
@@ -30,3 +33,5 @@
 LOCAL_SHARED_LIBRARIES := libcutils
 
 include $(BUILD_EXECUTABLE)
+
+endif # ifeq ($(BUILD_VOLD),true)