am f99e47a0: am 445e5ede: Merge "Switch fastboot to libziparchive."

* commit 'f99e47a0a0604aef2f3b1d07953d5f220662353c':
  Switch fastboot to libziparchive.
diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp
index 2c28139..48d980a 100644
--- a/fastboot/fastboot.cpp
+++ b/fastboot/fastboot.cpp
@@ -285,9 +285,8 @@
             "                                           Can override the fs type and/or\n"
             "                                           size the bootloader reports.\n"
             "  getvar <variable>                        display a bootloader variable\n"
-            "  boot <kernel> [ <ramdisk> [ <second> ] ] download and boot kernel\n"
-            "  flash:raw boot <kernel> [ <ramdisk> [ <second> ] ] create bootimage and \n"
-            "                                           flash it\n"
+            "  boot <kernel> [ <ramdisk> ]              download and boot kernel\n"
+            "  flash:raw boot <kernel> [ <ramdisk> ]    create bootimage and flash it\n"
             "  devices                                  list all connected devices\n"
             "  continue                                 continue with autoboot\n"
             "  reboot [bootloader]                      reboot device, optionally into bootloader\n"
@@ -315,11 +314,10 @@
 }
 
 void *load_bootable_image(const char *kernel, const char *ramdisk,
-                          const char *secondstage, unsigned *sz,
-                          const char *cmdline)
+                          unsigned *sz, const char *cmdline)
 {
-    void *kdata = 0, *rdata = 0, *sdata = 0;
-    unsigned ksize = 0, rsize = 0, ssize = 0;
+    void *kdata = 0, *rdata = 0;
+    unsigned ksize = 0, rsize = 0;
     void *bdata;
     unsigned bsize;
 
@@ -355,18 +353,10 @@
         }
     }
 
-    if (secondstage) {
-        sdata = load_file(secondstage, &ssize);
-        if(sdata == 0) {
-            fprintf(stderr,"cannot load '%s': %s\n", secondstage, strerror(errno));
-            return  0;
-        }
-    }
-
     fprintf(stderr,"creating boot image...\n");
     bdata = mkbootimg(kdata, ksize, kernel_offset,
                       rdata, rsize, ramdisk_offset,
-                      sdata, ssize, second_offset,
+                      0, 0, second_offset,
                       page_size, base_addr, tags_offset, &bsize);
     if(bdata == 0) {
         fprintf(stderr,"failed to create boot.img\n");
@@ -1134,7 +1124,6 @@
         } else if(!strcmp(*argv, "boot")) {
             char *kname = 0;
             char *rname = 0;
-            char *sname = 0;
             skip(1);
             if (argc > 0) {
                 kname = argv[0];
@@ -1144,11 +1133,7 @@
                 rname = argv[0];
                 skip(1);
             }
-            if (argc > 0) {
-                sname = argv[0];
-                skip(1);
-            }
-            data = load_bootable_image(kname, rname, sname, &sz, cmdline);
+            data = load_bootable_image(kname, rname, &sz, cmdline);
             if (data == 0) return 1;
             fb_queue_download("boot.img", data, sz);
             fb_queue_command("boot", "booting");
@@ -1172,18 +1157,14 @@
             char *pname = argv[1];
             char *kname = argv[2];
             char *rname = 0;
-            char *sname = 0;
             require(3);
-            skip(3);
-            if (argc > 0) {
-                rname = argv[0];
-                skip(1);
+            if(argc > 3) {
+                rname = argv[3];
+                skip(4);
+            } else {
+                skip(3);
             }
-            if (argc > 0) {
-                sname = argv[0];
-                skip(1);
-            }
-            data = load_bootable_image(kname, rname, sname, &sz, cmdline);
+            data = load_bootable_image(kname, rname, &sz, cmdline);
             if (data == 0) die("cannot load bootable image");
             fb_queue_flash(pname, data, sz);
         } else if(!strcmp(*argv, "flashall")) {
diff --git a/fs_mgr/fs_mgr_fstab.c b/fs_mgr/fs_mgr_fstab.c
index ab8f128..64f7edc 100644
--- a/fs_mgr/fs_mgr_fstab.c
+++ b/fs_mgr/fs_mgr_fstab.c
@@ -68,6 +68,7 @@
     { "zramsize=",   MF_ZRAMSIZE },
     { "verify",      MF_VERIFY },
     { "noemulatedsd", MF_NOEMULATEDSD },
+    { "notrim",       MF_NOTRIM },
     { "defaults",    0 },
     { 0,             0 },
 };
@@ -432,3 +433,8 @@
 {
     return fstab->fs_mgr_flags & MF_NOEMULATEDSD;
 }
+
+int fs_mgr_is_notrim(struct fstab_rec *fstab)
+{
+    return fstab->fs_mgr_flags & MF_NOTRIM;
+}
diff --git a/fs_mgr/fs_mgr_priv.h b/fs_mgr/fs_mgr_priv.h
index 88a1040..efc7ca5 100644
--- a/fs_mgr/fs_mgr_priv.h
+++ b/fs_mgr/fs_mgr_priv.h
@@ -76,6 +76,7 @@
 #define MF_FORCECRYPT   0x400
 #define MF_NOEMULATEDSD 0x800 /* no emulated sdcard daemon, sd card is the only
                                  external storage */
+#define MF_NOTRIM       0x1000
 
 #define DM_BUF_SIZE 4096
 
diff --git a/fs_mgr/include/fs_mgr.h b/fs_mgr/include/fs_mgr.h
index 0437d45..a7a0bdb 100644
--- a/fs_mgr/include/fs_mgr.h
+++ b/fs_mgr/include/fs_mgr.h
@@ -94,6 +94,7 @@
 int fs_mgr_is_verified(struct fstab_rec *fstab);
 int fs_mgr_is_encryptable(struct fstab_rec *fstab);
 int fs_mgr_is_noemulatedsd(struct fstab_rec *fstab);
+int fs_mgr_is_notrim(struct fstab_rec *fstab);
 int fs_mgr_swapon_all(struct fstab *fstab);
 #ifdef __cplusplus
 }
diff --git a/healthd/healthd.cpp b/healthd/healthd.cpp
index 1fee855..b0002cc 100644
--- a/healthd/healthd.cpp
+++ b/healthd/healthd.cpp
@@ -53,6 +53,7 @@
     .batteryCurrentAvgPath = String8(String8::kEmptyString),
     .batteryChargeCounterPath = String8(String8::kEmptyString),
     .energyCounter = NULL,
+    .boot_min_cap = 0,
     .screen_on = NULL,
 };
 
diff --git a/healthd/healthd.h b/healthd/healthd.h
index 4704f0b..84b6d76 100644
--- a/healthd/healthd.h
+++ b/healthd/healthd.h
@@ -67,6 +67,7 @@
     android::String8 batteryChargeCounterPath;
 
     int (*energyCounter)(int64_t *);
+    int boot_min_cap;
     bool (*screen_on)(android::BatteryProperties *props);
 };
 
diff --git a/healthd/healthd_mode_charger.cpp b/healthd/healthd_mode_charger.cpp
index 9ed5944..352510b 100644
--- a/healthd/healthd_mode_charger.cpp
+++ b/healthd/healthd_mode_charger.cpp
@@ -116,6 +116,7 @@
 
     struct animation *batt_anim;
     gr_surface surf_unknown;
+    int boot_min_cap;
 };
 
 static struct frame batt_anim_frames[] = {
@@ -520,19 +521,29 @@
                     LOGW("[%" PRId64 "] booting from charger mode\n", now);
                     property_set("sys.boot_from_charger_mode", "1");
                 } else {
-                    LOGW("[%" PRId64 "] rebooting\n", now);
-                    android_reboot(ANDROID_RB_RESTART, 0, 0);
+                    if (charger->batt_anim->capacity >= charger->boot_min_cap) {
+                        LOGW("[%" PRId64 "] rebooting\n", now);
+                        android_reboot(ANDROID_RB_RESTART, 0, 0);
+                    } else {
+                        LOGV("[%" PRId64 "] ignore power-button press, battery level "
+                            "less than minimum\n", now);
+                    }
                 }
             } else {
                 /* if the key is pressed but timeout hasn't expired,
                  * make sure we wake up at the right-ish time to check
                  */
                 set_next_key_check(charger, key, POWER_ON_KEY_TIME);
+
+               /* Turn on the display and kick animation on power-key press
+                * rather than on key release
+                */
+                kick_animation(charger->batt_anim);
+                request_suspend(false);
             }
         } else {
             /* if the power key got released, force screen state cycle */
             if (key->pending) {
-                request_suspend(false);
                 kick_animation(charger->batt_anim);
             }
         }
