Merge "To remove drm service from groups of "system" and "root"."
diff --git a/include/sysutils/NetlinkEvent.h b/include/sysutils/NetlinkEvent.h
index b329b09..1ee9849 100644
--- a/include/sysutils/NetlinkEvent.h
+++ b/include/sysutils/NetlinkEvent.h
@@ -30,17 +30,23 @@
     const static int NlActionAdd;
     const static int NlActionRemove;
     const static int NlActionChange;
+    const static int NlActionLinkDown;
+    const static int NlActionLinkUp;
 
     NetlinkEvent();
     virtual ~NetlinkEvent();
 
-    bool decode(char *buffer, int size);
+    bool decode(char *buffer, int size, int format);
     const char *findParam(const char *paramName);
 
     const char *getSubsystem() { return mSubsystem; }
     int getAction() { return mAction; }
 
     void dump();
+
+ protected:
+    bool parseBinaryNetlinkMessage(char *buffer, int size);
+    bool parseAsciiNetlinkMessage(char *buffer, int size);
 };
 
 #endif
diff --git a/include/sysutils/NetlinkListener.h b/include/sysutils/NetlinkListener.h
index 2880046..1cf5f9f 100644
--- a/include/sysutils/NetlinkListener.h
+++ b/include/sysutils/NetlinkListener.h
@@ -22,9 +22,13 @@
 
 class NetlinkListener : public SocketListener {
     char mBuffer[64 * 1024];
+    int mFormat;
 
 public:
-    NetlinkListener(int socket);
+    static const int NETLINK_FORMAT_ASCII = 0;
+    static const int NETLINK_FORMAT_BINARY = 1;
+
+    NetlinkListener(int socket, int format);
     virtual ~NetlinkListener() {}
 
 protected:
diff --git a/include/usbhost/usbhost.h b/include/usbhost/usbhost.h
index 4a8a4fc..7ef7ace 100644
--- a/include/usbhost/usbhost.h
+++ b/include/usbhost/usbhost.h
@@ -39,6 +39,17 @@
     unsigned char*  curr_desc;
 };
 
+struct usb_request
+{
+    struct usb_device *dev;
+    void* buffer;
+    int buffer_length;
+    int actual_length;
+    int max_packet_size;
+    void *private_data; /* struct usbdevfs_urb* */
+    void *client_data;  /* free for use by client */
+};
+
 /* Callback for notification when new USB devices are attached.
  * Return true to exit from usb_host_run.
  */
@@ -81,14 +92,10 @@
 /* Releases all resources associated with the USB device */
 void usb_device_close(struct usb_device *device);
 
-/* Creates a usb_device object for already open USB device.
- * This is intended to facilitate sharing USB devices across address spaces.
- */
+/* Creates a usb_device object for already open USB device */
 struct usb_device *usb_device_new(const char *dev_name, int fd);
 
-/* Returns the file descriptor for the usb_device.  Used in conjunction with
- * usb_device_new() for sharing USB devices across address spaces.
- */
+/* Returns the file descriptor for the usb_device */
 int usb_device_get_fd(struct usb_device *device);
 
 /* Returns the name for the USB device, which is the same as
@@ -170,38 +177,23 @@
 /* Releases the specified interface of a USB device */
 int usb_device_release_interface(struct usb_device *device, unsigned int interface);
 
+/* Creates a new usb_request. */
+struct usb_request *usb_request_new(struct usb_device *dev,
+        const struct usb_endpoint_descriptor *ep_desc);
 
-/* Creates a new usb_endpoint for the specified endpoint of a USB device.
- * This can be used to read or write data across the endpoint.
- */
-struct usb_endpoint *usb_endpoint_open(struct usb_device *dev,
-                const struct usb_endpoint_descriptor *desc);
+/* Releases all resources associated with the request */
+void usb_request_free(struct usb_request *req);
 
-/* Releases all resources associated with the endpoint */
-void usb_endpoint_close(struct usb_endpoint *ep);
+/* Submits a read or write request on the specified device */
+int usb_request_queue(struct usb_request *req);
 
