Merge "Add 'adb backup' for pulling a full backup tarfile to the host"
diff --git a/adb/commandline.c b/adb/commandline.c
index f8cdbf4..733cbff 100644
--- a/adb/commandline.c
+++ b/adb/commandline.c
@@ -98,7 +98,7 @@
         "                                 Port 5555 is used by default if no port number is specified.\n"
         " disconnect [<host>[:<port>]]  - disconnect from a TCP/IP device.\n"
         "                                 Port 5555 is used by default if no port number is specified.\n"
-        "                                 Using this ocmmand with no additional arguments\n"
+        "                                 Using this command with no additional arguments\n"
         "                                 will disconnect from all connected TCP/IP devices.\n"
         "\n"
         "device commands:\n"
diff --git a/fastboot/usb_linux.c b/fastboot/usb_linux.c
index 78b7b98..1ba87e6 100644
--- a/fastboot/usb_linux.c
+++ b/fastboot/usb_linux.c
@@ -61,6 +61,11 @@
 #define DBG1(x...)
 #endif
 
+/* The max bulk size for linux is 16384 which is defined
+ * in drivers/usb/core/devio.c.
+ */
+#define MAX_USBFS_BULK_SIZE (16 * 1024)
+
 struct usb_handle 
 {
     char fname[64];
@@ -289,7 +294,7 @@
     
     while(len > 0) {
         int xfer;
-        xfer = (len > 4096) ? 4096 : len;
+        xfer = (len > MAX_USBFS_BULK_SIZE) ? MAX_USBFS_BULK_SIZE : len;
         
         bulk.ep = h->ep_out;
         bulk.len = xfer;
@@ -323,7 +328,7 @@
     }
     
     while(len > 0) {
-        int xfer = (len > 4096) ? 4096 : len;
+        int xfer = (len > MAX_USBFS_BULK_SIZE) ? MAX_USBFS_BULK_SIZE : len;
         
         bulk.ep = h->ep_in;
         bulk.len = xfer;
diff --git a/fastboot/usb_windows.c b/fastboot/usb_windows.c
index 54008a4..1050293 100644
--- a/fastboot/usb_windows.c
+++ b/fastboot/usb_windows.c
@@ -42,6 +42,7 @@
 #define DBG(x...)
 #endif
 
+#define MAX_USBFS_BULK_SIZE (1024 * 1024)
 
 /** Structure usb_handle describes our connection to the usb device via
   AdbWinApi.dll. This structure is returned from usb_open() routine and
@@ -160,7 +161,7 @@
     if (NULL != handle) {
         // Perform write
         while(len > 0) {
-            int xfer = (len > 4096) ? 4096 : len;
+            int xfer = (len > MAX_USBFS_BULK_SIZE) ? MAX_USBFS_BULK_SIZE : len;
             ret = AdbWriteEndpointSync(handle->adb_write_pipe,
                                    (void*)data,
                                    (unsigned long)xfer,
@@ -200,7 +201,7 @@
     DBG("usb_read %d\n", len);
     if (NULL != handle) {
         while (1) {
-            int xfer = (len > 4096) ? 4096 : len;
+            int xfer = (len > MAX_USBFS_BULK_SIZE) ? MAX_USBFS_BULK_SIZE : len;
 
 	        ret = AdbReadEndpointSync(handle->adb_read_pipe,
 	                              (void*)data,
diff --git a/include/cutils/native_handle.h b/include/cutils/native_handle.h
index 89d6b65..268c5d3 100644
--- a/include/cutils/native_handle.h
+++ b/include/cutils/native_handle.h
@@ -21,7 +21,7 @@
 extern "C" {
 #endif
 
-typedef struct
+typedef struct native_handle
 {
     int version;        /* sizeof(native_handle_t) */
     int numFds;         /* number of file-descriptors at &data[0] */
@@ -29,10 +29,6 @@
     int data[0];        /* numFds + numInts ints */
 } native_handle_t;
 
-
-/* keep the old definition for backward source-compatibility */
-typedef native_handle_t native_handle;
-
 /*
  * native_handle_close
  * 
diff --git a/include/cutils/str_parms.h b/include/cutils/str_parms.h
new file mode 100644
index 0000000..247c996
--- /dev/null
+++ b/include/cutils/str_parms.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2011 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 __CUTILS_STR_PARMS_H
+#define __CUTILS_STR_PARMS_H
+
+#include <stdint.h>
+
+struct str_parms;
+
+struct str_parms *str_parms_create(void);
+struct str_parms *str_parms_create_str(const char *_string);
+void str_parms_destroy(struct str_parms *str_parms);
+
+void str_parms_del(struct str_parms *str_parms, const char *key);
+
+int str_parms_add_str(struct str_parms *str_parms, const char *key,
+                      const char *value);
+int str_parms_add_int(struct str_parms *str_parms, const char *key, int value);
+
+int str_parms_add_float(struct str_parms *str_parms, const char *key,
+                        float value);
+
+int str_parms_get_str(struct str_parms *str_parms, const char *key,
+                      char *out_val, int len);
+int str_parms_get_int(struct str_parms *str_parms, const char *key,
+                      int *out_val);
+int str_parms_get_float(struct str_parms *str_parms, const char *key,
+                        float *out_val);
+
+char *str_parms_to_str(struct str_parms *str_parms);
+
+/* debug */
+void str_parms_dump(struct str_parms *str_parms);
+
+#endif /* __CUTILS_STR_PARMS_H */
diff --git a/include/cutils/uevent.h b/include/cutils/uevent.h
new file mode 100644
index 0000000..587149c
--- /dev/null
+++ b/include/cutils/uevent.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2011 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 __CUTILS_UEVENT_H
+#define __CUTILS_UEVENT_H
+
+#include <sys/socket.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ssize_t uevent_checked_recv(int socket, void *buffer, size_t length);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CUTILS_UEVENT_H */
diff --git a/include/system/camera.h b/include/system/camera.h
new file mode 100644
index 0000000..58e0c6f
--- /dev/null
+++ b/include/system/camera.h
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2011 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 SYSTEM_CORE_INCLUDE_ANDROID_CAMERA_H
+#define SYSTEM_CORE_INCLUDE_ANDROID_CAMERA_H
+
+#include <stdint.h>
+#include <sys/cdefs.h>
+#include <sys/types.h>
+#include <cutils/native_handle.h>
+#include <hardware/hardware.h>
+#include <hardware/gralloc.h>
+
+__BEGIN_DECLS
+
+/**
+ * A set of bit masks for specifying how the received preview frames are
+ * handled before the previewCallback() call.
+ *
+ * The least significant 3 bits of an "int" value are used for this purpose:
+ *
+ * ..... 0 0 0
+ *       ^ ^ ^
+ *       | | |---------> determine whether the callback is enabled or not
+ *       | |-----------> determine whether the callback is one-shot or not
+ *       |-------------> determine whether the frame is copied out or not
+ *
+ * WARNING: When a frame is sent directly without copying, it is the frame
+ * receiver's responsiblity to make sure that the frame data won't get
+ * corrupted by subsequent preview frames filled by the camera. This flag is
+ * recommended only when copying out data brings significant performance price
+ * and the handling/processing of the received frame data is always faster than
+ * the preview frame rate so that data corruption won't occur.
+ *
+ * For instance,
+ * 1. 0x00 disables the callback. In this case, copy out and one shot bits
+ *    are ignored.
+ * 2. 0x01 enables a callback without copying out the received frames. A
+ *    typical use case is the Camcorder application to avoid making costly
+ *    frame copies.
+ * 3. 0x05 is enabling a callback with frame copied out repeatedly. A typical
+ *    use case is the Camera application.
+ * 4. 0x07 is enabling a callback with frame copied out only once. A typical
+ *    use case is the Barcode scanner application.
+ */
+
+enum {
+    CAMERA_FRAME_CALLBACK_FLAG_ENABLE_MASK = 0x01,
+    CAMERA_FRAME_CALLBACK_FLAG_ONE_SHOT_MASK = 0x02,
+    CAMERA_FRAME_CALLBACK_FLAG_COPY_OUT_MASK = 0x04,
+    /** Typical use cases */
+    CAMERA_FRAME_CALLBACK_FLAG_NOOP = 0x00,
+    CAMERA_FRAME_CALLBACK_FLAG_CAMCORDER = 0x01,
+    CAMERA_FRAME_CALLBACK_FLAG_CAMERA = 0x05,
+    CAMERA_FRAME_CALLBACK_FLAG_BARCODE_SCANNER = 0x07
+};
+
+/** msgType in notifyCallback and dataCallback functions */
+enum {
+    CAMERA_MSG_ERROR = 0x0001,
+    CAMERA_MSG_SHUTTER = 0x0002,
+    CAMERA_MSG_FOCUS = 0x0004,
+    CAMERA_MSG_ZOOM = 0x0008,
+    CAMERA_MSG_PREVIEW_FRAME = 0x0010,
+    CAMERA_MSG_VIDEO_FRAME = 0x0020,
+    CAMERA_MSG_POSTVIEW_FRAME = 0x0040,
+    CAMERA_MSG_RAW_IMAGE = 0x0080,
+    CAMERA_MSG_COMPRESSED_IMAGE = 0x0100,
+    CAMERA_MSG_RAW_IMAGE_NOTIFY = 0x0200,
+    CAMERA_MSG_ALL_MSGS = 0xFFFF
+};
+
+/** cmdType in sendCommand functions */
+enum {
+    CAMERA_CMD_START_SMOOTH_ZOOM = 1,
+    CAMERA_CMD_STOP_SMOOTH_ZOOM = 2,
+    /** Set the clockwise rotation of preview display (setPreviewDisplay) in
+     * degrees. This affects the preview frames and the picture displayed after
+     * snapshot. This method is useful for portrait mode applications. Note
+     * that preview display of front-facing cameras is flipped horizontally
+     * before the rotation, that is, the image is reflected along the central
+     * vertical axis of the camera sensor. So the users can see themselves as
+     * looking into a mirror.
+     *
+     * This does not affect the order of byte array of
+     * CAMERA_MSG_PREVIEW_FRAME, CAMERA_MSG_VIDEO_FRAME,
+     * CAMERA_MSG_POSTVIEW_FRAME, CAMERA_MSG_RAW_IMAGE, or
+     * CAMERA_MSG_COMPRESSED_IMAGE. This is not allowed to be set during
+     * preview
+     */
+    CAMERA_CMD_SET_DISPLAY_ORIENTATION = 3,
+
+    /** cmdType to disable/enable shutter sound. In sendCommand passing arg1 =
+     * 0 will disable, while passing arg1 = 1 will enable the shutter sound.
+     */
+    CAMERA_CMD_ENABLE_SHUTTER_SOUND = 4,
+
+    /* cmdType to play recording sound */
+    CAMERA_CMD_PLAY_RECORDING_SOUND = 5,
+};
+
+/** camera fatal errors */
+enum {
+    CAMERA_ERROR_UNKNOWN = 1,
+    CAMERA_ERROR_SERVER_DIED = 100
+};
+
+enum {
+    CAMERA_FACING_BACK = 0, /** The facing of the camera is opposite to that of
+                 * the screen. */
+    CAMERA_FACING_FRONT = 1 /** The facing of the camera is the same as that of
+                 * the screen. */
+};
+
+__END_DECLS
+
+#endif /* SYSTEM_CORE_INCLUDE_ANDROID_CAMERA_H */
diff --git a/include/system/graphics.h b/include/system/graphics.h
new file mode 100644
index 0000000..fab6ec9
--- /dev/null
+++ b/include/system/graphics.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2011 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 SYSTEM_CORE_INCLUDE_ANDROID_GRAPHICS_H
+#define SYSTEM_CORE_INCLUDE_ANDROID_GRAPHICS_H
+
+__BEGIN_DECLS
+
+/**
+ * pixel format definitions
+ */
+
+enum {
+    HAL_PIXEL_FORMAT_RGBA_8888          = 1,
+    HAL_PIXEL_FORMAT_RGBX_8888          = 2,
+    HAL_PIXEL_FORMAT_RGB_888            = 3,
+    HAL_PIXEL_FORMAT_RGB_565            = 4,
+    HAL_PIXEL_FORMAT_BGRA_8888          = 5,
+    HAL_PIXEL_FORMAT_RGBA_5551          = 6,
+    HAL_PIXEL_FORMAT_RGBA_4444          = 7,
+
+    /* 0x8 - 0xFF range unavailable */
+
+    /*
+     * 0x100 - 0x1FF
+     *
+     * This range is reserved for pixel formats that are specific to the HAL
+     * implementation.  Implementations can use any value in this range to
+     * communicate video pixel formats between their HAL modules.  These formats
+     * must not have an alpha channel.  Additionally, an EGLimage created from a
+     * gralloc buffer of one of these formats must be supported for use with the
+     * GL_OES_EGL_image_external OpenGL ES extension.
+     */
+
+    /*
+     * Android YUV format:
+     *
+     * This format is exposed outside of the HAL to software
+     * decoders and applications.
+     * EGLImageKHR must support it in conjunction with the
+     * OES_EGL_image_external extension.
+     *
+     * YV12 is 4:2:0 YCrCb planar format comprised of a WxH Y plane followed
+     * by (W/2) x (H/2) Cr and Cb planes.
+     *
+     * This format assumes
+     * - an even width
+     * - an even height
+     * - a horizontal stride multiple of 16 pixels
+     * - a vertical stride equal to the height
+     *
+     *   y_size = stride * height
+     *   c_size = ALIGN(stride/2, 16) * height/2
+     *   size = y_size + c_size * 2
+     *   cr_offset = y_size
+     *   cb_offset = y_size + c_size
+     *
+     */
+    HAL_PIXEL_FORMAT_YV12   = 0x32315659, // YCrCb 4:2:0 Planar
+
+
+
+    /* Legacy formats (deprecated), used by ImageFormat.java */
+    HAL_PIXEL_FORMAT_YCbCr_422_SP       = 0x10, // NV16
+    HAL_PIXEL_FORMAT_YCrCb_420_SP       = 0x11, // NV21
+    HAL_PIXEL_FORMAT_YCbCr_422_I        = 0x14, // YUY2
+};
+
+
+/**
+ * Transformation definitions
+ *
+ * IMPORTANT NOTE:
+ * HAL_TRANSFORM_ROT_90 is applied CLOCKWISE and AFTER HAL_TRANSFORM_FLIP_{H|V}.
+ *
+ */
+
+enum {
+    /* flip source image horizontally (around the vertical axis) */
+    HAL_TRANSFORM_FLIP_H    = 0x01,
+    /* flip source image vertically (around the horizontal axis)*/
+    HAL_TRANSFORM_FLIP_V    = 0x02,
+    /* rotate source image 90 degrees clockwise */
+    HAL_TRANSFORM_ROT_90    = 0x04,
+    /* rotate source image 180 degrees */
+    HAL_TRANSFORM_ROT_180   = 0x03,
+    /* rotate source image 270 degrees clockwise */
+    HAL_TRANSFORM_ROT_270   = 0x07,
+};
+
+__END_DECLS
+
+#endif /* SYSTEM_CORE_INCLUDE_ANDROID_GRAPHICS_H */
diff --git a/include/system/window.h b/include/system/window.h
new file mode 100644
index 0000000..4b0381b
--- /dev/null
+++ b/include/system/window.h
@@ -0,0 +1,457 @@
+/*
+ * Copyright (C) 2011 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 SYSTEM_CORE_INCLUDE_ANDROID_WINDOW_H
+#define SYSTEM_CORE_INCLUDE_ANDROID_WINDOW_H
+
+#include <stdint.h>
+#include <sys/cdefs.h>
+#include <system/graphics.h>
+#include <cutils/native_handle.h>
+
+__BEGIN_DECLS
+
+/*****************************************************************************/
+
+#define ANDROID_NATIVE_MAKE_CONSTANT(a,b,c,d) \
+    (((unsigned)(a)<<24)|((unsigned)(b)<<16)|((unsigned)(c)<<8)|(unsigned)(d))
+
+#define ANDROID_NATIVE_WINDOW_MAGIC \
+    ANDROID_NATIVE_MAKE_CONSTANT('_','w','n','d')
+
+#define ANDROID_NATIVE_BUFFER_MAGIC \
+    ANDROID_NATIVE_MAKE_CONSTANT('_','b','f','r')
+
+// ---------------------------------------------------------------------------
+
+typedef const native_handle_t* buffer_handle_t;
+
+// ---------------------------------------------------------------------------
+
+typedef struct android_native_rect_t
+{
+    int32_t left;
+    int32_t top;
+    int32_t right;
+    int32_t bottom;
+} android_native_rect_t;
+
+// ---------------------------------------------------------------------------
+
+typedef struct android_native_base_t
+{
+    /* a magic value defined by the actual EGL native type */
+    int magic;
+
+    /* the sizeof() of the actual EGL native type */
+    int version;
+
+    void* reserved[4];
+
+    /* reference-counting interface */
+    void (*incRef)(struct android_native_base_t* base);
+    void (*decRef)(struct android_native_base_t* base);
+} android_native_base_t;
+
+typedef struct ANativeWindowBuffer
+{
+#ifdef __cplusplus
+    ANativeWindowBuffer() {
+        common.magic = ANDROID_NATIVE_BUFFER_MAGIC;
+        common.version = sizeof(ANativeWindowBuffer);
+        memset(common.reserved, 0, sizeof(common.reserved));
+    }
+
+    // Implement the methods that sp<ANativeWindowBuffer> expects so that it
+    // can be used to automatically refcount ANativeWindowBuffer's.
+    void incStrong(const void* id) const {
+        common.incRef(const_cast<android_native_base_t*>(&common));
+    }
+    void decStrong(const void* id) const {
+        common.decRef(const_cast<android_native_base_t*>(&common));
+    }
+#endif
+
+    struct android_native_base_t common;
+
+    int width;
+    int height;
+    int stride;
+    int format;
+    int usage;
+
+    void* reserved[2];
+
+    buffer_handle_t handle;
+
+    void* reserved_proc[8];
+} ANativeWindowBuffer_t;
+
+// Old typedef for backwards compatibility.
+typedef ANativeWindowBuffer_t android_native_buffer_t;
+
+// ---------------------------------------------------------------------------
+
+/* attributes queriable with query() */
+enum {
+    NATIVE_WINDOW_WIDTH     = 0,
+    NATIVE_WINDOW_HEIGHT,
+    NATIVE_WINDOW_FORMAT,
+
+    /* The minimum number of buffers that must remain un-dequeued after a buffer
+     * has been queued.  This value applies only if set_buffer_count was used to
+     * override the number of buffers and if a buffer has since been queued.
+     * Users of the set_buffer_count ANativeWindow method should query this
+     * value before calling set_buffer_count.  If it is necessary to have N
+     * buffers simultaneously dequeued as part of the steady-state operation,
+     * and this query returns M then N+M buffers should be requested via
+     * native_window_set_buffer_count.
+     *
+     * Note that this value does NOT apply until a single buffer has been
+     * queued.  In particular this means that it is possible to:
+     *
+     * 1. Query M = min undequeued buffers
+     * 2. Set the buffer count to N + M
+     * 3. Dequeue all N + M buffers
+     * 4. Cancel M buffers
+     * 5. Queue, dequeue, queue, dequeue, ad infinitum
+     */
+    NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
+
+    /* Check whether queueBuffer operations on the ANativeWindow send the buffer
+     * to the window compositor.  The query sets the returned 'value' argument
+     * to 1 if the ANativeWindow DOES send queued buffers directly to the window
+     * compositor and 0 if the buffers do not go directly to the window
+     * compositor.
+     *
+     * This can be used to determine whether protected buffer content should be
+     * sent to the ANativeWindow.  Note, however, that a result of 1 does NOT
+     * indicate that queued buffers will be protected from applications or users
+     * capturing their contents.  If that behavior is desired then some other
+     * mechanism (e.g. the GRALLOC_USAGE_PROTECTED flag) should be used in
+     * conjunction with this query.
+     */
+    NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER,
+
+    /* Get the concrete type of a ANativeWindow.  See below for the list of
+     * possible return values.
+     *
+     * This query should not be used outside the Android framework and will
+     * likely be removed in the near future.
+     */
+    NATIVE_WINDOW_CONCRETE_TYPE,
+};
+
+/* valid operations for the (*perform)() hook */
+enum {
+    NATIVE_WINDOW_SET_USAGE  = 0,
+    NATIVE_WINDOW_CONNECT,
+    NATIVE_WINDOW_DISCONNECT,
+    NATIVE_WINDOW_SET_CROP,
+    NATIVE_WINDOW_SET_BUFFER_COUNT,
+    NATIVE_WINDOW_SET_BUFFERS_GEOMETRY,
+    NATIVE_WINDOW_SET_BUFFERS_TRANSFORM,
+    NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP,
+};
+
+/* parameter for NATIVE_WINDOW_[DIS]CONNECT */
+enum {
+    NATIVE_WINDOW_API_EGL = 1
+};
+
+/* parameter for NATIVE_WINDOW_SET_BUFFERS_TRANSFORM */
+enum {
+    /* flip source image horizontally */
+    NATIVE_WINDOW_TRANSFORM_FLIP_H = HAL_TRANSFORM_FLIP_H ,
+    /* flip source image vertically */
+    NATIVE_WINDOW_TRANSFORM_FLIP_V = HAL_TRANSFORM_FLIP_V,
+    /* rotate source image 90 degrees clock-wise */
+    NATIVE_WINDOW_TRANSFORM_ROT_90 = HAL_TRANSFORM_ROT_90,
+    /* rotate source image 180 degrees */
+    NATIVE_WINDOW_TRANSFORM_ROT_180 = HAL_TRANSFORM_ROT_180,
+    /* rotate source image 270 degrees clock-wise */
+    NATIVE_WINDOW_TRANSFORM_ROT_270 = HAL_TRANSFORM_ROT_270,
+};
+
+/* values returned by the NATIVE_WINDOW_CONCRETE_TYPE query */
+enum {
+    NATIVE_WINDOW_FRAMEBUFFER,                  // FramebufferNativeWindow
+    NATIVE_WINDOW_SURFACE,                      // Surface
+    NATIVE_WINDOW_SURFACE_TEXTURE_CLIENT,       // SurfaceTextureClient
+};
+
+/* parameter for NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP
+ *
+ * Special timestamp value to indicate that timestamps should be auto-generated
+ * by the native window when queueBuffer is called.  This is equal to INT64_MIN,
+ * defined directly to avoid problems with C99/C++ inclusion of stdint.h.
+ */
+static const int64_t NATIVE_WINDOW_TIMESTAMP_AUTO = (-9223372036854775807LL-1);
+
+struct ANativeWindow
+{
+#ifdef __cplusplus
+    ANativeWindow()
+        : flags(0), minSwapInterval(0), maxSwapInterval(0), xdpi(0), ydpi(0)
+    {
+        common.magic = ANDROID_NATIVE_WINDOW_MAGIC;
+        common.version = sizeof(ANativeWindow);
+        memset(common.reserved, 0, sizeof(common.reserved));
+    }
+
+    // Implement the methods that sp<ANativeWindow> expects so that it
+    // can be used to automatically refcount ANativeWindow's.
+    void incStrong(const void* id) const {
+        common.incRef(const_cast<android_native_base_t*>(&common));
+    }
+    void decStrong(const void* id) const {
+        common.decRef(const_cast<android_native_base_t*>(&common));
+    }
+#endif
+
+    struct android_native_base_t common;
+
+    /* flags describing some attributes of this surface or its updater */
+    const uint32_t flags;
+
+    /* min swap interval supported by this updated */
+    const int   minSwapInterval;
+
+    /* max swap interval supported by this updated */
+    const int   maxSwapInterval;
+
+    /* horizontal and vertical resolution in DPI */
+    const float xdpi;
+    const float ydpi;
+
+    /* Some storage reserved for the OEM's driver. */
+    intptr_t    oem[4];
+
+    /*
+     * Set the swap interval for this surface.
+     *
+     * Returns 0 on success or -errno on error.
+     */
+    int     (*setSwapInterval)(struct ANativeWindow* window,
+                int interval);
+
+    /*
+     * hook called by EGL to acquire a buffer. After this call, the buffer
+     * is not locked, so its content cannot be modified.
+     * this call may block if no buffers are available.
+     *
+     * Returns 0 on success or -errno on error.
+     */
+    int     (*dequeueBuffer)(struct ANativeWindow* window,
+                struct ANativeWindowBuffer** buffer);
+
+    /*
+     * hook called by EGL to lock a buffer. This MUST be called before modifying
+     * the content of a buffer. The buffer must have been acquired with
+     * dequeueBuffer first.
+     *
+     * Returns 0 on success or -errno on error.
+     */
+    int     (*lockBuffer)(struct ANativeWindow* window,
+                struct ANativeWindowBuffer* buffer);
+   /*
+    * hook called by EGL when modifications to the render buffer are done.
+    * This unlocks and post the buffer.
+    *
+    * Buffers MUST be queued in the same order than they were dequeued.
+    *
+    * Returns 0 on success or -errno on error.
+    */
+    int     (*queueBuffer)(struct ANativeWindow* window,
+                struct ANativeWindowBuffer* buffer);
+
+    /*
+     * hook used to retrieve information about the native window.
+     *
+     * Returns 0 on success or -errno on error.
+     */
+    int     (*query)(const struct ANativeWindow* window,
+                int what, int* value);
+
+    /*
+     * hook used to perform various operations on the surface.
+     * (*perform)() is a generic mechanism to add functionality to
+     * ANativeWindow while keeping backward binary compatibility.
+     *
+     * DO NOT CALL THIS HOOK DIRECTLY.  Instead, use the helper functions
+     * defined below.
+     *
+     *  (*perform)() returns -ENOENT if the 'what' parameter is not supported
+     *  by the surface's implementation.
+     *
+     * The valid operations are:
+     *     NATIVE_WINDOW_SET_USAGE
+     *     NATIVE_WINDOW_CONNECT
+     *     NATIVE_WINDOW_DISCONNECT
+     *     NATIVE_WINDOW_SET_CROP
+     *     NATIVE_WINDOW_SET_BUFFER_COUNT
+     *     NATIVE_WINDOW_SET_BUFFERS_GEOMETRY
+     *     NATIVE_WINDOW_SET_BUFFERS_TRANSFORM
+     *     NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP
+     *
+     */
+
+    int     (*perform)(struct ANativeWindow* window,
+                int operation, ... );
+
+    /*
+     * hook used to cancel a buffer that has been dequeued.
+     * No synchronization is performed between dequeue() and cancel(), so
+     * either external synchronization is needed, or these functions must be
+     * called from the same thread.
+     */
+    int     (*cancelBuffer)(struct ANativeWindow* window,
+                struct ANativeWindowBuffer* buffer);
+
+
+    void* reserved_proc[2];
+};
+
+ /* Backwards compatibility: use ANativeWindow (struct ANativeWindow in C).
+  * android_native_window_t is deprecated.
+  */
+typedef struct ANativeWindow ANativeWindow;
+typedef struct ANativeWindow android_native_window_t;
+
+/*
+ *  native_window_set_usage(..., usage)
+ *  Sets the intended usage flags for the next buffers
+ *  acquired with (*lockBuffer)() and on.
+ *  By default (if this function is never called), a usage of
+ *      GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE
+ *  is assumed.
+ *  Calling this function will usually cause following buffers to be
+ *  reallocated.
+ */
+
+static inline int native_window_set_usage(
+        struct ANativeWindow* window, int usage)
+{
+    return window->perform(window, NATIVE_WINDOW_SET_USAGE, usage);
+}
+
+/*
+ * native_window_connect(..., NATIVE_WINDOW_API_EGL)
+ * Must be called by EGL when the window is made current.
+ * Returns -EINVAL if for some reason the window cannot be connected, which
+ * can happen if it's connected to some other API.
+ */
+static inline int native_window_connect(
+        struct ANativeWindow* window, int api)
+{
+    return window->perform(window, NATIVE_WINDOW_CONNECT, api);
+}
+
+/*
+ * native_window_disconnect(..., NATIVE_WINDOW_API_EGL)
+ * Must be called by EGL when the window is made not current.
+ * An error is returned if for instance the window wasn't connected in the
+ * first place.
+ */
+static inline int native_window_disconnect(
+        struct ANativeWindow* window, int api)
+{
+    return window->perform(window, NATIVE_WINDOW_DISCONNECT, api);
+}
+
+/*
+ * native_window_set_crop(..., crop)
+ * Sets which region of the next queued buffers needs to be considered.
+ * A buffer's crop region is scaled to match the surface's size.
+ *
+ * The specified crop region applies to all buffers queued after it is called.
+ *
+ * if 'crop' is NULL, subsequently queued buffers won't be cropped.
+ *
+ * An error is returned if for instance the crop region is invalid,
+ * out of the buffer's bound or if the window is invalid.
+ */
+static inline int native_window_set_crop(
+        struct ANativeWindow* window,
+        android_native_rect_t const * crop)
+{
+    return window->perform(window, NATIVE_WINDOW_SET_CROP, crop);
+}
+
+/*
+ * native_window_set_buffer_count(..., count)
+ * Sets the number of buffers associated with this native window.
+ */
+static inline int native_window_set_buffer_count(
+        struct ANativeWindow* window,
+        size_t bufferCount)
+{
+    return window->perform(window, NATIVE_WINDOW_SET_BUFFER_COUNT, bufferCount);
+}
+
+/*
+ * native_window_set_buffers_geometry(..., int w, int h, int format)
+ * All buffers dequeued after this call will have the geometry specified.
+ * In particular, all buffers will have a fixed-size, independent form the
+ * native-window size. They will be appropriately scaled to the window-size
+ * upon composition.
+ *
+ * If all parameters are 0, the normal behavior is restored. That is,
+ * dequeued buffers following this call will be sized to the window's size.
+ *
+ * Calling this function will reset the window crop to a NULL value, which
+ * disables cropping of the buffers.
+ */
+static inline int native_window_set_buffers_geometry(
+        struct ANativeWindow* window,
+        int w, int h, int format)
+{
+    return window->perform(window, NATIVE_WINDOW_SET_BUFFERS_GEOMETRY,
+            w, h, format);
+}
+
+/*
+ * native_window_set_buffers_transform(..., int transform)
+ * All buffers queued after this call will be displayed transformed according
+ * to the transform parameter specified.
+ */
+static inline int native_window_set_buffers_transform(
+        struct ANativeWindow* window,
+        int transform)
+{
+    return window->perform(window, NATIVE_WINDOW_SET_BUFFERS_TRANSFORM,
+            transform);
+}
+
+/*
+ * native_window_set_buffers_timestamp(..., int64_t timestamp)
+ * All buffers queued after this call will be associated with the timestamp
+ * parameter specified. If the timestamp is set to NATIVE_WINDOW_TIMESTAMP_AUTO
+ * (the default), timestamps will be generated automatically when queueBuffer is
+ * called. The timestamp is measured in nanoseconds, and must be monotonically
+ * increasing.
+ */
+static inline int native_window_set_buffers_timestamp(
+        struct ANativeWindow* window,
+        int64_t timestamp)
+{
+    return window->perform(window, NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP,
+            timestamp);
+}
+
+__END_DECLS
+
+#endif SYSTEM_CORE_INCLUDE_ANDROID_WINDOW_H
diff --git a/init/devices.c b/init/devices.c
index bc36ac1..a200c95 100644
--- a/init/devices.c
+++ b/init/devices.c
@@ -34,6 +34,8 @@
 #include <asm/page.h>
 #include <sys/wait.h>
 
+#include <cutils/uevent.h>
+
 #include "devices.h"
 #include "util.h"
 #include "log.h"
@@ -770,35 +772,9 @@
 #define UEVENT_MSG_LEN  1024
 void handle_device_fd()
 {
-    for(;;) {
-        char msg[UEVENT_MSG_LEN+2];
-        char cred_msg[CMSG_SPACE(sizeof(struct ucred))];
-        struct iovec iov = {msg, sizeof(msg)};
-        struct sockaddr_nl snl;
-        struct msghdr hdr = {&snl, sizeof(snl), &iov, 1, cred_msg, sizeof(cred_msg), 0};
-
-        ssize_t n = recvmsg(device_fd, &hdr, 0);
-        if (n <= 0) {
-            break;
-        }
-
-        if ((snl.nl_groups != 1) || (snl.nl_pid != 0)) {
-            /* ignoring non-kernel netlink multicast message */
-            continue;
-        }
-
-        struct cmsghdr * cmsg = CMSG_FIRSTHDR(&hdr);
-        if (cmsg == NULL || cmsg->cmsg_type != SCM_CREDENTIALS) {
-            /* no sender credentials received, ignore message */
-            continue;
-        }
-
-        struct ucred * cred = (struct ucred *)CMSG_DATA(cmsg);
-        if (cred->uid != 0) {
-            /* message from non-root user, ignore */
-            continue;
-        }
-
+    char msg[UEVENT_MSG_LEN+2];
+    int n;
+    while ((n = uevent_checked_recv(device_fd, msg, UEVENT_MSG_LEN)) > 0) {
         if(n >= UEVENT_MSG_LEN)   /* overflow -- discard */
             continue;
 
diff --git a/libcutils/Android.mk b/libcutils/Android.mk
index b6c5382..3b8cbbb 100644
--- a/libcutils/Android.mk
+++ b/libcutils/Android.mk
@@ -46,7 +46,8 @@
 	properties.c \
 	threads.c \
 	sched_policy.c \
-	iosched_policy.c
+	iosched_policy.c \
+	str_parms.c
 
 commonHostSources := \
         ashmem-host.c
@@ -109,7 +110,7 @@
 # ========================================================
 include $(CLEAR_VARS)
 LOCAL_MODULE := libcutils
-LOCAL_SRC_FILES := $(commonSources) ashmem-dev.c mq.c android_reboot.c
+LOCAL_SRC_FILES := $(commonSources) ashmem-dev.c mq.c android_reboot.c uevent.c
 
 ifeq ($(TARGET_ARCH),arm)
 LOCAL_SRC_FILES += arch-arm/memset32.S
@@ -138,4 +139,12 @@
 LOCAL_CFLAGS += $(targetSmpFlag)
 include $(BUILD_SHARED_LIBRARY)
 
+include $(CLEAR_VARS)
+LOCAL_MODULE := tst_str_parms
+LOCAL_CFLAGS += -DTEST_STR_PARMS
+LOCAL_SRC_FILES := str_parms.c hashmap.c memory.c
+LOCAL_SHARED_LIBRARIES := liblog
+LOCAL_MODULE_TAGS := optional
+include $(BUILD_EXECUTABLE)
+
 endif #!sim
diff --git a/libcutils/hashmap.c b/libcutils/hashmap.c
index e29bc24..65539ea 100644
--- a/libcutils/hashmap.c
+++ b/libcutils/hashmap.c
@@ -310,10 +310,11 @@
     for (i = 0; i < map->bucketCount; i++) {
         Entry* entry = map->buckets[i];
         while (entry != NULL) {
+            Entry *next = entry->next;
             if (!callback(entry->key, entry->value, context)) {
                 return;
             }
-            entry = entry->next;
+            entry = next;
         }
     }
 }
diff --git a/libcutils/str_parms.c b/libcutils/str_parms.c
new file mode 100644
index 0000000..dfa1f73
--- /dev/null
+++ b/libcutils/str_parms.c
@@ -0,0 +1,329 @@
+/*
+ * Copyright (C) 2011 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 LOG_TAG "str_params"
+//#define LOG_NDEBUG 0
+
+#define _GNU_SOURCE 1
+#include <errno.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <cutils/hashmap.h>
+#include <cutils/log.h>
+#include <cutils/memory.h>
+
+#include <cutils/str_parms.h>
+
+struct str_parms {
+    Hashmap *map;
+};
+
+
+static bool str_eq(void *key_a, void *key_b)
+{
+    return !strcmp((const char *)key_a, (const char *)key_b);
+}
+
+/* use djb hash unless we find it inadequate */
+static int str_hash_fn(void *str)
+{
+    uint32_t hash = 5381;
+    char *p;
+
+    for (p = str; p && *p; p++)
+        hash = ((hash << 5) + hash) + *p;
+    return (int)hash;
+}
+
+struct str_parms *str_parms_create(void)
+{
+    struct str_parms *str_parms;
+
+    str_parms = calloc(1, sizeof(struct str_parms));
+    if (!str_parms)
+        return NULL;
+
+    str_parms->map = hashmapCreate(5, str_hash_fn, str_eq);
+    if (!str_parms->map)
+        goto err;
+
+    return str_parms;
+
+err:
+    free(str_parms);
+    return NULL;
+}
+
+static bool remove_pair(void *key, void *value, void *context)
+{
+    struct str_parms *str_parms = context;
+
+    hashmapRemove(str_parms->map, key);
+    free(key);
+    free(value);
+    return true;
+}
+
+void str_parms_destroy(struct str_parms *str_parms)
+{
+    hashmapForEach(str_parms->map, remove_pair, str_parms);
+    hashmapFree(str_parms->map);
+    free(str_parms);
+}
+
+struct str_parms *str_parms_create_str(const char *_string)
+{
+    struct str_parms *str_parms;
+    char *str;
+    char *kvpair;
+    char *tmpstr;
+    int items = 0;
+
+    str_parms = str_parms_create();
+    if (!str_parms)
+        goto err_create_str_parms;
+
+    str = strdup(_string);
+    if (!str)
+        goto err_strdup;
+
+    LOGV("%s: source string == '%s'\n", __func__, _string);
+
+    kvpair = strtok_r(str, ";", &tmpstr);
+    while (kvpair && *kvpair) {
+        char *eq = strchr(kvpair, '='); /* would love strchrnul */
+        char *value;
+        char *key;
+        void *old_val;
+
+        if (eq == kvpair)
+            goto next_pair;
+
+        if (eq) {
+            key = strndup(kvpair, eq - kvpair);
+            if (*(++eq))
+                value = strdup(eq);
+            else
+                value = strdup("");
+        } else {
+            key = strdup(kvpair);
+            value = strdup("");
+        }
+
+        /* if we replaced a value, free it */
+        old_val = hashmapPut(str_parms->map, key, value);
+        if (old_val)
+            free(old_val);
+
+        items++;
+next_pair:
+        kvpair = strtok_r(NULL, ";", &tmpstr);
+    }
+
+    if (!items)
+        LOGV("%s: no items found in string\n", __func__);
+
+    free(str);
+
+    return str_parms;
+
+err_strdup:
+    str_parms_destroy(str_parms);
+err_create_str_parms:
+    return NULL;
+}
+
+void str_parms_del(struct str_parms *str_parms, const char *key)
+{
+    hashmapRemove(str_parms->map, (void *)key);
+}
+
+int str_parms_add_str(struct str_parms *str_parms, const char *key,
+                      const char *value)
+{
+    void *old_val;
+    char *tmp;
+
+    tmp = strdup(value);
+    old_val = hashmapPut(str_parms->map, (void *)key, tmp);
+
+    if (old_val) {
+        free(old_val);
+    } else if (errno == ENOMEM) {
+        free(tmp);
+        return -ENOMEM;
+    }
+    return 0;
+}
+
+int str_parms_add_int(struct str_parms *str_parms, const char *key, int value)
+{
+    char val_str[12];
+    int ret;
+
+    ret = snprintf(val_str, sizeof(val_str), "%d", value);
+    if (ret < 0)
+        return -EINVAL;
+
+    ret = str_parms_add_str(str_parms, key, val_str);
+    return ret;
+}
+
+int str_parms_add_float(struct str_parms *str_parms, const char *key,
+                        float value)
+{
+    char val_str[23];
+    int ret;
+
+    ret = snprintf(val_str, sizeof(val_str), "%.10f", value);
+    if (ret < 0)
+        return -EINVAL;
+
+    ret = str_parms_add_str(str_parms, key, val_str);
+    return ret;
+}
+
+int str_parms_get_str(struct str_parms *str_parms, const char *key, char *val,
+                      int len)
+{
+    char *value;
+
+    value = hashmapGet(str_parms->map, (void *)key);
+    if (value)
+        return strlcpy(val, value, len);
+
+    return -ENOENT;
+}
+
+int str_parms_get_int(struct str_parms *str_parms, const char *key, int *val)
+{
+    char *value;
+    char *end;
+
+    value = hashmapGet(str_parms->map, (void *)key);
+    if (!value)
+        return -ENOENT;
+
+    *val = (int)strtol(value, &end, 0);
+    if (*value != '\0' && *end == '\0')
+        return 0;
+
+    return -EINVAL;
+}
+
+int str_parms_get_float(struct str_parms *str_parms, const char *key,
+                        float *val)
+{
+    float out;
+    char *value;
+    char *end;
+
+    value = hashmapGet(str_parms->map, (void *)key);
+    if (!value)
+        return -ENOENT;
+
+    out = strtof(value, &end);
+    if (*value != '\0' && *end == '\0')
+        return 0;
+
+    return -EINVAL;
+}
+
+static bool combine_strings(void *key, void *value, void *context)
+{
+    char **old_str = context;
+    char *new_str;
+    int ret;
+
+    ret = asprintf(&new_str, "%s%s%s=%s",
+                   *old_str ? *old_str : "",
+                   *old_str ? ";" : "",
+                   (char *)key,
+                   (char *)value);
+    if (*old_str)
+        free(*old_str);
+
+    if (ret >= 0) {
+        *old_str = new_str;
+        return true;
+    }
+
+    *old_str = NULL;
+    return false;
+}
+
+char *str_parms_to_str(struct str_parms *str_parms)
+{
+    char *str = NULL;
+
+    if (hashmapSize(str_parms->map) > 0)
+        hashmapForEach(str_parms->map, combine_strings, &str);
+    else
+        str = strdup("");
+    return str;
+}
+
+static bool dump_entry(void *key, void *value, void *context)
+{
+    LOGI("key: '%s' value: '%s'\n", (char *)key, (char *)value);
+    return true;
+}
+
+void str_parms_dump(struct str_parms *str_parms)
+{
+    hashmapForEach(str_parms->map, dump_entry, str_parms);
+}
+
+#ifdef TEST_STR_PARMS
+static void test_str_parms_str(const char *str)
+{
+    struct str_parms *str_parms;
+    char *out_str;
+    int ret;
+
+    str_parms = str_parms_create_str(str);
+    str_parms_dump(str_parms);
+    out_str = str_parms_to_str(str_parms);
+    str_parms_destroy(str_parms);
+    LOGI("%s: '%s' stringified is '%s'", __func__, str, out_str);
+    free(out_str);
+}
+
+int main(void)
+{
+    struct str_parms *str_parms;
+
+    test_str_parms_str("");
+    test_str_parms_str(";");
+    test_str_parms_str("=");
+    test_str_parms_str("=;");
+    test_str_parms_str("=bar");
+    test_str_parms_str("=bar;");
+    test_str_parms_str("foo=");
+    test_str_parms_str("foo=;");
+    test_str_parms_str("foo=bar");
+    test_str_parms_str("foo=bar;");
+    test_str_parms_str("foo=bar;baz");
+    test_str_parms_str("foo=bar;baz=");
+    test_str_parms_str("foo=bar;baz=bat");
+    test_str_parms_str("foo=bar;baz=bat;");
+
+    return 0;
+}
+#endif
diff --git a/libcutils/uevent.c b/libcutils/uevent.c
new file mode 100644
index 0000000..3533c00
--- /dev/null
+++ b/libcutils/uevent.c
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2011 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 <cutils/uevent.h>
+
+#include <errno.h>
+#include <strings.h>
+
+#include <linux/netlink.h>
+
+/**
+ * Like recv(), but checks that messages actually originate from the kernel.
+ */
+ssize_t uevent_checked_recv(int socket, void *buffer, size_t length) {
+    struct iovec iov = { buffer, length };
+    struct sockaddr_nl addr;
+    char control[CMSG_SPACE(sizeof(struct ucred))];
+    struct msghdr hdr = {
+        &addr,
+        sizeof(addr),
+        &iov,
+        1,
+        control,
+        sizeof(control),
+        0,
+    };
+
+    ssize_t n = recvmsg(socket, &hdr, 0);
+    if (n <= 0) {
+        return n;
+    }
+
+    if (addr.nl_groups == 0 || addr.nl_pid != 0) {
+        /* ignoring non-kernel or unicast netlink message */
+        goto out;
+    }
+
+    struct cmsghdr *cmsg = CMSG_FIRSTHDR(&hdr);
+    if (cmsg == NULL || cmsg->cmsg_type != SCM_CREDENTIALS) {
+        /* ignoring netlink message with no sender credentials */
+        goto out;
+    }
+
+    struct ucred *cred = (struct ucred *)CMSG_DATA(cmsg);
+    if (cred->uid != 0) {
+        /* ignoring netlink message from non-root user */
+        goto out;
+    }
+
+    return n;
+
+out:
+    /* clear residual potentially malicious data */
+    bzero(buffer, length);
+    errno = EIO;
+    return -1;
+}
diff --git a/libsysutils/src/SocketListener.cpp b/libsysutils/src/SocketListener.cpp
index 69ed79e..fcad624 100644
--- a/libsysutils/src/SocketListener.cpp
+++ b/libsysutils/src/SocketListener.cpp
@@ -213,8 +213,9 @@
             it = pendingList->begin();
             SocketClient* c = *it;
             pendingList->erase(it);
-            /* Process it, if false is returned, remove and destroy it */
-            if (!onDataAvailable(c)) {
+            /* Process it, if false is returned and our sockets are
+             * connection-based, remove and destroy it */
+            if (!onDataAvailable(c) && mListen) {
                 /* Remove the client from our array */
                 pthread_mutex_lock(&mClientsLock);
                 for (it = mClients->begin(); it != mClients->end(); ++it) {
diff --git a/rootdir/etc/ueventd.goldfish.rc b/rootdir/etc/ueventd.goldfish.rc
index b5828e7..8de7049 100644
--- a/rootdir/etc/ueventd.goldfish.rc
+++ b/rootdir/etc/ueventd.goldfish.rc
@@ -1,4 +1,5 @@
 # These settings are specific to running under the Android emulator
 /dev/qemu_trace           0666   system     system
+/dev/qemu_pipe            0666   system     system
 /dev/ttyS*                0666   system     system
 /proc                     0666   system     system
diff --git a/toolbox/Android.mk b/toolbox/Android.mk
index 76542a6..d7a675a 100644
--- a/toolbox/Android.mk
+++ b/toolbox/Android.mk
@@ -57,6 +57,10 @@
 	touch \
 	lsof
 
+ifneq (,$(filter userdebug eng,$(TARGET_BUILD_VARIANT)))
+TOOLS += r
+endif
+
 LOCAL_SRC_FILES:= \
 	dynarray.c \
 	toolbox.c \