@@ -555,6 +566,11 @@
         return;
 
     if (!charger->charger_connected) {
+
+        /* Last cycle would have stopped at the extreme top of battery-icon
+         * Need to show the correct level corresponding to capacity.
+         */
+        kick_animation(charger->batt_anim);
         request_suspend(false);
         if (charger->next_pwr_check == -1) {
             charger->next_pwr_check = now + UNPLUGGED_SHUTDOWN_TIME;
@@ -705,4 +721,5 @@
     charger->next_key_check = -1;
     charger->next_pwr_check = -1;
     healthd_config = config;
+    charger->boot_min_cap = config->boot_min_cap;
 }
diff --git a/include/netutils/dhcp.h b/include/netutils/dhcp.h
index de6bc82..008dbd8 100644
--- a/include/netutils/dhcp.h
+++ b/include/netutils/dhcp.h
@@ -23,26 +23,18 @@
 __BEGIN_DECLS
 
 extern int do_dhcp(char *iname);
-extern int dhcp_do_request(const char *ifname,
-                          char *ipaddr,
-                          char *gateway,
-                          uint32_t *prefixLength,
-                          char *dns[],
-                          char *server,
-                          uint32_t *lease,
-                          char *vendorInfo,
-                          char *domain,
-                          char *mtu);
-extern int dhcp_do_request_renew(const char *ifname,
-                                char *ipaddr,
-                                char *gateway,
-                                uint32_t *prefixLength,
-                                char *dns[],
-                                char *server,
-                                uint32_t *lease,
-                                char *vendorInfo,
-                                char *domain,
-                                char *mtu);
+extern int dhcp_start(const char *ifname);
+extern int dhcp_start_renew(const char *ifname);
+extern int dhcp_get_results(const char *ifname,
+                            char *ipaddr,
+                            char *gateway,
+                            uint32_t *prefixLength,
+                            char *dns[],
+                            char *server,
+                            uint32_t *lease,
+                            char *vendorInfo,
+                            char *domain,
+                            char *mtu);
 extern int dhcp_stop(const char *ifname);
 extern int dhcp_release_lease(const char *ifname);
 extern char *dhcp_get_errmsg();
diff --git a/include/system/audio.h b/include/system/audio.h
index 181a171..17bf260 100644
--- a/include/system/audio.h
+++ b/include/system/audio.h
@@ -194,7 +194,7 @@
     AUDIO_FORMAT_PCM_SUB_16_BIT          = 0x1, /* DO NOT CHANGE - PCM signed 16 bits */
     AUDIO_FORMAT_PCM_SUB_8_BIT           = 0x2, /* DO NOT CHANGE - PCM unsigned 8 bits */
     AUDIO_FORMAT_PCM_SUB_32_BIT          = 0x3, /* PCM signed .31 fixed point */
-    AUDIO_FORMAT_PCM_SUB_8_24_BIT        = 0x4, /* PCM signed 7.24 fixed point */
+    AUDIO_FORMAT_PCM_SUB_8_24_BIT        = 0x4, /* PCM signed 8.23 fixed point */
     AUDIO_FORMAT_PCM_SUB_FLOAT           = 0x5, /* PCM single-precision floating point */
     AUDIO_FORMAT_PCM_SUB_24_BIT_PACKED   = 0x6, /* PCM signed .23 fixed point packed in 3 bytes */
 } audio_format_pcm_sub_fmt_t;
@@ -872,6 +872,8 @@
 typedef int audio_port_handle_t;
 #define AUDIO_PORT_HANDLE_NONE 0
 
+/* the maximum length for the human-readable device name. i.e. "Alesis iO4"*/
+#define AUDIO_PORT_MAX_NAME_LEN 128
 
 /* maximum audio device address length */
 #define AUDIO_DEVICE_MAX_ADDRESS_LEN 32
@@ -966,11 +968,11 @@
     audio_session_t   session; /* audio session */
 };
 
-
 struct audio_port {
     audio_port_handle_t      id;                /* port unique ID */
     audio_port_role_t        role;              /* sink or source */
     audio_port_type_t        type;              /* device, mix ... */
+    char                     name[AUDIO_PORT_MAX_NAME_LEN];
     unsigned int             num_sample_rates;  /* number of sampling rates in following array */
     unsigned int             sample_rates[AUDIO_PORT_MAX_SAMPLING_RATES];
     unsigned int             num_channel_masks; /* number of channel masks in following array */
diff --git a/include/system/camera.h b/include/system/camera.h
index 7a4dd53..09c915d 100644
--- a/include/system/camera.h
+++ b/include/system/camera.h
@@ -194,7 +194,12 @@
     /** The facing of the camera is opposite to that of the screen. */
     CAMERA_FACING_BACK = 0,
     /** The facing of the camera is the same as that of the screen. */
-    CAMERA_FACING_FRONT = 1
+    CAMERA_FACING_FRONT = 1,
+    /**
+     * The facing of the camera is not fixed relative to the screen.
+     * The cameras with this facing are external cameras, e.g. USB cameras.
+     */
+    CAMERA_FACING_EXTERNAL = 2
 };
 
 enum {
diff --git a/include/system/graphics.h b/include/system/graphics.h
index c3fca97..c9f5950 100644
--- a/include/system/graphics.h
+++ b/include/system/graphics.h
@@ -45,9 +45,12 @@
     /*
      * "linear" color pixel formats:
      *
-     * The pixel formats below contain sRGB data but are otherwise treated
-     * as linear formats, i.e.: no special operation is performed when
-     * reading or writing into a buffer in one of these formats
+     * When used with ANativeWindow, the dataSpace field describes the color
+     * space of the buffer.
+     *
+     * The color space determines, for example, if the formats are linear or
+     * gamma-corrected; or whether any special operations are performed when
+     * reading or writing into a buffer in one of these formats.
      */
     HAL_PIXEL_FORMAT_RGBA_8888          = 1,
     HAL_PIXEL_FORMAT_RGBX_8888          = 2,
@@ -56,28 +59,6 @@
     HAL_PIXEL_FORMAT_BGRA_8888          = 5,
 
     /*
-     * sRGB color pixel formats:
-     *
-     * The red, green and blue components are stored in sRGB space, and converted
-     * to linear space when read, using the standard sRGB to linear equation:
-     *
-     * Clinear = Csrgb / 12.92                  for Csrgb <= 0.04045
-     *         = (Csrgb + 0.055 / 1.055)^2.4    for Csrgb >  0.04045
-     *
-     * When written the inverse transformation is performed:
-     *
-     * Csrgb = 12.92 * Clinear                  for Clinear <= 0.0031308
-     *       = 1.055 * Clinear^(1/2.4) - 0.055  for Clinear >  0.0031308
-     *
-     *
-     *  The alpha component, if present, is always stored in linear space and
-     *  is left unmodified when read or written.
-     *
-     */
-    HAL_PIXEL_FORMAT_sRGB_A_8888        = 0xC,
-    HAL_PIXEL_FORMAT_sRGB_X_8888        = 0xD,
-
-    /*
      * 0x100 - 0x1FF
      *
      * This range is reserved for pixel formats that are specific to the HAL
@@ -111,6 +92,8 @@
      *   cr_offset = y_size
      *   cb_offset = y_size + c_size
      *
+     * When used with ANativeWindow, the dataSpace field describes the color
+     * space of the buffer.
      */
     HAL_PIXEL_FORMAT_YV12   = 0x32315659, // YCrCb 4:2:0 Planar
 
@@ -135,6 +118,8 @@
      *
      *   size = stride * height
      *
+     * When used with ANativeWindow, the dataSpace field describes the color
+     * space of the buffer.
      */
     HAL_PIXEL_FORMAT_Y8     = 0x20203859,
 
@@ -159,6 +144,10 @@
      *
      *   size = stride * height * 2
      *
+     * When used with ANativeWindow, the dataSpace field describes the color
+     * space of the buffer, except that dataSpace field
+     * HAL_DATASPACE_DEPTH indicates that this buffer contains a depth
+     * image where each sample is a distance value measured by a depth camera.
      */
     HAL_PIXEL_FORMAT_Y16    = 0x20363159,
 
@@ -167,7 +156,7 @@
      *
      * This format is exposed outside of the camera HAL to applications.
      *
-     * RAW_SENSOR is a single-channel, 16-bit, little endian  format, typically
+     * RAW16 is a single-channel, 16-bit, little endian format, typically
      * representing raw Bayer-pattern images from an image sensor, with minimal
      * processing.
      *
@@ -193,9 +182,12 @@
      *    - GRALLOC_USAGE_HW_CAMERA_*
      *    - GRALLOC_USAGE_SW_*
      *    - GRALLOC_USAGE_RENDERSCRIPT
+     *
+     * When used with ANativeWindow, the dataSpace should be
+     * HAL_DATASPACE_ARBITRARY, as raw image sensor buffers require substantial
+     * extra metadata to define.
      */
     HAL_PIXEL_FORMAT_RAW16 = 0x20,
-    HAL_PIXEL_FORMAT_RAW_SENSOR = 0x20, // TODO(rubenbrunk): Remove RAW_SENSOR.
 
     /*
      * Android RAW10 format:
@@ -244,6 +236,10 @@
      *    - GRALLOC_USAGE_HW_CAMERA_*
      *    - GRALLOC_USAGE_SW_*
      *    - GRALLOC_USAGE_RENDERSCRIPT
+     *
+     * When used with ANativeWindow, the dataSpace field should be
+     * HAL_DATASPACE_ARBITRARY, as raw image sensor buffers require substantial
+     * extra metadata to define.
      */
     HAL_PIXEL_FORMAT_RAW10 = 0x25,
 
@@ -261,6 +257,10 @@
      *    - GRALLOC_USAGE_HW_CAMERA_*
      *    - GRALLOC_USAGE_SW_*
      *    - GRALLOC_USAGE_RENDERSCRIPT
+     *
+     * When used with ANativeWindow, the dataSpace field should be
+     * HAL_DATASPACE_ARBITRARY, as raw image sensor buffers require substantial
+     * extra metadata to define.
      */
     HAL_PIXEL_FORMAT_RAW_OPAQUE = 0x24,
 
@@ -276,6 +276,16 @@
      *
      * Buffers of this format must have a height of 1, and width equal to their
      * size in bytes.
+     *
+     * When used with ANativeWindow, the mapping of the dataSpace field to
+     * buffer contents for BLOB is as follows:
+     *
+     *  dataSpace value               | Buffer contents
+     * -------------------------------+-----------------------------------------
+     *  HAL_DATASPACE_JFIF            | An encoded JPEG image
+     *  HAL_DATASPACE_DEPTH           | An android_depth_points buffer
+     *  Other                         | Unsupported
+     *
      */
     HAL_PIXEL_FORMAT_BLOB = 0x21,
 
@@ -292,6 +302,8 @@
      * framework will assume that sampling the texture will always return an
      * alpha value of 1.0 (i.e. the buffer contains only opaque pixel values).
      *
+     * When used with ANativeWindow, the dataSpace field describes the color
+     * space of the buffer.
      */
     HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED = 0x22,
 
@@ -311,6 +323,9 @@
      *
      * This format is locked for use by gralloc's (*lock_ycbcr) method, and
      * locking with the (*lock) method will return an error.
+     *
+     * When used with ANativeWindow, the dataSpace field describes the color
+     * space of the buffer.
      */
     HAL_PIXEL_FORMAT_YCbCr_420_888 = 0x23,
 
@@ -355,6 +370,42 @@
 };
 
 /**
+ * Structure used to define depth point clouds for format HAL_PIXEL_FORMAT_BLOB
+ * with dataSpace value of HAL_DATASPACE_DEPTH.
+ * When locking a native buffer of the above format and dataSpace value,
+ * the vaddr pointer can be cast to this structure.
+ *
+ * A variable-length list of (x,y,z) 3D points, as floats.
+ *
+ * @num_points is the number of points in the list
+ *
+ * @xyz_points is the flexible array of floating-point values.
+ *   It contains (num_points) * 3 floats.
+ *
+ *   For example:
+ *     android_depth_points d = get_depth_buffer();
+ *     struct {
+ *       float x; float y; float z;
+ *     } firstPoint, lastPoint;
+ *
+ *     firstPoint.x = d.xyz_points[0];
+ *     firstPoint.y = d.xyz_points[1];
+ *     firstPoint.z = d.xyz_points[2];
+ *     lastPoint.x = d.xyz_points[(d.num_points - 1) * 3 + 0];
+ *     lastPoint.y = d.xyz_points[(d.num_points - 1) * 3 + 1];
+ *     lastPoint.z = d.xyz_points[(d.num_points - 1) * 3 + 2];
+ */
+
+struct android_depth_points {
+    uint32_t num_points;
+
+    /** reserved for future use, set to 0 by gralloc's (*lock)() */
+    uint32_t reserved[8];
+
+    float xyz_points[];
+};
+
+/**
  * Transformation definitions
  *
  * IMPORTANT NOTE:
@@ -378,19 +429,33 @@
 };
 
 /**
- * Colorspace Definitions
+ * Dataspace Definitions
  * ======================
  *
- * Colorspace is the definition of how pixel values should be interpreted.
- * It includes primaries (including white point) and the transfer
- * characteristic function, which describes both gamma curve and numeric
- * range (within the bit depth).
+ * Dataspace is the definition of how pixel values should be interpreted.
+ *
+ * For many formats, this is the colorspace of the image data, which includes
+ * primaries (including white point) and the transfer characteristic function,
+ * which describes both gamma curve and numeric range (within the bit depth).
+ *
+ * Other dataspaces include depth measurement data from a depth camera.
  */
 
