Merge "Remove definitions that are now in bionic libc"
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 63bf97a..203c006 100644
--- a/adb/usb_vendors.c
+++ b/adb/usb_vendors.c
@@ -53,6 +53,8 @@
 #define VENDOR_ID_SONY_ERICSSON 0x0FCE
 // Foxconn's USB Vendor ID
 #define VENDOR_ID_FOXCONN       0x0489
+// Dell's USB Vendor ID
+#define VENDOR_ID_DELL          0x413c
 
 
 /** built-in vendor list */
@@ -66,6 +68,7 @@
     VENDOR_ID_ACER,
     VENDOR_ID_SONY_ERICSSON,
     VENDOR_ID_FOXCONN,
+    VENDOR_ID_DELL,
 };
 
 #define BUILT_IN_VENDOR_COUNT    (sizeof(builtInVendorIds)/sizeof(builtInVendorIds[0]))
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/rootdir/init.rc b/rootdir/init.rc
index c39af6c..cd977e2 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -45,7 +45,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
@@ -267,6 +267,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