-/* Begins a read or write operation on the specified endpoint */
-int usb_endpoint_queue(struct usb_endpoint *ep, void *data, int len);
-
- /* Waits for the results of a previous usb_endpoint_queue operation on the
-  * specified endpoint.  Returns number of bytes transferred, or a negative
-  * value for error.
+ /* Waits for the results of a previous usb_request_queue operation.
+  * Returns a usb_request, or NULL for error.
   */
-int usb_endpoint_wait(struct usb_device *device, int *out_ep_num);
+struct usb_request *usb_request_wait(struct usb_device *dev);
 
-/* Cancels a pending usb_endpoint_queue() operation on an endpoint. */
-int usb_endpoint_cancel(struct usb_endpoint *ep);
-
-/* Returns the usb_device for the given endpoint */
-struct usb_device *usb_endpoint_get_device(struct usb_endpoint *ep);
-
-/* Returns the endpoint address for the given endpoint */
-int usb_endpoint_number(struct usb_endpoint *ep);
-
-/* Returns the maximum packet size for the given endpoint.
- * For bulk endpoints this should be 512 for highspeed or 64 for fullspeed.
- */
-int usb_endpoint_max_packet(struct usb_endpoint *ep);
+/* Cancels a pending usb_request_queue() operation. */
+int usb_request_cancel(struct usb_request *req);
 
 #ifdef __cplusplus
 }
diff --git a/libsysutils/src/NetlinkEvent.cpp b/libsysutils/src/NetlinkEvent.cpp
index 86c1f42..2e3143d 100644
--- a/libsysutils/src/NetlinkEvent.cpp
+++ b/libsysutils/src/NetlinkEvent.cpp
@@ -19,12 +19,20 @@
 #define LOG_TAG "NetlinkEvent"
 #include <cutils/log.h>
 
+#include <sysutils/NetlinkListener.h>
 #include <sysutils/NetlinkEvent.h>
 
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <linux/rtnetlink.h>
+#include <linux/if.h>
+
 const int NetlinkEvent::NlActionUnknown = 0;
 const int NetlinkEvent::NlActionAdd = 1;
 const int NetlinkEvent::NlActionRemove = 2;
 const int NetlinkEvent::NlActionChange = 3;
+const int NetlinkEvent::NlActionLinkUp = 4;
+const int NetlinkEvent::NlActionLinkDown = 5;
 
 NetlinkEvent::NetlinkEvent() {
     mAction = NlActionUnknown;
@@ -56,7 +64,56 @@
     }
 }
 