-enum {
+typedef enum android_dataspace {
     /*
-     * Arbitrary colorspace with manually defined characteristics.
-     * Colorspace definition must be communicated separately.
+     * Default-assumption data space, when not explicitly specified.
+     *
+     * It is safest to assume the buffer is an image with sRGB primaries and
+     * encoding ranges, but the consumer and/or the producer of the data may
+     * simply be using defaults. No automatic gamma transform should be
+     * expected, except for a possible display gamma transform when drawn to a
+     * screen.
+     */
+    HAL_DATASPACE_UNKNOWN = 0x0,
+
+    /*
+     * Arbitrary dataspace with manually defined characteristics.  Definition
+     * for colorspaces or other meaning must be communicated separately.
      *
      * This is used when specifying primaries, transfer characteristics,
      * etc. separately.
@@ -399,7 +464,57 @@
      * where a colorspace can have separately defined primaries, transfer
      * characteristics, etc.
      */
-    HAL_COLORSPACE_ARBITRARY = 0x1,
+    HAL_DATASPACE_ARBITRARY = 0x1,
+
+    /*
+     * RGB Colorspaces
+     * -----------------
+     *
+     * Primaries are given using (x,y) coordinates in the CIE 1931 definition
+     * of x and y specified by ISO 11664-1.
+     *
+     * Transfer characteristics are the opto-electronic transfer characteristic
+     * at the source as a function of linear optical intensity (luminance).
+     */
+
+    /*
+     * sRGB linear encoding:
+     *
+     * The red, green, and blue components are stored in sRGB space, but
+     * are linear, not gamma-encoded.
+     * The RGB primaries and the white point are the same as BT.709.
+     *
+     * The values are encoded using the full range ([0,255] for 8-bit) for all
+     * components.
+     */
+    HAL_DATASPACE_SRGB_LINEAR = 0x200,
+
+    /*
+     * sRGB gamma encoding:
+     *
+     * The red, green and blue components are stored in sRGB space, and
+     * converted to linear space when read, using the standard sRGB to linear
+     * equation:
+     *
+     * Clinear = Csrgb / 12.92                  for Csrgb <= 0.04045
+     *         = (Csrgb + 0.055 / 1.055)^2.4    for Csrgb >  0.04045
+     *
+     * When written the inverse transformation is performed:
+     *
+     * Csrgb = 12.92 * Clinear                  for Clinear <= 0.0031308
+     *       = 1.055 * Clinear^(1/2.4) - 0.055  for Clinear >  0.0031308
+     *
+     *
+     * The alpha component, if present, is always stored in linear space and
+     * is left unmodified when read or written.
+     *
+     * The RGB primaries and the white point are the same as BT.709.
+     *
+     * The values are encoded using the full range ([0,255] for 8-bit) for all
+     * components.
+     *
+     */
+    HAL_DATASPACE_SRGB = 0x201,
 
     /*
      * YCbCr Colorspaces
@@ -429,7 +544,7 @@
      *  red             0.640   0.330
      *  white (D65)     0.3127  0.3290
      */
-    HAL_COLORSPACE_JFIF = 0x101,
+    HAL_DATASPACE_JFIF = 0x101,
 
     /*
      * ITU-R Recommendation 601 (BT.601) - 625-line
@@ -456,7 +571,7 @@
      *  red             0.640   0.330
      *  white (D65)     0.3127  0.3290
      */
-    HAL_COLORSPACE_BT601_625 = 0x102,
+    HAL_DATASPACE_BT601_625 = 0x102,
 
     /*
      * ITU-R Recommendation 601 (BT.601) - 525-line
@@ -483,7 +598,7 @@
      *  red             0.630   0.340
      *  white (D65)     0.3127  0.3290
      */
-    HAL_COLORSPACE_BT601_525 = 0x103,
+    HAL_DATASPACE_BT601_525 = 0x103,
 
     /*
      * ITU-R Recommendation 709 (BT.709)
@@ -504,8 +619,20 @@
      *  red             0.640   0.330
      *  white (D65)     0.3127  0.3290
      */
-    HAL_COLORSPACE_BT709 = 0x104,
-};
+    HAL_DATASPACE_BT709 = 0x104,
+
+    /*
+     * The buffer contains depth ranging measurements from a depth camera.
+     * This value is valid with formats:
+     *    HAL_PIXEL_FORMAT_Y16: 16-bit single channel depth image.
+     *    HAL_PIXEL_FORMAT_BLOB: A depth point cloud, as
+     *       a variable-length float (x,y,z) coordinate point list.
+     *       The point cloud will be represented with the android_depth_points
+     *       structure.
+     */
+    HAL_DATASPACE_DEPTH = 0x1000
+
+} android_dataspace_t;
 
 #ifdef __cplusplus
 }
diff --git a/include/system/radio.h b/include/system/radio.h
new file mode 100644
index 0000000..a088526
--- /dev/null
+++ b/include/system/radio.h
@@ -0,0 +1,247 @@
+/*
+ * Copyright (C) 2015 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_RADIO_H
+#define ANDROID_RADIO_H
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+
+#define RADIO_NUM_BANDS_MAX     16
+#define RADIO_NUM_SPACINGS_MAX  16
+#define RADIO_STRING_LEN_MAX    128
+
+/*
+ * Radio hardware module class. A given radio hardware module HAL is of one class
+ * only. The platform can not have more than one hardware module of each class.
+ * Current version of the framework only supports RADIO_CLASS_AM_FM.
+ */
+typedef enum {
+    RADIO_CLASS_AM_FM = 0,  /* FM (including HD radio) and AM */
+    RADIO_CLASS_SAT   = 1,  /* Satellite Radio */
+    RADIO_CLASS_DT    = 2,  /* Digital Radio (DAB) */
+} radio_class_t;
+
+/* value for field "type" of radio band described in struct radio_hal_band_config */
+typedef enum {
+    RADIO_BAND_AM     = 0,  /* Amplitude Modulation band: LW, MW, SW */
+    RADIO_BAND_FM     = 1,  /* Frequency Modulation band: FM */
+    RADIO_BAND_FM_HD  = 2,  /* FM HD Radio / DRM (IBOC) */
+    RADIO_BAND_AM_HD  = 3,  /* AM HD Radio / DRM (IBOC) */
+} radio_band_t;
+
+/* RDS variant implemented. A struct radio_hal_fm_band_config can list none or several. */
+enum {
+    RADIO_RDS_NONE   = 0x0,
+    RADIO_RDS_WORLD  = 0x01,
+    RADIO_RDS_US     = 0x02,
+};
+typedef unsigned int radio_rds_t;
+
+/* FM deemphasis variant implemented. A struct radio_hal_fm_band_config can list one or more. */
+enum {
+    RADIO_DEEMPHASIS_50   = 0x1,
+    RADIO_DEEMPHASIS_75   = 0x2,
+};
+typedef unsigned int radio_deemphasis_t;
+
+/* Region a particular radio band configuration corresponds to. Not used at the HAL.
+ * Derived by the framework when converting the band descriptors retrieved from the HAL to
+ * individual band descriptors for each supported region. */
+typedef enum {
+    RADIO_REGION_NONE  = -1,
+    RADIO_REGION_ITU_1 = 0,
+    RADIO_REGION_ITU_2 = 1,
+    RADIO_REGION_OIRT  = 2,
+    RADIO_REGION_JAPAN = 3,
+    RADIO_REGION_KOREA = 4,
+} radio_region_t;
+
+/* scanning direction for scan() and step() tuner APIs */
+typedef enum {
+    RADIO_DIRECTION_UP,
+    RADIO_DIRECTION_DOWN
+} radio_direction_t;
+
+/* unique handle allocated to a radio module */
+typedef unsigned int radio_handle_t;
+
+/* Opaque meta data structure used by radio meta data API (see system/radio_metadata.h) */
+typedef struct radio_medtadata radio_metadata_t;
+
+
+/* Additional attributes for an FM band configuration */
+typedef struct radio_hal_fm_band_config {
+    radio_deemphasis_t  deemphasis; /* deemphasis variant */
+    bool                stereo;     /* stereo supported */
+    radio_rds_t         rds;        /* RDS variants supported */
+    bool                ta;         /* Traffic Announcement supported */
+    bool                af;         /* Alternate Frequency supported */
+} radio_hal_fm_band_config_t;
+
+/* Additional attributes for an AM band configuration */
+typedef struct radio_hal_am_band_config {
+    bool                stereo;     /* stereo supported */
+} radio_hal_am_band_config_t;
+
+/* Radio band configuration. Describes a given band supported by the radio module.
+ * The HAL can expose only one band per type with the the maximum range supported and all options.
+ * THe framework will derive the actual regions were this module can operate and expose separate
+ * band configurations for applications to chose from. */
+typedef struct radio_hal_band_config {
+    radio_band_t type;
+    bool         antenna_connected;
+    unsigned int lower_limit;
+    unsigned int upper_limit;
+    unsigned int num_spacings;
+    unsigned int spacings[RADIO_NUM_SPACINGS_MAX];
+    union {
+        radio_hal_fm_band_config_t fm;
+        radio_hal_am_band_config_t am;
+    };
+} radio_hal_band_config_t;
+
+/* Used internally by the framework to represent a band for s specific region */
+typedef struct radio_band_config {
+    radio_region_t  region;
+    radio_hal_band_config_t band;
+} radio_band_config_t;
+
+
+/* Exposes properties of a given hardware radio module.
+ * NOTE: current framework implementation supports only one audio source (num_audio_sources = 1).
+ * The source corresponds to AUDIO_DEVICE_IN_FM_TUNER.
+ * If more than one tuner is supported (num_tuners > 1), only one can be connected to the audio
+ * source. */
+typedef struct radio_hal_properties {
+    radio_class_t   class_id;   /* Class of this module. E.g RADIO_CLASS_AM_FM */
+    char            implementor[RADIO_STRING_LEN_MAX];  /* implementor name */
+    char            product[RADIO_STRING_LEN_MAX];  /* product name */
+    char            version[RADIO_STRING_LEN_MAX];  /* product version */
+    char            serial[RADIO_STRING_LEN_MAX];  /* serial number (for subscription services) */
+    unsigned int    num_tuners;     /* number of tuners controllable independently */
+    unsigned int    num_audio_sources; /* number of audio sources driven simultaneously */
+    bool            supports_capture; /* the hardware supports capture of audio source audio HAL */
+    unsigned int    num_bands;      /* number of band descriptors */
+    radio_hal_band_config_t bands[RADIO_NUM_BANDS_MAX]; /* band descriptors */
+} radio_hal_properties_t;
+
+/* Used internally by the framework. Same information as in struct radio_hal_properties plus a
+ * unique handle and one band configuration per region. */
+typedef struct radio_properties {
+    radio_handle_t      handle;
+    radio_class_t       class_id;
+    char                implementor[RADIO_STRING_LEN_MAX];
+    char                product[RADIO_STRING_LEN_MAX];
+    char                version[RADIO_STRING_LEN_MAX];
+    char                serial[RADIO_STRING_LEN_MAX];
+    unsigned int        num_tuners;
+    unsigned int        num_audio_sources;
+    bool                supports_capture;
+    unsigned int        num_bands;
+    radio_band_config_t bands[RADIO_NUM_BANDS_MAX];
+} radio_properties_t;
+
+/* Radio program information. Returned by the HAL with event RADIO_EVENT_TUNED.
+ * Contains information on currently tuned channel.
+ */
+typedef struct radio_program_info {
+    unsigned int     channel;   /* current channel. (e.g kHz for band type RADIO_BAND_FM) */
+    unsigned int     sub_channel; /* current sub channel. (used for RADIO_BAND_FM_HD) */
+    bool             tuned;     /* tuned to a program or not */
+    bool             stereo;    /* program is stereo or not */
+    bool             digital;   /* digital program or not (e.g HD Radio program) */
+    unsigned int     signal_strength; /* signal strength from 0 to 100 */
+    radio_metadata_t *metadata; /* non null if meta data are present (e.g PTY, song title ...) */
+} radio_program_info_t;
+
+
+/* Events sent to the framework via the HAL callback. An event can notify the completion of an
+ * asynchronous command (configuration, tune, scan ...) or a spontaneous change (antenna connection,
+ * failure, AF switching, meta data reception... */
+enum {
+    RADIO_EVENT_HW_FAILURE  = 0,  /* hardware module failure. Requires reopening the tuner */
+    RADIO_EVENT_CONFIG      = 1,  /* configuration change completed */
+    RADIO_EVENT_ANTENNA     = 2,  /* Antenna connected, disconnected */
+    RADIO_EVENT_TUNED       = 3,  /* tune, step, scan completed */
+    RADIO_EVENT_METADATA    = 4,  /* New meta data received */
+    RADIO_EVENT_TA          = 5,  /* Traffic announcement start or stop */
+    RADIO_EVENT_AF_SWITCH   = 6,  /* Switch to Alternate Frequency */
+    // begin framework only events
+    RADIO_EVENT_CONTROL     = 100, /* loss/gain of tuner control */
+    RADIO_EVENT_SERVER_DIED = 101, /* radio service died */
+};
+typedef unsigned int radio_event_type_t;
+
+/* Event passed to the framework by the HAL callback */
+typedef struct radio_hal_event {
+    radio_event_type_t  type;       /* event type */
+    int                 status;     /* used by RADIO_EVENT_CONFIG, RADIO_EVENT_TUNED */
+    union {
+        bool                    on;     /* RADIO_EVENT_ANTENNA, RADIO_EVENT_TA */
+        radio_hal_band_config_t config; /* RADIO_EVENT_CONFIG */
+        radio_program_info_t    info;   /* RADIO_EVENT_TUNED, RADIO_EVENT_AF_SWITCH */
+        radio_metadata_t        *metadata; /* RADIO_EVENT_METADATA */
+    };
+} radio_hal_event_t;
+
+/* Used internally by the framework. Same information as in struct radio_hal_event */
+typedef struct radio_event {
+    radio_event_type_t  type;
+    int                 status;
+    union {
+        bool                    on;
+        radio_band_config_t     config;
+        radio_program_info_t    info;
+        radio_metadata_t        *metadata; /* offset from start of struct when in shared memory */
+    };
+} radio_event_t;
+
+
+static radio_rds_t radio_rds_for_region(bool rds, radio_region_t region) {
+    if (!rds)
+        return RADIO_RDS_NONE;
+    switch(region) {
+        case RADIO_REGION_ITU_1:
+        case RADIO_REGION_OIRT:
+        case RADIO_REGION_JAPAN:
+        case RADIO_REGION_KOREA:
+            return RADIO_RDS_WORLD;
+        case RADIO_REGION_ITU_2:
+            return RADIO_RDS_US;
+        default:
+            return RADIO_REGION_NONE;
+    }
+}
+
+static radio_deemphasis_t radio_demephasis_for_region(radio_region_t region) {
+    switch(region) {
+        case RADIO_REGION_KOREA:
+        case RADIO_REGION_ITU_2:
+            return RADIO_DEEMPHASIS_75;
+        case RADIO_REGION_ITU_1:
+        case RADIO_REGION_OIRT:
+        case RADIO_REGION_JAPAN:
+        default:
+            return RADIO_DEEMPHASIS_50;
+    }
+}
+
+#endif  // ANDROID_RADIO_H
diff --git a/include/system/window.h b/include/system/window.h
index bf93b79..af0418b 100644
--- a/include/system/window.h
+++ b/include/system/window.h
@@ -262,6 +262,12 @@
      * the aspect ratio of the buffers produced.
      */
     NATIVE_WINDOW_STICKY_TRANSFORM = 11,
+
+    /**
+     * The default data space for the buffers as set by the consumer.
+     * The values are defined in graphics.h.
+     */
+    NATIVE_WINDOW_DEFAULT_DATASPACE = 12
 };
 
 /* Valid operations for the (*perform)() hook.
@@ -294,6 +300,7 @@
     NATIVE_WINDOW_SET_POST_TRANSFORM_CROP   = 16,   /* private */
     NATIVE_WINDOW_SET_BUFFERS_STICKY_TRANSFORM = 17,/* private */
     NATIVE_WINDOW_SET_SIDEBAND_STREAM       = 18,
+    NATIVE_WINDOW_SET_BUFFERS_DATASPACE     = 19
 };
 
 /* parameter for NATIVE_WINDOW_[API_][DIS]CONNECT */
@@ -498,6 +505,7 @@
      *     NATIVE_WINDOW_SET_BUFFERS_GEOMETRY  (deprecated)
      *     NATIVE_WINDOW_SET_BUFFERS_TRANSFORM
      *     NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP
+     *     NATIVE_WINDOW_SET_BUFFERS_DATASPACE
      *     NATIVE_WINDOW_SET_BUFFERS_DIMENSIONS
      *     NATIVE_WINDOW_SET_BUFFERS_FORMAT
      *     NATIVE_WINDOW_SET_SCALING_MODE       (private)