-bool NetlinkEvent::decode(char *buffer, int size) {
+/*
+ * Parse an binary message from a NETLINK_ROUTE netlink socket.
+ */
+bool NetlinkEvent::parseBinaryNetlinkMessage(char *buffer, int size) {
+    size_t sz = size;
+    struct nlmsghdr *nh = (struct nlmsghdr *) buffer;
+
+    while (NLMSG_OK(nh, sz) && (nh->nlmsg_type != NLMSG_DONE)) {
+        if (nh->nlmsg_type == RTM_NEWLINK) {
+            int len = nh->nlmsg_len - sizeof(*nh);
+            struct ifinfomsg *ifi;
+
+            if (sizeof(*ifi) <= (size_t) len) {
+                ifi = (ifinfomsg *)NLMSG_DATA(nh);
+
+                if ((ifi->ifi_flags & IFF_LOOPBACK) == 0) {
+                    struct rtattr *rta = (struct rtattr *)
+                      ((char *) ifi + NLMSG_ALIGN(sizeof(*ifi)));
+                    len = NLMSG_PAYLOAD(nh, sizeof(*ifi));
+
+                    while(RTA_OK(rta, len)) {
+                        switch(rta->rta_type) {
+                        case IFLA_IFNAME:
+                            char buffer[16 + IFNAMSIZ];
+                            snprintf(buffer, sizeof(buffer), "INTERFACE=%s",
+                                     (char *) RTA_DATA(rta));
+                            mParams[0] = strdup(buffer);
+                            mAction = (ifi->ifi_flags & IFF_LOWER_UP) ?
+                              NlActionLinkUp : NlActionLinkDown;
+                            mSubsystem = strdup("net");
+                            break;
+                        }
+
+                        rta = RTA_NEXT(rta, len);
+                    }
+                }
+            }
+        }
+
+        nh = NLMSG_NEXT(nh, size);
+    }
+
+    return true;
+}
+
+/*
+ * Parse an ASCII-formatted message from a NETLINK_KOBJECT_UEVENT
+ * netlink socket.
+ */
+bool NetlinkEvent::parseAsciiNetlinkMessage(char *buffer, int size) {
     char *s = buffer;
     char *end;
     int param_idx = 0;
@@ -92,6 +149,14 @@
     return true;
 }
 
+bool NetlinkEvent::decode(char *buffer, int size, int format) {
+  if (format == NetlinkListener::NETLINK_FORMAT_BINARY) {
+    return parseBinaryNetlinkMessage(buffer, size);
+  } else {
+    return parseAsciiNetlinkMessage(buffer, size);
+  }
+}
+
 const char *NetlinkEvent::findParam(const char *paramName) {
     size_t len = strlen(paramName);
     for (int i = 0; mParams[i] && i < NL_PARAMS_MAX; ++i) {
diff --git a/libsysutils/src/NetlinkListener.cpp b/libsysutils/src/NetlinkListener.cpp
index e2a354e..8361120 100644
--- a/libsysutils/src/NetlinkListener.cpp
+++ b/libsysutils/src/NetlinkListener.cpp
@@ -25,8 +25,9 @@
 #include <sysutils/NetlinkListener.h>
 #include <sysutils/NetlinkEvent.h>
 
-NetlinkListener::NetlinkListener(int socket) :
+NetlinkListener::NetlinkListener(int socket, int format) :
                             SocketListener(socket, false) {
+    mFormat = format;
 }
 
 bool NetlinkListener::onDataAvailable(SocketClient *cli)
@@ -40,13 +41,14 @@
     }
 
     NetlinkEvent *evt = new NetlinkEvent();
-    if (!evt->decode(mBuffer, count)) {
+    int err = evt->decode(mBuffer, count, mFormat);
+
+    if (!err) {
         SLOGE("Error decoding NetlinkEvent");
-        goto out;
+    } else {
+        onEvent(evt);
     }
 
-    onEvent(evt);
-out:
     delete evt;
     return true;
 }
diff --git a/libusbhost/Android.mk b/libusbhost/Android.mk
index c9a1c8a..52b4ead 100644
--- a/libusbhost/Android.mk
+++ b/libusbhost/Android.mk
@@ -40,4 +40,7 @@
 
 LOCAL_CFLAGS := -g -DUSE_LIBLOG
 
+# needed for logcat
+LOCAL_SHARED_LIBRARIES := libcutils
+
 include $(BUILD_SHARED_LIBRARY)
diff --git a/libusbhost/usbhost.c b/libusbhost/usbhost.c
index dbc7962..d6736d3 100644
--- a/libusbhost/usbhost.c
+++ b/libusbhost/usbhost.c
@@ -45,12 +45,6 @@
 #include <pthread.h>
 
 #include <linux/usbdevice_fs.h>
-#include <linux/version.h>
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 20)
-#include <linux/usb/ch9.h>
-#else
-#include <linux/usb_ch9.h>
-#endif
 #include <asm/byteorder.h>
 
 #include "usbhost/usbhost.h"
@@ -72,13 +66,6 @@
     int writeable;
 };
 