@@ -799,6 +807,26 @@
 }
 
 /*
+ * native_window_set_buffers_data_space(..., int dataSpace)
+ * All buffers queued after this call will be associated with the dataSpace
+ * parameter specified.
+ *
+ * dataSpace specifies additional information about the buffer that's dependent
+ * on the buffer format and the endpoints. For example, it can be used to convey
+ * the color space of the image data in the buffer, or it can be used to
+ * indicate that the buffers contain depth measurement data instead of color
+ * images.  The default dataSpace is 0, HAL_DATASPACE_UNKNOWN, unless it has been
+ * overridden by the consumer.
+ */
+static inline int native_window_set_buffers_data_space(
+        struct ANativeWindow* window,
+        android_dataspace_t dataSpace)
+{
+    return window->perform(window, NATIVE_WINDOW_SET_BUFFERS_DATASPACE,
+            dataSpace);
+}
+
+/*
  * native_window_set_buffers_transform(..., int transform)
  * All buffers queued after this call will be displayed transformed according
  * to the transform parameter specified.
diff --git a/include/sysutils/NetlinkEvent.h b/include/sysutils/NetlinkEvent.h
index 4fa49c5..a428d37 100644
--- a/include/sysutils/NetlinkEvent.h
+++ b/include/sysutils/NetlinkEvent.h
@@ -21,13 +21,30 @@
 #define NL_PARAMS_MAX 32
 
 class NetlinkEvent {
+public:
+    enum class Action {
+        kUnknown = 0,
+        kAdd = 1,
+        kRemove = 2,
+        kChange = 3,
+        kLinkUp = 4,
+        kLinkDown = 5,
+        kAddressUpdated = 6,
+        kAddressRemoved = 7,
+        kRdnss = 8,
+        kRouteUpdated = 9,
+        kRouteRemoved = 10,
+    };
+
+private:
     int  mSeq;
     char *mPath;
-    int  mAction;
+    Action mAction;
     char *mSubsystem;
     char *mParams[NL_PARAMS_MAX];
 
 public:
+    // STOPSHIP: remove these deprecated constants once we have updated prebuilts
     const static int NlActionUnknown;
     const static int NlActionAdd;
     const static int NlActionRemove;
@@ -47,7 +64,7 @@
     const char *findParam(const char *paramName);
 
     const char *getSubsystem() { return mSubsystem; }
-    int getAction() { return mAction; }
+    Action getAction() { return mAction; }
 
     void dump();
 
diff --git a/include/utils/Looper.h b/include/utils/Looper.h
index 15c9891..a381251 100644
--- a/include/utils/Looper.h
+++ b/include/utils/Looper.h
@@ -386,11 +386,12 @@
     void removeMessages(const sp<MessageHandler>& handler, int what);
 
     /**
-     * Return whether this looper's thread is currently idling -- that is, whether it
-     * stopped waiting for more work to do.  Note that this is intrinsically racy, since
-     * its state can change before you get the result back.
+     * Returns whether this looper's thread is currently polling for more work to do.
+     * This is a good signal that the loop is still alive rather than being stuck
+     * handling a callback.  Note that this method is intrinsically racy, since the
+     * state of the loop can change before you get the result back.
      */
-    bool isIdling() const;
+    bool isPolling() const;
 
     /**
      * Prepares a looper associated with the calling thread, and returns it.
@@ -419,8 +420,12 @@
     struct Request {
         int fd;
         int ident;
+        int events;
+        int seq;
         sp<LooperCallback> callback;
         void* data;
+
+        void initEventItem(struct epoll_event* eventItem) const;
     };
 
     struct Response {
@@ -451,12 +456,14 @@
 
     // Whether we are currently waiting for work.  Not protected by a lock,
     // any use of it is racy anyway.
-    volatile bool mIdling;
+    volatile bool mPolling;
 
-    int mEpollFd; // immutable
+    int mEpollFd; // guarded by mLock but only modified on the looper thread
+    bool mEpollRebuildRequired; // guarded by mLock
 
     // Locked list of file descriptor monitoring requests.
     KeyedVector<int, Request> mRequests;  // guarded by mLock
+    int mNextRequestSeq;
 
     // This state is only used privately by pollOnce and does not require a lock since
     // it runs on a single thread.
@@ -465,11 +472,15 @@
     nsecs_t mNextMessageUptime; // set to LLONG_MAX when none
 
     int pollInner(int timeoutMillis);
+    int removeFd(int fd, int seq);
     void awoken();
     void pushResponse(int events, const Request& request);
+    void rebuildEpollLocked();
+    void scheduleEpollRebuildLocked();
 
     static void initTLSKey();
     static void threadDestructor(void *st);
+    static void initEpollEvent(struct epoll_event* eventItem);
 };
 
 } // namespace android
diff --git a/init/init.cpp b/init/init.cpp
index e1c82a4..a27221a 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -15,6 +15,7 @@
  */
 
 #include <ctype.h>
+#include <dirent.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <libgen.h>
@@ -34,12 +35,16 @@
 #include <termios.h>
 #include <unistd.h>
 
+#include <memory>
+
 #include <mtd/mtd-user.h>
 
 #include <selinux/selinux.h>
 #include <selinux/label.h>
 #include <selinux/android.h>
 
+#include <base/file.h>
+#include <base/stringprintf.h>
 #include <cutils/android_reboot.h>
 #include <cutils/fs.h>
 #include <cutils/iosched_policy.h>
@@ -59,6 +64,9 @@
 #include "ueventd.h"
 #include "watchdogd.h"
 
+using android::base::ReadFileToString;
+using android::base::StringPrintf;
+
 struct selabel_handle *sehandle;
 struct selabel_handle *sehandle_prop;
 
@@ -66,8 +74,6 @@
 
 static char console[32];
 static char bootmode[32];
-static char hardware[32];
-static unsigned revision = 0;
 static char qemu[32];
 
 static struct action *cur_action = NULL;
@@ -773,6 +779,8 @@
         { "ro.boot.mode", "ro.bootmode", "unknown", },
         { "ro.boot.baseband", "ro.baseband", "unknown", },
         { "ro.boot.bootloader", "ro.bootloader", "unknown", },
+        { "ro.boot.hardware", "ro.hardware", "unknown", },
+        { "ro.boot.revision", "ro.revision", "0", },
     };
 
     for (i = 0; i < ARRAY_SIZE(prop_map); i++) {
@@ -791,16 +799,6 @@
     property_get("ro.bootmode", tmp);
     strlcpy(bootmode, tmp, sizeof(bootmode));
 
-    /* if this was given on kernel command line, override what we read
-     * before (e.g. from /proc/cpuinfo), if anything */
-    ret = property_get("ro.boot.hardware", tmp);
-    if (ret)
-        strlcpy(hardware, tmp, sizeof(hardware));
-    property_set("ro.hardware", hardware);
-
-    snprintf(tmp, PROP_VALUE_MAX, "%d", revision);
-    property_set("ro.revision", tmp);
-
     /* TODO: these are obsolete. We should delete them */
     if (!strcmp(bootmode,"factory"))
         property_set("ro.factorytest", "1");
@@ -810,6 +808,40 @@
         property_set("ro.factorytest", "0");
 }
 
+static void process_kernel_dt(void)
+{
+    static const char android_dir[] = "/proc/device-tree/firmware/android";
+
+    std::string file_name = StringPrintf("%s/compatible", android_dir);
+
+    std::string dt_file;
+    ReadFileToString(file_name, &dt_file);
+    if (!dt_file.compare("android,firmware")) {
+        ERROR("firmware/android is not compatible with 'android,firmware'\n");
+        return;
+    }
+
+    std::unique_ptr<DIR, int(*)(DIR*)>dir(opendir(android_dir), closedir);
+    if (!dir)
+        return;
+
+    struct dirent *dp;
+    while ((dp = readdir(dir.get())) != NULL) {
+        if (dp->d_type != DT_REG || !strcmp(dp->d_name, "compatible"))
+            continue;
+
+        file_name = StringPrintf("%s/%s", android_dir, dp->d_name);
+
+        ReadFileToString(file_name, &dt_file);
+        std::replace(dt_file.begin(), dt_file.end(), ',', '.');
+
+        std::string property_name = StringPrintf("ro.boot.%s", dp->d_name);
+        if (property_set(property_name.c_str(), dt_file.c_str())) {
+            ERROR("Could not set property %s to value %s", property_name.c_str(), dt_file.c_str());
+        }
+    }
+}
+
 static void process_kernel_cmdline(void)
 {
     /* don't expose the raw commandline to nonpriv processes */
@@ -822,11 +854,6 @@
     import_kernel_cmdline(0, import_kernel_nv);
     if (qemu[0])
         import_kernel_cmdline(1, import_kernel_nv);
-
-    /* now propogate the info given on command line to internal variables
-     * used by init as well as the current required properties
-     */
-    export_kernel_boot_props();
 }
 
 static int property_service_init_action(int nargs, char **args)
@@ -1014,10 +1041,17 @@
     klog_init();
     property_init();
 
-    get_hardware_name(hardware, &revision);
-
+    process_kernel_dt();
+    /* in case one is passing arguments both on the command line and in DT
+     * Properties set in DT always have priority over the command-line ones
+     */
     process_kernel_cmdline();
 
+    /* now propogate the kernel variables to internal variables
+     * used by init as well as the current required properties
+     */
+    export_kernel_boot_props();
+
     selinux_callback cb;
     cb.func_log = log_callback;
     selinux_set_callback(SELINUX_CB_LOG, cb);
diff --git a/init/ueventd.cpp b/init/ueventd.cpp
index d56b91a..5af6e3d 100644
--- a/init/ueventd.cpp
+++ b/init/ueventd.cpp
@@ -30,28 +30,13 @@
 #include "util.h"
 #include "devices.h"
 #include "ueventd_parser.h"
-
-static char hardware[32];
-static unsigned revision = 0;
-
-static void import_kernel_nv(char *name, int in_qemu)
-{
-    if (*name != '\0') {
-        char *value = strchr(name, '=');
-        if (value != NULL) {
-            *value++ = 0;
-            if (!strcmp(name,"androidboot.hardware"))
-            {
-                strlcpy(hardware, value, sizeof(hardware));
-            }
-        }
-    }
-}
+#include "property_service.h"
 
 int ueventd_main(int argc, char **argv)
 {
     struct pollfd ufd;
     int nr;
+    char hardware[PROP_VALUE_MAX];
     char tmp[32];
 
     /*
@@ -83,12 +68,7 @@
 
     INFO("starting ueventd\n");
 
-    /* Respect hardware passed in through the kernel cmd line. Here we will look
-     * for androidboot.hardware param in kernel cmdline, and save its value in
-     * hardware[]. */
-    import_kernel_cmdline(0, import_kernel_nv);
-
-    get_hardware_name(hardware, &revision);
+    property_get("ro.hardware", hardware);
 
     ueventd_parse_config_file("/ueventd.rc");
 
diff --git a/init/util.cpp b/init/util.cpp
index c805083..8b238d4 100644
--- a/init/util.cpp
+++ b/init/util.cpp
@@ -400,39 +400,6 @@
     exit(1);
 }
 
-void get_hardware_name(char *hardware, unsigned int *revision) {
-  // Hardware string was provided on kernel command line.
-  if (hardware[0]) {
-    return;
-  }
-
-  FILE* fp = fopen("/proc/cpuinfo", "re");
-  if (fp == NULL) {
-    return;
-  }
-  char buf[1024];
-  while (fgets(buf, sizeof(buf), fp) != NULL) {
-    if (strncmp(buf, "Hardware", 8) == 0) {
-      const char* hw = strstr(buf, ": ");
-      if (hw) {
-        hw += 2;
-        size_t n = 0;
-        while (*hw) {
-          if (!isspace(*hw)) {
-            hardware[n++] = tolower(*hw);
-          }
-          hw++;
-          if (n == 31) break;
-        }
-        hardware[n] = 0;
-      }
-    } else if (strncmp(buf, "Revision", 8) == 0) {
-      sscanf(buf, "Revision : %ux", revision);
-    }
-  }
-  fclose(fp);
-}
-
 void import_kernel_cmdline(int in_qemu,
                            void (*import_kernel_nv)(char *name, int in_qemu))
 {
diff --git a/init/util.h b/init/util.h
index 77da3ac..e0b3c69 100644
--- a/init/util.h
+++ b/init/util.h
@@ -42,7 +42,6 @@
 void remove_link(const char *oldpath, const char *newpath);
 int wait_for_file(const char *filename, int timeout);
 void open_devnull_stdio(void);
-void get_hardware_name(char *hardware, unsigned int *revision);
 void import_kernel_cmdline(int in_qemu, void (*import_kernel_nv)(char *name, int in_qemu));
 int make_dir(const char *path, mode_t mode);
 int restorecon(const char *pathname);
diff --git a/libion/ion.c b/libion/ion.c
index 4908932..d1984bd 100644
--- a/libion/ion.c
+++ b/libion/ion.c
@@ -91,6 +91,7 @@
             int flags, off_t offset, unsigned char **ptr, int *map_fd)
 {
     int ret;
+    unsigned char *tmp_ptr;
     struct ion_fd_data data = {
         .handle = handle,
     };
@@ -103,16 +104,17 @@
     ret = ion_ioctl(fd, ION_IOC_MAP, &data);
     if (ret < 0)
         return ret;
-    *map_fd = data.fd;
-    if (*map_fd < 0) {
+    if (data.fd < 0) {
         ALOGE("map ioctl returned negative fd\n");
         return -EINVAL;
     }
-    *ptr = mmap(NULL, length, prot, flags, *map_fd, offset);
-    if (*ptr == MAP_FAILED) {
+    tmp_ptr = mmap(NULL, length, prot, flags, data.fd, offset);
+    if (tmp_ptr == MAP_FAILED) {
         ALOGE("mmap failed: %s\n", strerror(errno));
         return -errno;
     }
+    *map_fd = data.fd;
+    *ptr = tmp_ptr;
     return ret;
 }
 
@@ -129,11 +131,11 @@
     ret = ion_ioctl(fd, ION_IOC_SHARE, &data);
     if (ret < 0)
         return ret;
-    *share_fd = data.fd;
-    if (*share_fd < 0) {
+    if (data.fd < 0) {
         ALOGE("share ioctl returned negative fd\n");
         return -EINVAL;
     }
+    *share_fd = data.fd;
     return ret;
 }
 
diff --git a/libnetutils/dhcp_utils.c b/libnetutils/dhcp_utils.c
index 70e37c6..c6b9fe4 100644
--- a/libnetutils/dhcp_utils.c
+++ b/libnetutils/dhcp_utils.c
@@ -1,16 +1,16 @@
 /*
  * Copyright 2008, 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 
+ * 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 
+ *     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 
+ * 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.
  */
 
@@ -33,7 +33,7 @@
 static const int NAP_TIME = 200;   /* wait for 200ms at a time */
                                   /* when polling for property values */
 static const char DAEMON_NAME_RENEW[]  = "iprenew";
-static char errmsg[100];
+static char errmsg[100] = "\0";
 /* interface length for dhcpcd daemon start (dhcpcd_<interface> as defined in init.rc file)
  * or for filling up system properties dhcpcd.<interface>.ipaddress, dhcpcd.<interface>.dns1
  * and other properties on a successful bind
@@ -74,7 +74,7 @@
 
     while (maxnaps-- >= 0) {
         if (property_get(name, value, NULL)) {
-            if (desired_value == NULL || 
+            if (desired_value == NULL ||
                     strcmp(value, desired_value) == 0) {
                 return 0;
             }
@@ -169,6 +169,47 @@
 }
 
 /*
+ * Get any available DHCP results.
+ */
+int dhcp_get_results(const char *interface,
+                     char *ipaddr,
+                     char *gateway,
+                     uint32_t *prefixLength,
+                     char *dns[],
+                     char *server,
+                     uint32_t *lease,
+                     char *vendorInfo,
+                     char *domain,
+                     char *mtu)
+{
+    char result_prop_name[PROPERTY_KEY_MAX];
+    char prop_value[PROPERTY_VALUE_MAX];
+
+    /* Interface name after converting p2p0-p2p0-X to p2p to reuse system properties */
+    char p2p_interface[MAX_INTERFACE_LENGTH];
+    get_p2p_interface_replacement(interface, p2p_interface);
+    snprintf(result_prop_name, sizeof(result_prop_name), "%s.%s.result",
+            DHCP_PROP_NAME_PREFIX,
+            p2p_interface);
+
+    memset(prop_value, '\0', PROPERTY_VALUE_MAX);
+    if (!property_get(result_prop_name, prop_value, NULL)) {
+        snprintf(errmsg, sizeof(errmsg), "%s", "DHCP result property was not set");
+        return -1;
+    }
+    if (strcmp(prop_value, "ok") == 0) {
+        if (fill_ip_info(interface, ipaddr, gateway, prefixLength, dns,
+                server, lease, vendorInfo, domain, mtu) == -1) {
+            return -1;
+        }
+        return 0;
+    } else {
+        snprintf(errmsg, sizeof(errmsg), "DHCP result was %s", prop_value);
+        return -1;
+    }
+}
+
+/*
  * Start the dhcp client daemon, and wait for it to finish
  * configuring the interface.
  *
@@ -177,16 +218,7 @@
  * Example:
  * service dhcpcd_<interface> /system/bin/dhcpcd -ABKL -f dhcpcd.conf
  */
-int dhcp_do_request(const char *interface,
-                    char *ipaddr,
-                    char *gateway,
-                    uint32_t *prefixLength,
-                    char *dns[],
-                    char *server,
-                    uint32_t *lease,
-                    char *vendorInfo,
-                    char *domain,
-                    char *mtu)
+int dhcp_start(const char *interface)
 {
     char result_prop_name[PROPERTY_KEY_MAX];
     char daemon_prop_name[PROPERTY_KEY_MAX];
@@ -230,21 +262,7 @@
         return -1;
     }
 
-    if (!property_get(result_prop_name, prop_value, NULL)) {
-        /* shouldn't ever happen, given the success of wait_for_property() */
-        snprintf(errmsg, sizeof(errmsg), "%s", "DHCP result property was not set");
-        return -1;
-    }
-    if (strcmp(prop_value, "ok") == 0) {
-        if (fill_ip_info(interface, ipaddr, gateway, prefixLength, dns,
-                server, lease, vendorInfo, domain, mtu) == -1) {
-            return -1;
-        }
-        return 0;
-    } else {
-        snprintf(errmsg, sizeof(errmsg), "DHCP result was %s", prop_value);
-        return -1;
-    }
+    return 0;
 }
 
 /**
@@ -320,16 +338,7 @@
  * service iprenew_<interface> /system/bin/dhcpcd -n
  *
  */
-int dhcp_do_request_renew(const char *interface,
-                    char *ipaddr,
-                    char *gateway,
-                    uint32_t *prefixLength,
-                    char *dns[],
-                    char *server,
-                    uint32_t *lease,
-                    char *vendorInfo,
-                    char *domain,
-                    char *mtu)
+int dhcp_start_renew(const char *interface)
 {
     char result_prop_name[PROPERTY_KEY_MAX];
     char prop_value[PROPERTY_VALUE_MAX] = {'\0'};
@@ -359,16 +368,5 @@
         return -1;
     }
 
-    if (!property_get(result_prop_name, prop_value, NULL)) {
-        /* shouldn't ever happen, given the success of wait_for_property() */
-        snprintf(errmsg, sizeof(errmsg), "%s", "DHCP Renew result property was not set");
-        return -1;
-    }
-    if (strcmp(prop_value, "ok") == 0) {
-        return fill_ip_info(interface, ipaddr, gateway, prefixLength, dns,
-                server, lease, vendorInfo, domain, mtu);
-    } else {
-        snprintf(errmsg, sizeof(errmsg), "DHCP Renew result was %s", prop_value);
-        return -1;
-    }
+    return 0;
 }