-struct usb_endpoint
-{
-    struct usb_device *dev;
-    struct usb_endpoint_descriptor  desc;
-    struct usbdevfs_urb urb;
-};
-
 static inline int badname(const char *name)
 {
     while(*name) {
@@ -465,83 +452,89 @@
     return ioctl(device->fd, USBDEVFS_RELEASEINTERFACE, &interface);
 }
 
-struct usb_endpoint *usb_endpoint_open(struct usb_device *dev,
-        const struct usb_endpoint_descriptor *desc)
+struct usb_request *usb_request_new(struct usb_device *dev,
+        const struct usb_endpoint_descriptor *ep_desc)
 {
-    struct usb_endpoint *ep = calloc(1, sizeof(struct usb_endpoint));
-    memcpy(&ep->desc, desc, sizeof(ep->desc));
-    ep->dev = dev;
-    return ep;
+    struct usbdevfs_urb *urb = calloc(1, sizeof(struct usbdevfs_urb));
+    if (!urb)
+        return NULL;
+
+    if ((ep_desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK)
+        urb->type = USBDEVFS_URB_TYPE_BULK;
+    else if ((ep_desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)
+        urb->type = USBDEVFS_URB_TYPE_INTERRUPT;
+    else {
+        D("Unsupported endpoint type %d", ep_desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK);
+        free(urb);
+        return NULL;
+    }
+    urb->endpoint = ep_desc->bEndpointAddress;
+
+    struct usb_request *req = calloc(1, sizeof(struct usb_request));
+    if (!req) {
+        free(urb);
+        return NULL;
+    }
+
+    req->dev = dev;
+    req->max_packet_size = __le16_to_cpu(ep_desc->wMaxPacketSize);
+    req->private_data = urb;
+    urb->usercontext = req;
+
+    return req;
 }
 
-void usb_endpoint_close(struct usb_endpoint *ep)
+void usb_request_free(struct usb_request *req)
 {
-    // cancel IO here?
-    free(ep);
+    free(req->private_data);
+    free(req);
 }
 
-int usb_endpoint_queue(struct usb_endpoint *ep, void *data, int len)
+int usb_request_queue(struct usb_request *req)
 {
-    struct usbdevfs_urb *urb = &ep->urb;
+    struct usbdevfs_urb *urb = (struct usbdevfs_urb*)req->private_data;
     int res;
 
-    D("usb_endpoint_queue\n");
-    memset(urb, 0, sizeof(*urb));
-    urb->type = USBDEVFS_URB_TYPE_BULK;
-    urb->endpoint = ep->desc.bEndpointAddress;
     urb->status = -1;
-    urb->buffer = data;
-    urb->buffer_length = len;
+    urb->buffer = req->buffer;
+    urb->buffer_length = req->buffer_length;
 
     do {
-        res = ioctl(ep->dev->fd, USBDEVFS_SUBMITURB, urb);
+        res = ioctl(req->dev->fd, USBDEVFS_SUBMITURB, urb);
     } while((res < 0) && (errno == EINTR));
 
     return res;
 }
 
-int usb_endpoint_wait(struct usb_device *dev, int *out_ep_num)
+struct usb_request *usb_request_wait(struct usb_device *dev)
 {
-    struct usbdevfs_urb *out = NULL;
+    struct usbdevfs_urb *urb = NULL;
+    struct usb_request *req = NULL;
     int res;
 
     while (1) {
-        res = ioctl(dev->fd, USBDEVFS_REAPURB, &out);
+        int res = ioctl(dev->fd, USBDEVFS_REAPURB, &urb);
         D("USBDEVFS_REAPURB returned %d\n", res);
         if (res < 0) {
             if(errno == EINTR) {
                 continue;
             }
             D("[ reap urb - error ]\n");
-            *out_ep_num = -1;
+            return NULL;
         } else {
             D("[ urb @%p status = %d, actual = %d ]\n",
-                out, out->status, out->actual_length);
-            res = out->actual_length;
-            *out_ep_num = out->endpoint;
+                urb, urb->status, urb->actual_length);
+            req = (struct usb_request*)urb->usercontext;
+            req->actual_length = urb->actual_length;
         }
         break;
     }
-    return res;
+    return req;
 }
 
-int usb_endpoint_cancel(struct usb_endpoint *ep)
+int usb_request_cancel(struct usb_request *req)
 {
-    return ioctl(ep->dev->fd, USBDEVFS_DISCARDURB, &ep->urb);
-}
-
-struct usb_device *usb_endpoint_get_device(struct usb_endpoint *ep)
-{
-    return ep->dev;
-}
-
-int usb_endpoint_number(struct usb_endpoint *ep)
-{
-    return ep->desc.bEndpointAddress;
-}
-
-int usb_endpoint_max_packet(struct usb_endpoint *ep)
-{
-    return __le16_to_cpu(ep->desc.wMaxPacketSize);
+    struct usbdevfs_urb *urb = ((struct usbdevfs_urb*)req->private_data);
+    return ioctl(req->dev->fd, USBDEVFS_DISCARDURB, &urb);
 }
 
diff --git a/rootdir/etc/init.goldfish.rc b/rootdir/etc/init.goldfish.rc
index 6f30843..fa70c2e 100644
--- a/rootdir/etc/init.goldfish.rc
+++ b/rootdir/etc/init.goldfish.rc
@@ -22,6 +22,11 @@
     stop dund
     stop akmd
 
+# start essential services
+    start qemud
+    start goldfish-logcat
+    start goldfish-setup
+
     setprop ro.setupwizard.mode EMULATOR
 
 # enable Google-specific location features,
@@ -42,6 +47,8 @@
 # something else.
 
 service goldfish-setup /system/etc/init.goldfish.sh
+    user root
+    group root
     oneshot
 
 service qemud /system/bin/qemud
@@ -52,7 +59,7 @@
 # program to check wether it runs on the emulator
 # if it does, it redirects its output to the device
 # named by the androidboot.console kernel option
-# if not, is simply exit immediately
+# if not, is simply exits immediately
 
 service goldfish-logcat /system/bin/logcat -Q
     oneshot
diff --git a/rootdir/etc/init.goldfish.sh b/rootdir/etc/init.goldfish.sh
index cfa2c82..c18c032 100755
--- a/rootdir/etc/init.goldfish.sh
+++ b/rootdir/etc/init.goldfish.sh
@@ -18,7 +18,7 @@
     ;;
 esac
 
-num_dns=`getprop ro.kernel.android.ndns`
+num_dns=`getprop ro.kernel.ndns`
 case "$num_dns" in
     2) setprop net.eth0.dns2 10.0.2.4
     ;;
@@ -44,7 +44,7 @@
 
 # this line doesn't really do anything useful. however without it the
 # previous setprop doesn't seem to apply for some really odd reason
-setprop ro.qemu.init.completed 1
+#setprop ro.qemu.init.completed 1
 
 # set up the second interface (for inter-emulator connections)
 # if required
diff --git a/rootdir/etc/ueventd.goldfish.rc b/rootdir/etc/ueventd.goldfish.rc
index e69de29..b5828e7 100644
--- a/rootdir/etc/ueventd.goldfish.rc
+++ b/rootdir/etc/ueventd.goldfish.rc
@@ -0,0 +1,4 @@
+# These settings are specific to running under the Android emulator
+/dev/qemu_trace           0666   system     system
+/dev/ttyS*                0666   system     system
+/proc                     0666   system     system
diff --git a/rootdir/ueventd.rc b/rootdir/ueventd.rc
index a52bdda..c0540a7 100644
--- a/rootdir/ueventd.rc
+++ b/rootdir/ueventd.rc
@@ -63,7 +63,6 @@
 /dev/snd/dsp1             0660   system     audio
 /dev/snd/mixer            0660   system     audio
 /dev/smd0                 0640   radio      radio
-/dev/qemu_trace           0666   system     system
 /dev/qmi                  0640   radio      radio
 /dev/qmi0                 0640   radio      radio
 /dev/qmi1                 0640   radio      radio