diff --git a/libsysutils/src/NetlinkEvent.cpp b/libsysutils/src/NetlinkEvent.cpp
index 909df86..29a86d8 100644
--- a/libsysutils/src/NetlinkEvent.cpp
+++ b/libsysutils/src/NetlinkEvent.cpp
@@ -47,20 +47,21 @@
 #include <netlink/handlers.h>
 #include <netlink/msg.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;
-const int NetlinkEvent::NlActionAddressUpdated = 6;
-const int NetlinkEvent::NlActionAddressRemoved = 7;
-const int NetlinkEvent::NlActionRdnss = 8;
-const int NetlinkEvent::NlActionRouteUpdated = 9;
-const int NetlinkEvent::NlActionRouteRemoved = 10;
+// STOPSHIP: remove these deprecated constants once we have updated prebuilts
+const int NetlinkEvent::NlActionUnknown = static_cast<int>(Action::kUnknown);
+const int NetlinkEvent::NlActionAdd = static_cast<int>(Action::kAdd);
+const int NetlinkEvent::NlActionRemove = static_cast<int>(Action::kRemove);
+const int NetlinkEvent::NlActionChange = static_cast<int>(Action::kChange);
+const int NetlinkEvent::NlActionLinkDown = static_cast<int>(Action::kLinkDown);
+const int NetlinkEvent::NlActionLinkUp = static_cast<int>(Action::kLinkUp);
+const int NetlinkEvent::NlActionAddressUpdated = static_cast<int>(Action::kAddressUpdated);
+const int NetlinkEvent::NlActionAddressRemoved = static_cast<int>(Action::kAddressRemoved);
+const int NetlinkEvent::NlActionRdnss = static_cast<int>(Action::kRdnss);
+const int NetlinkEvent::NlActionRouteUpdated = static_cast<int>(Action::kRouteUpdated);
+const int NetlinkEvent::NlActionRouteRemoved = static_cast<int>(Action::kRouteRemoved);
 
 NetlinkEvent::NetlinkEvent() {
-    mAction = NlActionUnknown;
+    mAction = Action::kUnknown;
     memset(mParams, 0, sizeof(mParams));
     mPath = NULL;
     mSubsystem = NULL;
@@ -154,8 +155,8 @@
         switch(rta->rta_type) {
             case IFLA_IFNAME:
                 asprintf(&mParams[0], "INTERFACE=%s", (char *) RTA_DATA(rta));
-                mAction = (ifi->ifi_flags & IFF_LOWER_UP) ?  NlActionLinkUp :
-                                                             NlActionLinkDown;
+                mAction = (ifi->ifi_flags & IFF_LOWER_UP) ? Action::kLinkUp :
+                                                            Action::kLinkDown;
                 mSubsystem = strdup("net");
                 return true;
         }
@@ -244,8 +245,8 @@
     }
 
     // Fill in netlink event information.
-    mAction = (type == RTM_NEWADDR) ? NlActionAddressUpdated :
-                                      NlActionAddressRemoved;
+    mAction = (type == RTM_NEWADDR) ? Action::kAddressUpdated :
+                                      Action::kAddressRemoved;
     mSubsystem = strdup("net");
     asprintf(&mParams[0], "ADDRESS=%s/%d", addrstr,
              ifaddr->ifa_prefixlen);
@@ -276,7 +277,7 @@
     asprintf(&mParams[0], "ALERT_NAME=%s", pm->prefix);
     asprintf(&mParams[1], "INTERFACE=%s", devname);
     mSubsystem = strdup("qlog");
-    mAction = NlActionChange;
+    mAction = Action::kChange;
     return true;
 }
 
@@ -311,7 +312,7 @@
     asprintf(&mParams[0], "UID=%d", uid);
     mParams[1] = hex;
     mSubsystem = strdup("strict");
-    mAction = NlActionChange;
+    mAction = Action::kChange;
     return true;
 }
 
@@ -397,8 +398,8 @@
         return false;
 
     // Fill in netlink event information.
-    mAction = (type == RTM_NEWROUTE) ? NlActionRouteUpdated :
-                                       NlActionRouteRemoved;
+    mAction = (type == RTM_NEWROUTE) ? Action::kRouteUpdated :
+                                       Action::kRouteRemoved;
     mSubsystem = strdup("net");
     asprintf(&mParams[0], "ROUTE=%s/%d", dst, prefixLength);
     asprintf(&mParams[1], "GATEWAY=%s", (*gw) ? gw : "");
@@ -497,7 +498,7 @@
         }
         buf[pos] = '\0';
 
-        mAction = NlActionRdnss;
+        mAction = Action::kRdnss;
         mSubsystem = strdup("net");
         asprintf(&mParams[0], "INTERFACE=%s", ifname);
         asprintf(&mParams[1], "LIFETIME=%u", lifetime);
@@ -617,11 +618,11 @@
             const char* a;
             if ((a = HAS_CONST_PREFIX(s, end, "ACTION=")) != NULL) {
                 if (!strcmp(a, "add"))
-                    mAction = NlActionAdd;
+                    mAction = Action::kAdd;
                 else if (!strcmp(a, "remove"))
-                    mAction = NlActionRemove;
+                    mAction = Action::kRemove;
                 else if (!strcmp(a, "change"))
-                    mAction = NlActionChange;
+                    mAction = Action::kChange;
             } else if ((a = HAS_CONST_PREFIX(s, end, "SEQNUM=")) != NULL) {
                 mSeq = atoi(a);
             } else if ((a = HAS_CONST_PREFIX(s, end, "SUBSYSTEM=")) != NULL) {
diff --git a/libutils/Looper.cpp b/libutils/Looper.cpp
index 9a2dd6c..d739f11 100644
--- a/libutils/Looper.cpp
+++ b/libutils/Looper.cpp
@@ -20,6 +20,7 @@
 #include <unistd.h>
 #include <fcntl.h>
 #include <limits.h>
+#include <inttypes.h>
 
 
 namespace android {
@@ -68,7 +69,8 @@
 
 Looper::Looper(bool allowNonCallbacks) :
         mAllowNonCallbacks(allowNonCallbacks), mSendingMessage(false),
-        mResponseIndex(0), mNextMessageUptime(LLONG_MAX) {
+        mPolling(false), mEpollFd(-1), mEpollRebuildRequired(false),
+        mNextRequestSeq(0), mResponseIndex(0), mNextMessageUptime(LLONG_MAX) {
     int wakeFds[2];
     int result = pipe(wakeFds);
     LOG_ALWAYS_FATAL_IF(result != 0, "Could not create wake pipe.  errno=%d", errno);
@@ -84,25 +86,16 @@
     LOG_ALWAYS_FATAL_IF(result != 0, "Could not make wake write pipe non-blocking.  errno=%d",
             errno);
 
-    mIdling = false;
-
-    // Allocate the epoll instance and register the wake pipe.
-    mEpollFd = epoll_create(EPOLL_SIZE_HINT);
-    LOG_ALWAYS_FATAL_IF(mEpollFd < 0, "Could not create epoll instance.  errno=%d", errno);
-
-    struct epoll_event eventItem;
-    memset(& eventItem, 0, sizeof(epoll_event)); // zero out unused members of data field union
-    eventItem.events = EPOLLIN;
-    eventItem.data.fd = mWakeReadPipeFd;
-    result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeReadPipeFd, & eventItem);
-    LOG_ALWAYS_FATAL_IF(result != 0, "Could not add wake read pipe to epoll instance.  errno=%d",
-            errno);
+    AutoMutex _l(mLock);
+    rebuildEpollLocked();
 }
 
 Looper::~Looper() {
     close(mWakeReadPipeFd);
     close(mWakeWritePipeFd);
-    close(mEpollFd);
+    if (mEpollFd >= 0) {
+        close(mEpollFd);
+    }
 }
 
 void Looper::initTLSKey() {
@@ -156,6 +149,50 @@
     return mAllowNonCallbacks;
 }
 
+void Looper::rebuildEpollLocked() {
+    // Close old epoll instance if we have one.
+    if (mEpollFd >= 0) {
+#if DEBUG_CALLBACKS
+        ALOGD("%p ~ rebuildEpollLocked - rebuilding epoll set", this);
+#endif
+        close(mEpollFd);
+    }
+
+    // Allocate the new epoll instance and register the wake pipe.
+    mEpollFd = epoll_create(EPOLL_SIZE_HINT);
+    LOG_ALWAYS_FATAL_IF(mEpollFd < 0, "Could not create epoll instance.  errno=%d", errno);
+
+    struct epoll_event eventItem;
+    memset(& eventItem, 0, sizeof(epoll_event)); // zero out unused members of data field union
+    eventItem.events = EPOLLIN;
+    eventItem.data.fd = mWakeReadPipeFd;
+    int result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeReadPipeFd, & eventItem);
+    LOG_ALWAYS_FATAL_IF(result != 0, "Could not add wake read pipe to epoll instance.  errno=%d",
+            errno);
+
+    for (size_t i = 0; i < mRequests.size(); i++) {
+        const Request& request = mRequests.valueAt(i);
+        struct epoll_event eventItem;
+        request.initEventItem(&eventItem);
+
+        int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, request.fd, & eventItem);
+        if (epollResult < 0) {
+            ALOGE("Error adding epoll events for fd %d while rebuilding epoll set, errno=%d",
+                    request.fd, errno);
+        }
+    }
+}
+
+void Looper::scheduleEpollRebuildLocked() {
+    if (!mEpollRebuildRequired) {
+#if DEBUG_CALLBACKS
+        ALOGD("%p ~ scheduleEpollRebuildLocked - scheduling epoll set rebuild", this);
+#endif
+        mEpollRebuildRequired = true;
+        wake();
+    }
+}
+
 int Looper::pollOnce(int timeoutMillis, int* outFd, int* outEvents, void** outData) {
     int result = 0;
     for (;;) {
@@ -206,7 +243,7 @@
             timeoutMillis = messageTimeoutMillis;
         }
 #if DEBUG_POLL_AND_WAKE
-        ALOGD("%p ~ pollOnce - next message in %lldns, adjusted timeout: timeoutMillis=%d",
+        ALOGD("%p ~ pollOnce - next message in %" PRId64 "ns, adjusted timeout: timeoutMillis=%d",
                 this, mNextMessageUptime - now, timeoutMillis);
 #endif
     }
@@ -217,17 +254,24 @@
     mResponseIndex = 0;
 
     // We are about to idle.
-    mIdling = true;
+    mPolling = true;
 
     struct epoll_event eventItems[EPOLL_MAX_EVENTS];
     int eventCount = epoll_wait(mEpollFd, eventItems, EPOLL_MAX_EVENTS, timeoutMillis);
 
     // No longer idling.
-    mIdling = false;
+    mPolling = false;
 
     // Acquire lock.
     mLock.lock();
 
+    // Rebuild epoll set if needed.
+    if (mEpollRebuildRequired) {
+        mEpollRebuildRequired = false;
+        rebuildEpollLocked();
+        goto Done;
+    }
+
     // Check for poll error.
     if (eventCount < 0) {
         if (errno == EINTR) {
@@ -326,10 +370,14 @@
             ALOGD("%p ~ pollOnce - invoking fd event callback %p: fd=%d, events=0x%x, data=%p",
                     this, response.request.callback.get(), fd, events, data);
 #endif
+            // Invoke the callback.  Note that the file descriptor may be closed by
+            // the callback (and potentially even reused) before the function returns so
+            // we need to be a little careful when removing the file descriptor afterwards.
             int callbackResult = response.request.callback->handleEvent(fd, events, data);
             if (callbackResult == 0) {
-                removeFd(fd);
+                removeFd(fd, response.request.seq);
             }
+
             // Clear the callback reference in the response structure promptly because we
             // will not clear the response vector itself until the next poll.
             response.request.callback.clear();
@@ -425,23 +473,20 @@
         ident = POLL_CALLBACK;
     }
 
-    int epollEvents = 0;
-    if (events & EVENT_INPUT) epollEvents |= EPOLLIN;
-    if (events & EVENT_OUTPUT) epollEvents |= EPOLLOUT;
-
     { // acquire lock
         AutoMutex _l(mLock);
 
         Request request;
         request.fd = fd;
         request.ident = ident;
+        request.events = events;
+        request.seq = mNextRequestSeq++;
         request.callback = callback;
         request.data = data;
+        if (mNextRequestSeq == -1) mNextRequestSeq = 0; // reserve sequence number -1
 
         struct epoll_event eventItem;
-        memset(& eventItem, 0, sizeof(epoll_event)); // zero out unused members of data field union
-        eventItem.events = epollEvents;
-        eventItem.data.fd = fd;
+        request.initEventItem(&eventItem);
 
         ssize_t requestIndex = mRequests.indexOfKey(fd);
         if (requestIndex < 0) {
@@ -454,8 +499,36 @@
         } else {
             int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_MOD, fd, & eventItem);
             if (epollResult < 0) {
-                ALOGE("Error modifying epoll events for fd %d, errno=%d", fd, errno);
-                return -1;
+                if (errno == ENOENT) {
+                    // Tolerate ENOENT because it means that an older file descriptor was
+                    // closed before its callback was unregistered and meanwhile a new
+                    // file descriptor with the same number has been created and is now
+                    // being registered for the first time.  This error may occur naturally
+                    // when a callback has the side-effect of closing the file descriptor
+                    // before returning and unregistering itself.  Callback sequence number
+                    // checks further ensure that the race is benign.
+                    //
+                    // Unfortunately due to kernel limitations we need to rebuild the epoll
+                    // set from scratch because it may contain an old file handle that we are
+                    // now unable to remove since its file descriptor is no longer valid.
+                    // No such problem would have occurred if we were using the poll system
+                    // call instead, but that approach carries others disadvantages.
+#if DEBUG_CALLBACKS
+                    ALOGD("%p ~ addFd - EPOLL_CTL_MOD failed due to file descriptor "
+                            "being recycled, falling back on EPOLL_CTL_ADD, errno=%d",
+                            this, errno);
+#endif
+                    epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, fd, & eventItem);
+                    if (epollResult < 0) {
+                        ALOGE("Error modifying or adding epoll events for fd %d, errno=%d",
+                                fd, errno);
+                        return -1;
+                    }
+                    scheduleEpollRebuildLocked();
+                } else {
+                    ALOGE("Error modifying epoll events for fd %d, errno=%d", fd, errno);
+                    return -1;
+                }
             }
             mRequests.replaceValueAt(requestIndex, request);
         }
@@ -464,8 +537,12 @@
 }
 
 int Looper::removeFd(int fd) {
+    return removeFd(fd, -1);
+}
+
+int Looper::removeFd(int fd, int seq) {
 #if DEBUG_CALLBACKS
-    ALOGD("%p ~ removeFd - fd=%d", this, fd);
+    ALOGD("%p ~ removeFd - fd=%d, seq=%d", this, fd, seq);
 #endif
 
     { // acquire lock
@@ -475,13 +552,43 @@
             return 0;
         }
 
-        int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_DEL, fd, NULL);
-        if (epollResult < 0) {
-            ALOGE("Error removing epoll events for fd %d, errno=%d", fd, errno);
-            return -1;
+        // Check the sequence number if one was given.
+        if (seq != -1 && mRequests.valueAt(requestIndex).seq != seq) {
+#if DEBUG_CALLBACKS
+            ALOGD("%p ~ removeFd - sequence number mismatch, oldSeq=%d",
+                    this, mRequests.valueAt(requestIndex).seq);
+#endif
+            return 0;
         }
 
+        // Always remove the FD from the request map even if an error occurs while
+        // updating the epoll set so that we avoid accidentally leaking callbacks.
         mRequests.removeItemsAt(requestIndex);
+
+        int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_DEL, fd, NULL);
+        if (epollResult < 0) {
+            if (seq != -1 && (errno == EBADF || errno == ENOENT)) {
+                // Tolerate EBADF or ENOENT when the sequence number is known because it
+                // means that the file descriptor was closed before its callback was
+                // unregistered.  This error may occur naturally when a callback has the
+                // side-effect of closing the file descriptor before returning and
+                // unregistering itself.
+                //
+                // Unfortunately due to kernel limitations we need to rebuild the epoll
+                // set from scratch because it may contain an old file handle that we are
+                // now unable to remove since its file descriptor is no longer valid.
+                // No such problem would have occurred if we were using the poll system
+                // call instead, but that approach carries others disadvantages.
+#if DEBUG_CALLBACKS
+                ALOGD("%p ~ removeFd - EPOLL_CTL_DEL failed due to file descriptor "
+                        "being closed, errno=%d", this, errno);
+#endif
+                scheduleEpollRebuildLocked();
+            } else {
+                ALOGE("Error removing epoll events for fd %d, errno=%d", fd, errno);
+                return -1;
+            }
+        }
     } // release lock
     return 1;
 }
@@ -500,7 +607,7 @@
 void Looper::sendMessageAtTime(nsecs_t uptime, const sp<MessageHandler>& handler,
         const Message& message) {
 #if DEBUG_CALLBACKS
-    ALOGD("%p ~ sendMessageAtTime - uptime=%lld, handler=%p, what=%d",
+    ALOGD("%p ~ sendMessageAtTime - uptime=%" PRId64 ", handler=%p, what=%d",
             this, uptime, handler.get(), message.what);
 #endif
 
@@ -566,8 +673,18 @@
     } // release lock
 }
 
-bool Looper::isIdling() const {
-    return mIdling;
+bool Looper::isPolling() const {
+    return mPolling;
+}
+
+void Looper::Request::initEventItem(struct epoll_event* eventItem) const {
+    int epollEvents = 0;
+    if (events & EVENT_INPUT) epollEvents |= EPOLLIN;
+    if (events & EVENT_OUTPUT) epollEvents |= EPOLLOUT;
+
+    memset(eventItem, 0, sizeof(epoll_event)); // zero out unused members of data field union
+    eventItem->events = epollEvents;
+    eventItem->data.fd = fd;
 }
 
 } // namespace android
diff --git a/logwrapper/logwrap.c b/logwrapper/logwrap.c
index 3a6276e..83576fb 100644
--- a/logwrapper/logwrap.c
+++ b/logwrapper/logwrap.c
@@ -325,7 +325,7 @@
 
     if (log_target & LOG_KLOG) {
         snprintf(log_info.klog_fmt, sizeof(log_info.klog_fmt),
-                 "<6>%.*s: %%s", MAX_KLOG_TAG, log_info.btag);
+                 "<6>%.*s: %%s\n", MAX_KLOG_TAG, log_info.btag);
     }
 
     if ((log_target & LOG_FILE) && !file_path) {
diff --git a/rootdir/init.rc b/rootdir/init.rc
index bc36c3e..9748fed 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -113,6 +113,10 @@
     # set fwmark on accepted sockets
     write /proc/sys/net/ipv4/tcp_fwmark_accept 1
 
+    # disable icmp redirects
+    write /proc/sys/net/ipv4/conf/all/accept_redirects 0
+    write /proc/sys/net/ipv6/conf/all/accept_redirects 0
+
     # Create cgroup mount points for process groups
     mkdir /dev/cpuctl
     mount cgroup none /dev/cpuctl cpu