Merge "libsuspend: remove autosleep and earlysuspend"
diff --git a/adb/file_sync_service.cpp b/adb/file_sync_service.cpp
index 837902a..7a92d2e 100644
--- a/adb/file_sync_service.cpp
+++ b/adb/file_sync_service.cpp
@@ -198,11 +198,6 @@
         // Ignore the result of calling fchmod. It's not supported
         // by all filesystems, so we don't check for success. b/12441485
         fchmod(fd, mode);
-
-        if (!update_capabilities(path, capabilities)) {
-            SendSyncFailErrno(s, "update_capabilities failed");
-            goto fail;
-        }
     }
 
     while (true) {
@@ -232,6 +227,11 @@
 
     adb_close(fd);
 
+    if (!update_capabilities(path, capabilities)) {
+        SendSyncFailErrno(s, "update_capabilities failed");
+        goto fail;
+    }
+
     utimbuf u;
     u.actime = timestamp;
     u.modtime = timestamp;
diff --git a/include/cutils/files.h b/include/cutils/files.h
new file mode 100644
index 0000000..0210e30
--- /dev/null
+++ b/include/cutils/files.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2016 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_FILES_H
+#define __CUTILS_FILES_H
+
+#define ANDROID_FILE_ENV_PREFIX "ANDROID_FILE_"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * android_get_control_file - simple helper function to get the file
+ * descriptor of our init-managed file. `path' is the filename path as
+ * given in init.rc. Returns -1 on error.
+ */
+int android_get_control_file(const char* path);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CUTILS_FILES_H */
diff --git a/include/system/graphics-base.h b/include/system/graphics-base.h
new file mode 100644
index 0000000..cebd2f9
--- /dev/null
+++ b/include/system/graphics-base.h
@@ -0,0 +1,120 @@
+// This file is autogenerated by hidl-gen. Do not edit manually.
+
+#ifndef HIDL_GENERATED_android_hardware_graphics_common_V1_0_EXPORTED_CONSTANTS_H_
+#define HIDL_GENERATED_android_hardware_graphics_common_V1_0_EXPORTED_CONSTANTS_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef 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_YV12 = 842094169, // 0x32315659
+    HAL_PIXEL_FORMAT_Y8 = 538982489, // 0x20203859
+    HAL_PIXEL_FORMAT_Y16 = 540422489, // 0x20363159
+    HAL_PIXEL_FORMAT_RAW16 = 32, // 0x20
+    HAL_PIXEL_FORMAT_RAW10 = 37, // 0x25
+    HAL_PIXEL_FORMAT_RAW12 = 38, // 0x26
+    HAL_PIXEL_FORMAT_RAW_OPAQUE = 36, // 0x24
+    HAL_PIXEL_FORMAT_BLOB = 33, // 0x21
+    HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED = 34, // 0x22
+    HAL_PIXEL_FORMAT_YCBCR_420_888 = 35, // 0x23
+    HAL_PIXEL_FORMAT_YCBCR_422_888 = 39, // 0x27
+    HAL_PIXEL_FORMAT_YCBCR_444_888 = 40, // 0x28
+    HAL_PIXEL_FORMAT_FLEX_RGB_888 = 41, // 0x29
+    HAL_PIXEL_FORMAT_FLEX_RGBA_8888 = 42, // 0x2A
+    HAL_PIXEL_FORMAT_YCBCR_422_SP = 16, // 0x10
+    HAL_PIXEL_FORMAT_YCRCB_420_SP = 17, // 0x11
+    HAL_PIXEL_FORMAT_YCBCR_422_I = 20, // 0x14
+} android_pixel_format_t;
+
+typedef enum {
+    HAL_TRANSFORM_FLIP_H = 1, // 0x01
+    HAL_TRANSFORM_FLIP_V = 2, // 0x02
+    HAL_TRANSFORM_ROT_90 = 4, // 0x04
+    HAL_TRANSFORM_ROT_180 = 3, // 0x03
+    HAL_TRANSFORM_ROT_270 = 7, // 0x07
+} android_transform_t;
+
+typedef enum {
+    HAL_DATASPACE_UNKNOWN = 0, // 0x0
+    HAL_DATASPACE_ARBITRARY = 1, // 0x1
+    HAL_DATASPACE_STANDARD_SHIFT = 16,
+    HAL_DATASPACE_STANDARD_MASK = 4128768, // (63 << STANDARD_SHIFT)
+    HAL_DATASPACE_STANDARD_UNSPECIFIED = 0, // (0 << STANDARD_SHIFT)
+    HAL_DATASPACE_STANDARD_BT709 = 65536, // (1 << STANDARD_SHIFT)
+    HAL_DATASPACE_STANDARD_BT601_625 = 131072, // (2 << STANDARD_SHIFT)
+    HAL_DATASPACE_STANDARD_BT601_625_UNADJUSTED = 196608, // (3 << STANDARD_SHIFT)
+    HAL_DATASPACE_STANDARD_BT601_525 = 262144, // (4 << STANDARD_SHIFT)
+    HAL_DATASPACE_STANDARD_BT601_525_UNADJUSTED = 327680, // (5 << STANDARD_SHIFT)
+    HAL_DATASPACE_STANDARD_BT2020 = 393216, // (6 << STANDARD_SHIFT)
+    HAL_DATASPACE_STANDARD_BT2020_CONSTANT_LUMINANCE = 458752, // (7 << STANDARD_SHIFT)
+    HAL_DATASPACE_STANDARD_BT470M = 524288, // (8 << STANDARD_SHIFT)
+    HAL_DATASPACE_STANDARD_FILM = 589824, // (9 << STANDARD_SHIFT)
+    HAL_DATASPACE_TRANSFER_SHIFT = 22,
+    HAL_DATASPACE_TRANSFER_MASK = 130023424, // (31 << TRANSFER_SHIFT)
+    HAL_DATASPACE_TRANSFER_UNSPECIFIED = 0, // (0 << TRANSFER_SHIFT)
+    HAL_DATASPACE_TRANSFER_LINEAR = 4194304, // (1 << TRANSFER_SHIFT)
+    HAL_DATASPACE_TRANSFER_SRGB = 8388608, // (2 << TRANSFER_SHIFT)
+    HAL_DATASPACE_TRANSFER_SMPTE_170M = 12582912, // (3 << TRANSFER_SHIFT)
+    HAL_DATASPACE_TRANSFER_GAMMA2_2 = 16777216, // (4 << TRANSFER_SHIFT)
+    HAL_DATASPACE_TRANSFER_GAMMA2_8 = 20971520, // (5 << TRANSFER_SHIFT)
+    HAL_DATASPACE_TRANSFER_ST2084 = 25165824, // (6 << TRANSFER_SHIFT)
+    HAL_DATASPACE_TRANSFER_HLG = 29360128, // (7 << TRANSFER_SHIFT)
+    HAL_DATASPACE_RANGE_SHIFT = 27,
+    HAL_DATASPACE_RANGE_MASK = 939524096, // (7 << RANGE_SHIFT)
+    HAL_DATASPACE_RANGE_UNSPECIFIED = 0, // (0 << RANGE_SHIFT)
+    HAL_DATASPACE_RANGE_FULL = 134217728, // (1 << RANGE_SHIFT)
+    HAL_DATASPACE_RANGE_LIMITED = 268435456, // (2 << RANGE_SHIFT)
+    HAL_DATASPACE_SRGB_LINEAR = 512, // 0x200
+    HAL_DATASPACE_V0_SRGB_LINEAR = 138477568, // ((STANDARD_BT709 | TRANSFER_LINEAR) | RANGE_FULL)
+    HAL_DATASPACE_SRGB = 513, // 0x201
+    HAL_DATASPACE_V0_SRGB = 142671872, // ((STANDARD_BT709 | TRANSFER_SRGB) | RANGE_FULL)
+    HAL_DATASPACE_JFIF = 257, // 0x101
+    HAL_DATASPACE_V0_JFIF = 146931712, // ((STANDARD_BT601_625 | TRANSFER_SMPTE_170M) | RANGE_FULL)
+    HAL_DATASPACE_BT601_625 = 258, // 0x102
+    HAL_DATASPACE_V0_BT601_625 = 281149440, // ((STANDARD_BT601_625 | TRANSFER_SMPTE_170M) | RANGE_LIMITED)
+    HAL_DATASPACE_BT601_525 = 259, // 0x103
+    HAL_DATASPACE_V0_BT601_525 = 281280512, // ((STANDARD_BT601_525 | TRANSFER_SMPTE_170M) | RANGE_LIMITED)
+    HAL_DATASPACE_BT709 = 260, // 0x104
+    HAL_DATASPACE_V0_BT709 = 281083904, // ((STANDARD_BT709 | TRANSFER_SMPTE_170M) | RANGE_LIMITED)
+    HAL_DATASPACE_DEPTH = 4096, // 0x1000
+} android_dataspace_t;
+
+typedef enum {
+    HAL_COLOR_MODE_NATIVE = 0,
+    HAL_COLOR_MODE_STANDARD_BT601_625 = 1,
+    HAL_COLOR_MODE_STANDARD_BT601_625_UNADJUSTED = 2,
+    HAL_COLOR_MODE_STANDARD_BT601_525 = 3,
+    HAL_COLOR_MODE_STANDARD_BT601_525_UNADJUSTED = 4,
+    HAL_COLOR_MODE_STANDARD_BT709 = 5,
+    HAL_COLOR_MODE_DCI_P3 = 6,
+    HAL_COLOR_MODE_SRGB = 7,
+    HAL_COLOR_MODE_ADOBE_RGB = 8,
+} android_color_mode_t;
+
+typedef enum {
+    HAL_COLOR_TRANSFORM_IDENTITY = 0,
+    HAL_COLOR_TRANSFORM_ARBITRARY_MATRIX = 1,
+    HAL_COLOR_TRANSFORM_VALUE_INVERSE = 2,
+    HAL_COLOR_TRANSFORM_GRAYSCALE = 3,
+    HAL_COLOR_TRANSFORM_CORRECT_PROTANOPIA = 4,
+    HAL_COLOR_TRANSFORM_CORRECT_DEUTERANOPIA = 5,
+    HAL_COLOR_TRANSFORM_CORRECT_TRITANOPIA = 6,
+} android_color_transform_t;
+
+typedef enum {
+    HAL_HDR_DOLBY_VISION = 1,
+    HAL_HDR_HDR10 = 2,
+    HAL_HDR_HLG = 3,
+} android_hdr_t;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  // HIDL_GENERATED_android_hardware_graphics_common_V1_0_EXPORTED_CONSTANTS_H_
diff --git a/include/system/graphics.h b/include/system/graphics.h
index ae10fa0..449b8c7 100644
--- a/include/system/graphics.h
+++ b/include/system/graphics.h
@@ -20,10 +20,30 @@
 #include <stddef.h>
 #include <stdint.h>
 
+/*
+ * Some of the enums are now defined in HIDL in hardware/interfaces and are
+ * generated.
+ */
+#include "graphics-base.h"
+
 #ifdef __cplusplus
 extern "C" {
 #endif
 
+/* for compatibility */
+#define HAL_PIXEL_FORMAT_YCbCr_420_888 HAL_PIXEL_FORMAT_YCBCR_420_888
+#define HAL_PIXEL_FORMAT_YCbCr_422_888 HAL_PIXEL_FORMAT_YCBCR_422_888
+#define HAL_PIXEL_FORMAT_YCbCr_444_888 HAL_PIXEL_FORMAT_YCBCR_444_888
+#define HAL_PIXEL_FORMAT_YCbCr_422_SP HAL_PIXEL_FORMAT_YCBCR_422_SP
+#define HAL_PIXEL_FORMAT_YCrCb_420_SP HAL_PIXEL_FORMAT_YCRCB_420_SP
+#define HAL_PIXEL_FORMAT_YCbCr_422_I HAL_PIXEL_FORMAT_YCBCR_422_I
+typedef android_pixel_format_t android_pixel_format;
+typedef android_transform_t android_transform;
+typedef android_dataspace_t android_dataspace;
+typedef android_color_mode_t android_color_mode;
+typedef android_color_transform_t android_color_transform;
+typedef android_hdr_t android_hdr;
+
 /*
  * If the HAL needs to create service threads to handle graphics related
  * tasks, these threads need to run at HAL_PRIORITY_URGENT_DISPLAY priority
@@ -38,411 +58,6 @@
 
 #define HAL_PRIORITY_URGENT_DISPLAY     (-8)
 
-/**
- * pixel format definitions
- */
-
-typedef enum android_pixel_format {
-    /*
-     * "linear" color pixel 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,
-    HAL_PIXEL_FORMAT_RGB_888            = 3,
-    HAL_PIXEL_FORMAT_RGB_565            = 4,
-    HAL_PIXEL_FORMAT_BGRA_8888          = 5,
-
-    /*
-     * 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 a 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_stride = ALIGN(stride/2, 16)
-     *   c_size = c_stride * height/2
-     *   size = y_size + c_size * 2
-     *   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
-
-
-    /*
-     * Android Y8 format:
-     *
-     * This format is exposed outside of the HAL to the framework.
-     * The expected gralloc usage flags are SW_* and HW_CAMERA_*,
-     * and no other HW_ flags will be used.
-     *
-     * Y8 is a YUV planar format comprised of a WxH Y plane,
-     * with each pixel being represented by 8 bits.
-     *
-     * It is equivalent to just the Y plane from YV12.
-     *
-     * This format assumes
-     * - an even width
-     * - an even height
-     * - a horizontal stride multiple of 16 pixels
-     * - a vertical stride equal to the height
-     *
-     *   size = stride * height
-     *
-     * When used with ANativeWindow, the dataSpace field describes the color
-     * space of the buffer.
-     */
-    HAL_PIXEL_FORMAT_Y8     = 0x20203859,
-
-    /*
-     * Android Y16 format:
-     *
-     * This format is exposed outside of the HAL to the framework.
-     * The expected gralloc usage flags are SW_* and HW_CAMERA_*,
-     * and no other HW_ flags will be used.
-     *
-     * Y16 is a YUV planar format comprised of a WxH Y plane,
-     * with each pixel being represented by 16 bits.
-     *
-     * It is just like Y8, but has double the bits per pixel (little endian).
-     *
-     * This format assumes
-     * - an even width
-     * - an even height
-     * - a horizontal stride multiple of 16 pixels
-     * - a vertical stride equal to the height
-     * - strides are specified in pixels, not in bytes
-     *
-     *   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,
-     * plus an associated confidence value.
-     */
-    HAL_PIXEL_FORMAT_Y16    = 0x20363159,
-
-    /*
-     * Android RAW sensor format:
-     *
-     * This format is exposed outside of the camera HAL to applications.
-     *
-     * RAW16 is a single-channel, 16-bit, little endian format, typically
-     * representing raw Bayer-pattern images from an image sensor, with minimal
-     * processing.
-     *
-     * The exact pixel layout of the data in the buffer is sensor-dependent, and
-     * needs to be queried from the camera device.
-     *
-     * Generally, not all 16 bits are used; more common values are 10 or 12
-     * bits. If not all bits are used, the lower-order bits are filled first.
-     * All parameters to interpret the raw data (black and white points,
-     * color space, etc) must be queried from the camera device.
-     *
-     * This format assumes
-     * - an even width
-     * - an even height
-     * - a horizontal stride multiple of 16 pixels
-     * - a vertical stride equal to the height
-     * - strides are specified in pixels, not in bytes
-     *
-     *   size = stride * height * 2
-     *
-     * This format must be accepted by the gralloc module when used with the
-     * following usage flags:
-     *    - 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,
-
-    /*
-     * Android RAW10 format:
-     *
-     * This format is exposed outside of the camera HAL to applications.
-     *
-     * RAW10 is a single-channel, 10-bit per pixel, densely packed in each row,
-     * unprocessed format, usually representing raw Bayer-pattern images coming from
-     * an image sensor.
-     *
-     * In an image buffer with this format, starting from the first pixel of each
-     * row, each 4 consecutive pixels are packed into 5 bytes (40 bits). Each one
-     * of the first 4 bytes contains the top 8 bits of each pixel, The fifth byte
-     * contains the 2 least significant bits of the 4 pixels, the exact layout data
-     * for each 4 consecutive pixels is illustrated below (Pi[j] stands for the jth
-     * bit of the ith pixel):
-     *
-     *          bit 7                                     bit 0
-     *          =====|=====|=====|=====|=====|=====|=====|=====|
-     * Byte 0: |P0[9]|P0[8]|P0[7]|P0[6]|P0[5]|P0[4]|P0[3]|P0[2]|
-     *         |-----|-----|-----|-----|-----|-----|-----|-----|
-     * Byte 1: |P1[9]|P1[8]|P1[7]|P1[6]|P1[5]|P1[4]|P1[3]|P1[2]|
-     *         |-----|-----|-----|-----|-----|-----|-----|-----|
-     * Byte 2: |P2[9]|P2[8]|P2[7]|P2[6]|P2[5]|P2[4]|P2[3]|P2[2]|
-     *         |-----|-----|-----|-----|-----|-----|-----|-----|
-     * Byte 3: |P3[9]|P3[8]|P3[7]|P3[6]|P3[5]|P3[4]|P3[3]|P3[2]|
-     *         |-----|-----|-----|-----|-----|-----|-----|-----|
-     * Byte 4: |P3[1]|P3[0]|P2[1]|P2[0]|P1[1]|P1[0]|P0[1]|P0[0]|
-     *          ===============================================
-     *
-     * This format assumes
-     * - a width multiple of 4 pixels
-     * - an even height
-     * - a vertical stride equal to the height
-     * - strides are specified in bytes, not in pixels
-     *
-     *   size = stride * height
-     *
-     * When stride is equal to width * (10 / 8), there will be no padding bytes at
-     * the end of each row, the entire image data is densely packed. When stride is
-     * larger than width * (10 / 8), padding bytes will be present at the end of each
-     * row (including the last row).
-     *
-     * This format must be accepted by the gralloc module when used with the
-     * following usage flags:
-     *    - 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,
-
-    /*
-     * Android RAW12 format:
-     *
-     * This format is exposed outside of camera HAL to applications.
-     *
-     * RAW12 is a single-channel, 12-bit per pixel, densely packed in each row,
-     * unprocessed format, usually representing raw Bayer-pattern images coming from
-     * an image sensor.
-     *
-     * In an image buffer with this format, starting from the first pixel of each
-     * row, each two consecutive pixels are packed into 3 bytes (24 bits). The first
-     * and second byte contains the top 8 bits of first and second pixel. The third
-     * byte contains the 4 least significant bits of the two pixels, the exact layout
-     * data for each two consecutive pixels is illustrated below (Pi[j] stands for
-     * the jth bit of the ith pixel):
-     *
-     *           bit 7                                            bit 0
-     *          ======|======|======|======|======|======|======|======|
-     * Byte 0: |P0[11]|P0[10]|P0[ 9]|P0[ 8]|P0[ 7]|P0[ 6]|P0[ 5]|P0[ 4]|
-     *         |------|------|------|------|------|------|------|------|
-     * Byte 1: |P1[11]|P1[10]|P1[ 9]|P1[ 8]|P1[ 7]|P1[ 6]|P1[ 5]|P1[ 4]|
-     *         |------|------|------|------|------|------|------|------|
-     * Byte 2: |P1[ 3]|P1[ 2]|P1[ 1]|P1[ 0]|P0[ 3]|P0[ 2]|P0[ 1]|P0[ 0]|
-     *          =======================================================
-     *
-     * This format assumes:
-     * - a width multiple of 4 pixels
-     * - an even height
-     * - a vertical stride equal to the height
-     * - strides are specified in bytes, not in pixels
-     *
-     *   size = stride * height
-     *
-     * When stride is equal to width * (12 / 8), there will be no padding bytes at
-     * the end of each row, the entire image data is densely packed. When stride is
-     * larger than width * (12 / 8), padding bytes will be present at the end of
-     * each row (including the last row).
-     *
-     * This format must be accepted by the gralloc module when used with the
-     * following usage flags:
-     *    - 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_RAW12 = 0x26,
-
-    /*
-     * Android opaque RAW format:
-     *
-     * This format is exposed outside of the camera HAL to applications.
-     *
-     * RAW_OPAQUE is a format for unprocessed raw image buffers coming from an
-     * image sensor. The actual structure of buffers of this format is
-     * implementation-dependent.
-     *
-     * This format must be accepted by the gralloc module when used with the
-     * following usage flags:
-     *    - 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,
-
-    /*
-     * Android binary blob graphics buffer format:
-     *
-     * This format is used to carry task-specific data which does not have a
-     * standard image structure. The details of the format are left to the two
-     * endpoints.
-     *
-     * A typical use case is for transporting JPEG-compressed images from the
-     * Camera HAL to the framework or to applications.
-     *
-     * 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,
-
-    /*
-     * Android format indicating that the choice of format is entirely up to the
-     * device-specific Gralloc implementation.
-     *
-     * The Gralloc implementation should examine the usage bits passed in when
-     * allocating a buffer with this format, and it should derive the pixel
-     * format from those usage flags.  This format will never be used with any
-     * of the GRALLOC_USAGE_SW_* usage flags.
-     *
-     * If a buffer of this format is to be used as an OpenGL ES texture, the
-     * 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,
-
-    /*
-     * Android flexible YCbCr 4:2:0 formats
-     *
-     * This format allows platforms to use an efficient YCbCr/YCrCb 4:2:0
-     * buffer layout, while still describing the general format in a
-     * layout-independent manner.  While called YCbCr, it can be
-     * used to describe formats with either chromatic ordering, as well as
-     * whole planar or semiplanar layouts.
-     *
-     * struct android_ycbcr (below) is the the struct used to describe it.
-     *
-     * This format must be accepted by the gralloc module when
-     * USAGE_SW_WRITE_* or USAGE_SW_READ_* are set.
-     *
-     * 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,
-
-    /*
-     * Android flexible YCbCr 4:2:2 formats
-     *
-     * This format allows platforms to use an efficient YCbCr/YCrCb 4:2:2
-     * buffer layout, while still describing the general format in a
-     * layout-independent manner.  While called YCbCr, it can be
-     * used to describe formats with either chromatic ordering, as well as
-     * whole planar or semiplanar layouts.
-     *
-     * This format is currently only used by SW readable buffers
-     * produced by MediaCodecs, so the gralloc module can ignore this format.
-     */
-    HAL_PIXEL_FORMAT_YCbCr_422_888 = 0x27,
-
-    /*
-     * Android flexible YCbCr 4:4:4 formats
-     *
-     * This format allows platforms to use an efficient YCbCr/YCrCb 4:4:4
-     * buffer layout, while still describing the general format in a
-     * layout-independent manner.  While called YCbCr, it can be
-     * used to describe formats with either chromatic ordering, as well as
-     * whole planar or semiplanar layouts.
-     *
-     * This format is currently only used by SW readable buffers
-     * produced by MediaCodecs, so the gralloc module can ignore this format.
-     */
-    HAL_PIXEL_FORMAT_YCbCr_444_888 = 0x28,
-
-    /*
-     * Android flexible RGB 888 formats
-     *
-     * This format allows platforms to use an efficient RGB/BGR/RGBX/BGRX
-     * buffer layout, while still describing the general format in a
-     * layout-independent manner.  While called RGB, it can be
-     * used to describe formats with either color ordering and optional
-     * padding, as well as whole planar layout.
-     *
-     * This format is currently only used by SW readable buffers
-     * produced by MediaCodecs, so the gralloc module can ignore this format.
-     */
-    HAL_PIXEL_FORMAT_FLEX_RGB_888 = 0x29,
-
-    /*
-     * Android flexible RGBA 8888 formats
-     *
-     * This format allows platforms to use an efficient RGBA/BGRA/ARGB/ABGR
-     * buffer layout, while still describing the general format in a
-     * layout-independent manner.  While called RGBA, it can be
-     * used to describe formats with any of the component orderings, as
-     * well as whole planar layout.
-     *
-     * This format is currently only used by SW readable buffers
-     * produced by MediaCodecs, so the gralloc module can ignore this format.
-     */
-    HAL_PIXEL_FORMAT_FLEX_RGBA_8888 = 0x2A,
-
-    /* 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
-} android_pixel_format_t;
-
 /*
  * Structure for describing YCbCr formats for consumption by applications.
  * This is used with HAL_PIXEL_FORMAT_YCbCr_*_888.
@@ -622,797 +237,6 @@
 #endif
 };
 
-/**
- * Transformation definitions
- *
- * IMPORTANT NOTE:
- * HAL_TRANSFORM_ROT_90 is applied CLOCKWISE and AFTER HAL_TRANSFORM_FLIP_{H|V}.
- *
- */
-
-typedef enum android_transform {
-    /* 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,
-    /* don't use. see system/window.h */
-    HAL_TRANSFORM_RESERVED  = 0x08,
-} android_transform_t;
-
-/**
- * Dataspace Definitions
- * ======================
- *
- * 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.
- *
- * A dataspace is comprised of a number of fields.
- *
- * Version
- * --------
- * The top 2 bits represent the revision of the field specification. This is
- * currently always 0.
- *
- *
- * bits    31-30 29                      -                          0
- *        +-----+----------------------------------------------------+
- * fields | Rev |            Revision specific fields                |
- *        +-----+----------------------------------------------------+
- *
- * Field layout for version = 0:
- * ----------------------------
- *
- * A dataspace is comprised of the following fields:
- *      Standard
- *      Transfer function
- *      Range
- *
- * bits    31-30 29-27 26 -  22 21 -  16 15             -           0
- *        +-----+-----+--------+--------+----------------------------+
- * fields |  0  |Range|Transfer|Standard|    Legacy and custom       |
- *        +-----+-----+--------+--------+----------------------------+
- *          VV    RRR   TTTTT    SSSSSS    LLLLLLLL       LLLLLLLL
- *
- * If range, transfer and standard fields are all 0 (e.g. top 16 bits are
- * all zeroes), the bottom 16 bits contain either a legacy dataspace value,
- * or a custom value.
- */
-
-typedef enum android_dataspace {
-    /*
-     * 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.
-     *
-     * A typical use case is in video encoding parameters (e.g. for H.264),
-     * where a colorspace can have separately defined primaries, transfer
-     * characteristics, etc.
-     */
-    HAL_DATASPACE_ARBITRARY = 0x1,
-
-    /*
-     * Color-description aspects
-     *
-     * The following aspects define various characteristics of the color
-     * specification. These represent bitfields, so that a data space value
-     * can specify each of them independently.
-     */
-
-    HAL_DATASPACE_STANDARD_SHIFT = 16,
-
-    /*
-     * Standard aspect
-     *
-     * Defines the chromaticity coordinates of the source primaries in terms of
-     * the CIE 1931 definition of x and y specified in ISO 11664-1.
-     */
-    HAL_DATASPACE_STANDARD_MASK = 63 << HAL_DATASPACE_STANDARD_SHIFT,  // 0x3F
-
-    /*
-     * Chromacity coordinates are unknown or are determined by the application.
-     * Implementations shall use the following suggested standards:
-     *
-     * All YCbCr formats: BT709 if size is 720p or larger (since most video
-     *                    content is letterboxed this corresponds to width is
-     *                    1280 or greater, or height is 720 or greater).
-     *                    BT601_625 if size is smaller than 720p or is JPEG.
-     * All RGB formats:   BT709.
-     *
-     * For all other formats standard is undefined, and implementations should use
-     * an appropriate standard for the data represented.
-     */
-    HAL_DATASPACE_STANDARD_UNSPECIFIED = 0 << HAL_DATASPACE_STANDARD_SHIFT,
-
-    /*
-     * Primaries:       x       y
-     *  green           0.300   0.600
-     *  blue            0.150   0.060
-     *  red             0.640   0.330
-     *  white (D65)     0.3127  0.3290
-     *
-     * Use the unadjusted KR = 0.2126, KB = 0.0722 luminance interpretation
-     * for RGB conversion.
-     */
-    HAL_DATASPACE_STANDARD_BT709 = 1 << HAL_DATASPACE_STANDARD_SHIFT,
-
-    /*
-     * Primaries:       x       y
-     *  green           0.290   0.600
-     *  blue            0.150   0.060
-     *  red             0.640   0.330
-     *  white (D65)     0.3127  0.3290
-     *
-     *  KR = 0.299, KB = 0.114. This adjusts the luminance interpretation
-     *  for RGB conversion from the one purely determined by the primaries
-     *  to minimize the color shift into RGB space that uses BT.709
-     *  primaries.
-     */
-    HAL_DATASPACE_STANDARD_BT601_625 = 2 << HAL_DATASPACE_STANDARD_SHIFT,
-
-    /*
-     * Primaries:       x       y
-     *  green           0.290   0.600
-     *  blue            0.150   0.060
-     *  red             0.640   0.330
-     *  white (D65)     0.3127  0.3290
-     *
-     * Use the unadjusted KR = 0.222, KB = 0.071 luminance interpretation
-     * for RGB conversion.
-     */
-    HAL_DATASPACE_STANDARD_BT601_625_UNADJUSTED = 3 << HAL_DATASPACE_STANDARD_SHIFT,
-
-    /*
-     * Primaries:       x       y
-     *  green           0.310   0.595
-     *  blue            0.155   0.070
-     *  red             0.630   0.340
-     *  white (D65)     0.3127  0.3290
-     *
-     *  KR = 0.299, KB = 0.114. This adjusts the luminance interpretation
-     *  for RGB conversion from the one purely determined by the primaries
-     *  to minimize the color shift into RGB space that uses BT.709
-     *  primaries.
-     */
-    HAL_DATASPACE_STANDARD_BT601_525 = 4 << HAL_DATASPACE_STANDARD_SHIFT,
-
-    /*
-     * Primaries:       x       y
-     *  green           0.310   0.595
-     *  blue            0.155   0.070
-     *  red             0.630   0.340
-     *  white (D65)     0.3127  0.3290
-     *
-     * Use the unadjusted KR = 0.212, KB = 0.087 luminance interpretation
-     * for RGB conversion (as in SMPTE 240M).
-     */
-    HAL_DATASPACE_STANDARD_BT601_525_UNADJUSTED = 5 << HAL_DATASPACE_STANDARD_SHIFT,
-
-    /*
-     * Primaries:       x       y
-     *  green           0.170   0.797
-     *  blue            0.131   0.046
-     *  red             0.708   0.292
-     *  white (D65)     0.3127  0.3290
-     *
-     * Use the unadjusted KR = 0.2627, KB = 0.0593 luminance interpretation
-     * for RGB conversion.
-     */
-    HAL_DATASPACE_STANDARD_BT2020 = 6 << HAL_DATASPACE_STANDARD_SHIFT,
-
-    /*
-     * Primaries:       x       y
-     *  green           0.170   0.797
-     *  blue            0.131   0.046
-     *  red             0.708   0.292
-     *  white (D65)     0.3127  0.3290
-     *
-     * Use the unadjusted KR = 0.2627, KB = 0.0593 luminance interpretation
-     * for RGB conversion using the linear domain.
-     */
-    HAL_DATASPACE_STANDARD_BT2020_CONSTANT_LUMINANCE = 7 << HAL_DATASPACE_STANDARD_SHIFT,
-
-    /*
-     * Primaries:       x      y
-     *  green           0.21   0.71
-     *  blue            0.14   0.08
-     *  red             0.67   0.33
-     *  white (C)       0.310  0.316
-     *
-     * Use the unadjusted KR = 0.30, KB = 0.11 luminance interpretation
-     * for RGB conversion.
-     */
-    HAL_DATASPACE_STANDARD_BT470M = 8 << HAL_DATASPACE_STANDARD_SHIFT,
-
-    /*
-     * Primaries:       x       y
-     *  green           0.243   0.692
-     *  blue            0.145   0.049
-     *  red             0.681   0.319
-     *  white (C)       0.310   0.316
-     *
-     * Use the unadjusted KR = 0.254, KB = 0.068 luminance interpretation
-     * for RGB conversion.
-     */
-    HAL_DATASPACE_STANDARD_FILM = 9 << HAL_DATASPACE_STANDARD_SHIFT,
-
-    HAL_DATASPACE_TRANSFER_SHIFT = 22,
-
-    /*
-     * Transfer aspect
-     *
-     * Transfer characteristics are the opto-electronic transfer characteristic
-     * at the source as a function of linear optical intensity (luminance).
-     *
-     * For digital signals, E corresponds to the recorded value. Normally, the
-     * transfer function is applied in RGB space to each of the R, G and B
-     * components independently. This may result in color shift that can be
-     * minized by applying the transfer function in Lab space only for the L
-     * component. Implementation may apply the transfer function in RGB space
-     * for all pixel formats if desired.
-     */
-
-    HAL_DATASPACE_TRANSFER_MASK = 31 << HAL_DATASPACE_TRANSFER_SHIFT,  // 0x1F
-
-    /*
-     * Transfer characteristics are unknown or are determined by the
-     * application.
-     *
-     * Implementations should use the following transfer functions:
-     *
-     * For YCbCr formats: use HAL_DATASPACE_TRANSFER_SMPTE_170M
-     * For RGB formats: use HAL_DATASPACE_TRANSFER_SRGB
-     *
-     * For all other formats transfer function is undefined, and implementations
-     * should use an appropriate standard for the data represented.
-     */
-    HAL_DATASPACE_TRANSFER_UNSPECIFIED = 0 << HAL_DATASPACE_TRANSFER_SHIFT,
-
-    /*
-     * Transfer characteristic curve:
-     *  E = L
-     *      L - luminance of image 0 <= L <= 1 for conventional colorimetry
-     *      E - corresponding electrical signal
-     */
-    HAL_DATASPACE_TRANSFER_LINEAR = 1 << HAL_DATASPACE_TRANSFER_SHIFT,
-
-    /*
-     * Transfer characteristic curve:
-     *
-     * E = 1.055 * L^(1/2.4) - 0.055  for 0.0031308 <= L <= 1
-     *   = 12.92 * L                  for 0 <= L < 0.0031308
-     *     L - luminance of image 0 <= L <= 1 for conventional colorimetry
-     *     E - corresponding electrical signal
-     */
-    HAL_DATASPACE_TRANSFER_SRGB = 2 << HAL_DATASPACE_TRANSFER_SHIFT,
-
-    /*
-     * BT.601 525, BT.601 625, BT.709, BT.2020
-     *
-     * Transfer characteristic curve:
-     *  E = 1.099 * L ^ 0.45 - 0.099  for 0.018 <= L <= 1
-     *    = 4.500 * L                 for 0 <= L < 0.018
-     *      L - luminance of image 0 <= L <= 1 for conventional colorimetry
-     *      E - corresponding electrical signal
-     */
-    HAL_DATASPACE_TRANSFER_SMPTE_170M = 3 << HAL_DATASPACE_TRANSFER_SHIFT,
-
-    /*
-     * Assumed display gamma 2.2.
-     *
-     * Transfer characteristic curve:
-     *  E = L ^ (1/2.2)
-     *      L - luminance of image 0 <= L <= 1 for conventional colorimetry
-     *      E - corresponding electrical signal
-     */
-    HAL_DATASPACE_TRANSFER_GAMMA2_2 = 4 << HAL_DATASPACE_TRANSFER_SHIFT,
-
-    /*
-     *  display gamma 2.8.
-     *
-     * Transfer characteristic curve:
-     *  E = L ^ (1/2.8)
-     *      L - luminance of image 0 <= L <= 1 for conventional colorimetry
-     *      E - corresponding electrical signal
-     */
-    HAL_DATASPACE_TRANSFER_GAMMA2_8 = 5 << HAL_DATASPACE_TRANSFER_SHIFT,
-
-    /*
-     * SMPTE ST 2084
-     *
-     * Transfer characteristic curve:
-     *  E = ((c1 + c2 * L^n) / (1 + c3 * L^n)) ^ m
-     *  c1 = c3 - c2 + 1 = 3424 / 4096 = 0.8359375
-     *  c2 = 32 * 2413 / 4096 = 18.8515625
-     *  c3 = 32 * 2392 / 4096 = 18.6875
-     *  m = 128 * 2523 / 4096 = 78.84375
-     *  n = 0.25 * 2610 / 4096 = 0.1593017578125
-     *      L - luminance of image 0 <= L <= 1 for HDR colorimetry.
-     *          L = 1 corresponds to 10000 cd/m2
-     *      E - corresponding electrical signal
-     */
-    HAL_DATASPACE_TRANSFER_ST2084 = 6 << HAL_DATASPACE_TRANSFER_SHIFT,
-
-    /*
-     * ARIB STD-B67 Hybrid Log Gamma
-     *
-     * Transfer characteristic curve:
-     *  E = r * L^0.5                 for 0 <= L <= 1
-     *    = a * ln(L - b) + c         for 1 < L
-     *  a = 0.17883277
-     *  b = 0.28466892
-     *  c = 0.55991073
-     *  r = 0.5
-     *      L - luminance of image 0 <= L for HDR colorimetry. L = 1 corresponds
-     *          to reference white level of 100 cd/m2
-     *      E - corresponding electrical signal
-     */
-    HAL_DATASPACE_TRANSFER_HLG = 7 << HAL_DATASPACE_TRANSFER_SHIFT,
-
-    HAL_DATASPACE_RANGE_SHIFT = 27,
-
-    /*
-     * Range aspect
-     *
-     * Defines the range of values corresponding to the unit range of 0-1.
-     * This is defined for YCbCr only, but can be expanded to RGB space.
-     */
-    HAL_DATASPACE_RANGE_MASK = 7 << HAL_DATASPACE_RANGE_SHIFT,  // 0x7
-
-    /*
-     * Range is unknown or are determined by the application.  Implementations
-     * shall use the following suggested ranges:
-     *
-     * All YCbCr formats: limited range.
-     * All RGB or RGBA formats (including RAW and Bayer): full range.
-     * All Y formats: full range
-     *
-     * For all other formats range is undefined, and implementations should use
-     * an appropriate range for the data represented.
-     */
-    HAL_DATASPACE_RANGE_UNSPECIFIED = 0 << HAL_DATASPACE_RANGE_SHIFT,
-
-    /*
-     * Full range uses all values for Y, Cb and Cr from
-     * 0 to 2^b-1, where b is the bit depth of the color format.
-     */
-    HAL_DATASPACE_RANGE_FULL = 1 << HAL_DATASPACE_RANGE_SHIFT,
-
-    /*
-     * Limited range uses values 16/256*2^b to 235/256*2^b for Y, and
-     * 1/16*2^b to 15/16*2^b for Cb, Cr, R, G and B, where b is the bit depth of
-     * the color format.
-     *
-     * E.g. For 8-bit-depth formats:
-     * Luma (Y) samples should range from 16 to 235, inclusive
-     * Chroma (Cb, Cr) samples should range from 16 to 240, inclusive
-     *
-     * For 10-bit-depth formats:
-     * Luma (Y) samples should range from 64 to 940, inclusive
-     * Chroma (Cb, Cr) samples should range from 64 to 960, inclusive
-     */
-    HAL_DATASPACE_RANGE_LIMITED = 2 << HAL_DATASPACE_RANGE_SHIFT,
-
-    /*
-     * Legacy dataspaces
-     */
-
-    /*
-     * 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, // deprecated, use HAL_DATASPACE_V0_SRGB_LINEAR
-
-    HAL_DATASPACE_V0_SRGB_LINEAR = HAL_DATASPACE_STANDARD_BT709 |
-            HAL_DATASPACE_TRANSFER_LINEAR | HAL_DATASPACE_RANGE_FULL,
-
-
-    /*
-     * sRGB gamma encoding:
-     *
-     * The red, green and blue components are stored in sRGB space, and
-     * converted to linear space when read, using the SRGB transfer function
-     * for each of the R, G and B components. When written, the inverse
-     * transformation is performed.
-     *
-     * The alpha component, if present, is always stored in linear space and
-     * is left unmodified when read or written.
-     *
-     * Use full range and BT.709 standard.
-     */
-    HAL_DATASPACE_SRGB = 0x201, // deprecated, use HAL_DATASPACE_V0_SRGB
-
-    HAL_DATASPACE_V0_SRGB = HAL_DATASPACE_STANDARD_BT709 |
-            HAL_DATASPACE_TRANSFER_SRGB | HAL_DATASPACE_RANGE_FULL,
-
-
-    /*
-     * YCbCr 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).
-     */
-
-    /*
-     * JPEG File Interchange Format (JFIF)
-     *
-     * Same model as BT.601-625, but all values (Y, Cb, Cr) range from 0 to 255
-     *
-     * Use full range, BT.601 transfer and BT.601_625 standard.
-     */
-    HAL_DATASPACE_JFIF = 0x101, // deprecated, use HAL_DATASPACE_V0_JFIF
-
-    HAL_DATASPACE_V0_JFIF = HAL_DATASPACE_STANDARD_BT601_625 |
-            HAL_DATASPACE_TRANSFER_SMPTE_170M | HAL_DATASPACE_RANGE_FULL,
-
-    /*
-     * ITU-R Recommendation 601 (BT.601) - 625-line
-     *
-     * Standard-definition television, 625 Lines (PAL)
-     *
-     * Use limited range, BT.601 transfer and BT.601_625 standard.
-     */
-    HAL_DATASPACE_BT601_625 = 0x102, // deprecated, use HAL_DATASPACE_V0_BT601_625
-
-    HAL_DATASPACE_V0_BT601_625 = HAL_DATASPACE_STANDARD_BT601_625 |
-            HAL_DATASPACE_TRANSFER_SMPTE_170M | HAL_DATASPACE_RANGE_LIMITED,
-
-
-    /*
-     * ITU-R Recommendation 601 (BT.601) - 525-line
-     *
-     * Standard-definition television, 525 Lines (NTSC)
-     *
-     * Use limited range, BT.601 transfer and BT.601_525 standard.
-     */
-    HAL_DATASPACE_BT601_525 = 0x103, // deprecated, use HAL_DATASPACE_V0_BT601_525
-
-    HAL_DATASPACE_V0_BT601_525 = HAL_DATASPACE_STANDARD_BT601_525 |
-            HAL_DATASPACE_TRANSFER_SMPTE_170M | HAL_DATASPACE_RANGE_LIMITED,
-
-    /*
-     * ITU-R Recommendation 709 (BT.709)
-     *
-     * High-definition television
-     *
-     * Use limited range, BT.709 transfer and BT.709 standard.
-     */
-    HAL_DATASPACE_BT709 = 0x104, // deprecated, use HAL_DATASPACE_V0_BT709
-
-    HAL_DATASPACE_V0_BT709 = HAL_DATASPACE_STANDARD_BT709 |
-            HAL_DATASPACE_TRANSFER_SMPTE_170M | HAL_DATASPACE_RANGE_LIMITED,
-
-    /*
-     * Data spaces for non-color formats
-     */
-
-    /*
-     * The buffer contains depth ranging measurements from a depth camera.
-     * This value is valid with formats:
-     *    HAL_PIXEL_FORMAT_Y16: 16-bit samples, consisting of a depth measurement
-     *       and an associated confidence value. The 3 MSBs of the sample make
-     *       up the confidence value, and the low 13 LSBs of the sample make up
-     *       the depth measurement.
-     *       For the confidence section, 0 means 100% confidence, 1 means 0%
-     *       confidence. The mapping to a linear float confidence value between
-     *       0.f and 1.f can be obtained with
-     *         float confidence = (((depthSample >> 13) - 1) & 0x7) / 7.0f;
-     *       The depth measurement can be extracted simply with
-     *         uint16_t range = (depthSample & 0x1FFF);
-     *    HAL_PIXEL_FORMAT_BLOB: A depth point cloud, as
-     *       a variable-length float (x,y,z, confidence) coordinate point list.
-     *       The point cloud will be represented with the android_depth_points
-     *       structure.
-     */
-    HAL_DATASPACE_DEPTH = 0x1000
-
-} android_dataspace_t;
-
-/*
- * Color modes that may be supported by a display.
- *
- * Definitions:
- * Rendering intent generally defines the goal in mapping a source (input)
- * color to a destination device color for a given color mode.
- *
- *  It is important to keep in mind three cases where mapping may be applied:
- *  1. The source gamut is much smaller than the destination (display) gamut
- *  2. The source gamut is much larger than the destination gamut (this will
- *  ordinarily be handled using colorimetric rendering, below)
- *  3. The source and destination gamuts are roughly equal, although not
- *  completely overlapping
- *  Also, a common requirement for mappings is that skin tones should be
- *  preserved, or at least remain natural in appearance.
- *
- *  Colorimetric Rendering Intent (All cases):
- *  Colorimetric indicates that colors should be preserved. In the case
- *  that the source gamut lies wholly within the destination gamut or is
- *  about the same (#1, #3), this will simply mean that no manipulations
- *  (no saturation boost, for example) are applied. In the case where some
- *  source colors lie outside the destination gamut (#2, #3), those will
- *  need to be mapped to colors that are within the destination gamut,
- *  while the already in-gamut colors remain unchanged.
- *
- *  Non-colorimetric transforms can take many forms. There are no hard
- *  rules and it's left to the implementation to define.
- *  Two common intents are described below.
- *
- *  Stretched-Gamut Enhancement Intent (Source < Destination):
- *  When the destination gamut is much larger than the source gamut (#1), the
- *  source primaries may be redefined to reflect the full extent of the
- *  destination space, or to reflect an intermediate gamut.
- *  Skin-tone preservation would likely be applied. An example might be sRGB
- *  input displayed on a DCI-P3 capable device, with skin-tone preservation.
- *
- *  Within-Gamut Enhancement Intent (Source >= Destination):
- *  When the device (destination) gamut is not larger than the source gamut
- *  (#2 or #3), but the appearance of a larger gamut is desired, techniques
- *  such as saturation boost may be applied to the source colors. Skin-tone
- *  preservation may be applied. There is no unique method for within-gamut
- *  enhancement; it would be defined within a flexible color mode.
- *
- */
-typedef enum android_color_mode {
-
-  /*
-   * HAL_COLOR_MODE_DEFAULT is the "native" gamut of the display.
-   * White Point: Vendor/OEM defined
-   * Panel Gamma: Vendor/OEM defined (typically 2.2)
-   * Rendering Intent: Vendor/OEM defined (typically 'enhanced')
-   */
-  HAL_COLOR_MODE_NATIVE = 0,
-
-  /*
-   * HAL_COLOR_MODE_STANDARD_BT601_625 corresponds with display
-   * settings that implement the ITU-R Recommendation BT.601
-   * or Rec 601. Using 625 line version
-   * Rendering Intent: Colorimetric
-   * Primaries:
-   *                  x       y
-   *  green           0.290   0.600
-   *  blue            0.150   0.060
-   *  red             0.640   0.330
-   *  white (D65)     0.3127  0.3290
-   *
-   *  KR = 0.299, KB = 0.114. This adjusts the luminance interpretation
-   *  for RGB conversion from the one purely determined by the primaries
-   *  to minimize the color shift into RGB space that uses BT.709
-   *  primaries.
-   *
-   * Gamma Correction (GC):
-   *
-   *  if Vlinear < 0.018
-   *    Vnonlinear = 4.500 * Vlinear
-   *  else
-   *    Vnonlinear = 1.099 * (Vlinear)^(0.45) – 0.099
-   */
-  HAL_COLOR_MODE_STANDARD_BT601_625 = 1,
-
-  /*
-   * Primaries:
-   *                  x       y
-   *  green           0.290   0.600
-   *  blue            0.150   0.060
-   *  red             0.640   0.330
-   *  white (D65)     0.3127  0.3290
-   *
-   *  Use the unadjusted KR = 0.222, KB = 0.071 luminance interpretation
-   *  for RGB conversion.
-   *
-   * Gamma Correction (GC):
-   *
-   *  if Vlinear < 0.018
-   *    Vnonlinear = 4.500 * Vlinear
-   *  else
-   *    Vnonlinear = 1.099 * (Vlinear)^(0.45) – 0.099
-   */
-  HAL_COLOR_MODE_STANDARD_BT601_625_UNADJUSTED = 2,
-
-  /*
-   * Primaries:
-   *                  x       y
-   *  green           0.310   0.595
-   *  blue            0.155   0.070
-   *  red             0.630   0.340
-   *  white (D65)     0.3127  0.3290
-   *
-   *  KR = 0.299, KB = 0.114. This adjusts the luminance interpretation
-   *  for RGB conversion from the one purely determined by the primaries
-   *  to minimize the color shift into RGB space that uses BT.709
-   *  primaries.
-   *
-   * Gamma Correction (GC):
-   *
-   *  if Vlinear < 0.018
-   *    Vnonlinear = 4.500 * Vlinear
-   *  else
-   *    Vnonlinear = 1.099 * (Vlinear)^(0.45) – 0.099
-   */
-  HAL_COLOR_MODE_STANDARD_BT601_525 = 3,
-
-  /*
-   * Primaries:
-   *                  x       y
-   *  green           0.310   0.595
-   *  blue            0.155   0.070
-   *  red             0.630   0.340
-   *  white (D65)     0.3127  0.3290
-   *
-   *  Use the unadjusted KR = 0.212, KB = 0.087 luminance interpretation
-   *  for RGB conversion (as in SMPTE 240M).
-   *
-   * Gamma Correction (GC):
-   *
-   *  if Vlinear < 0.018
-   *    Vnonlinear = 4.500 * Vlinear
-   *  else
-   *    Vnonlinear = 1.099 * (Vlinear)^(0.45) – 0.099
-   */
-  HAL_COLOR_MODE_STANDARD_BT601_525_UNADJUSTED = 4,
-
-  /*
-   * HAL_COLOR_MODE_REC709 corresponds with display settings that implement
-   * the ITU-R Recommendation BT.709 / Rec. 709 for high-definition television.
-   * Rendering Intent: Colorimetric
-   * Primaries:
-   *                  x       y
-   *  green           0.300   0.600
-   *  blue            0.150   0.060
-   *  red             0.640   0.330
-   *  white (D65)     0.3127  0.3290
-   *
-   * HDTV REC709 Inverse Gamma Correction (IGC): V represents normalized
-   * (with [0 to 1] range) value of R, G, or B.
-   *
-   *  if Vnonlinear < 0.081
-   *    Vlinear = Vnonlinear / 4.5
-   *  else
-   *    Vlinear = ((Vnonlinear + 0.099) / 1.099) ^ (1/0.45)
-   *
-   * HDTV REC709 Gamma Correction (GC):
-   *
-   *  if Vlinear < 0.018
-   *    Vnonlinear = 4.5 * Vlinear
-   *  else
-   *    Vnonlinear = 1.099 * (Vlinear) ^ 0.45 – 0.099
-   */
-  HAL_COLOR_MODE_STANDARD_BT709 = 5,
-
-  /*
-   * HAL_COLOR_MODE_DCI_P3 corresponds with display settings that implement
-   * SMPTE EG 432-1 and SMPTE RP 431-2
-   * Rendering Intent: Colorimetric
-   * Primaries:
-   *                  x       y
-   *  green           0.265   0.690
-   *  blue            0.150   0.060
-   *  red             0.680   0.320
-   *  white (D65)     0.3127  0.3290
-   *
-   * Gamma: 2.2
-   */
-  HAL_COLOR_MODE_DCI_P3 = 6,
-
-  /*
-   * HAL_COLOR_MODE_SRGB corresponds with display settings that implement
-   * the sRGB color space. Uses the same primaries as ITU-R Recommendation
-   * BT.709
-   * Rendering Intent: Colorimetric
-   * Primaries:
-   *                  x       y
-   *  green           0.300   0.600
-   *  blue            0.150   0.060
-   *  red             0.640   0.330
-   *  white (D65)     0.3127  0.3290
-   *
-   * PC/Internet (sRGB) Inverse Gamma Correction (IGC):
-   *
-   *  if Vnonlinear ≤ 0.03928
-   *    Vlinear = Vnonlinear / 12.92
-   *  else
-   *    Vlinear = ((Vnonlinear + 0.055)/1.055) ^ 2.4
-   *
-   * PC/Internet (sRGB) Gamma Correction (GC):
-   *
-   *  if Vlinear ≤ 0.0031308
-   *    Vnonlinear = 12.92 * Vlinear
-   *  else
-   *    Vnonlinear = 1.055 * (Vlinear)^(1/2.4) – 0.055
-   */
-  HAL_COLOR_MODE_SRGB = 7,
-
-  /*
-   * HAL_COLOR_MODE_ADOBE_RGB corresponds with the RGB color space developed
-   * by Adobe Systems, Inc. in 1998.
-   * Rendering Intent: Colorimetric
-   * Primaries:
-   *                  x       y
-   *  green           0.210   0.710
-   *  blue            0.150   0.060
-   *  red             0.640   0.330
-   *  white (D65)     0.3127  0.3290
-   *
-   * Gamma: 2.2
-   */
-  HAL_COLOR_MODE_ADOBE_RGB = 8
-
-} android_color_mode_t;
-
-/*
- * Color transforms that may be applied by hardware composer to the whole
- * display.
- */
-typedef enum android_color_transform {
-    /* Applies no transform to the output color */
-    HAL_COLOR_TRANSFORM_IDENTITY = 0,
-
-    /* Applies an arbitrary transform defined by a 4x4 affine matrix */
-    HAL_COLOR_TRANSFORM_ARBITRARY_MATRIX = 1,
-
-    /* Applies a transform that inverts the value or luminance of the color, but
-     * does not modify hue or saturation */
-    HAL_COLOR_TRANSFORM_VALUE_INVERSE = 2,
-
-    /* Applies a transform that maps all colors to shades of gray */
-    HAL_COLOR_TRANSFORM_GRAYSCALE = 3,
-
-    /* Applies a transform which corrects for protanopic color blindness */
-    HAL_COLOR_TRANSFORM_CORRECT_PROTANOPIA = 4,
-
-    /* Applies a transform which corrects for deuteranopic color blindness */
-    HAL_COLOR_TRANSFORM_CORRECT_DEUTERANOPIA = 5,
-
-    /* Applies a transform which corrects for tritanopic color blindness */
-    HAL_COLOR_TRANSFORM_CORRECT_TRITANOPIA = 6
-} android_color_transform_t;
-
-/*
- * Supported HDR formats. Must be kept in sync with equivalents in Display.java.
- */
-typedef enum android_hdr {
-    /* Device supports Dolby Vision HDR */
-    HAL_HDR_DOLBY_VISION = 1,
-
-    /* Device supports HDR10 */
-    HAL_HDR_HDR10 = 2,
-
-    /* Device supports hybrid log-gamma HDR */
-    HAL_HDR_HLG = 3
-} android_hdr_t;
-
 #ifdef __cplusplus
 }
 #endif
diff --git a/init/Android.mk b/init/Android.mk
index 1be064c..442a5f3 100644
--- a/init/Android.mk
+++ b/init/Android.mk
@@ -45,6 +45,8 @@
 LOCAL_CPPFLAGS := $(init_cflags)
 LOCAL_SRC_FILES:= \
     action.cpp \
+    capabilities.cpp \
+    descriptors.cpp \
     import_parser.cpp \
     init_parser.cpp \
     log.cpp \
@@ -53,6 +55,7 @@
     util.cpp \
 
 LOCAL_STATIC_LIBRARIES := libbase libselinux liblog libprocessgroup
+LOCAL_WHOLE_STATIC_LIBRARIES := libcap
 LOCAL_MODULE := libinit
 LOCAL_SANITIZE := integer
 LOCAL_CLANG := true
@@ -102,7 +105,7 @@
     libz \
     libprocessgroup
 
-# Create symlinks
+# Create symlinks.
 LOCAL_POST_INSTALL_CMD := $(hide) mkdir -p $(TARGET_ROOT_OUT)/sbin; \
     ln -sf ../init $(TARGET_ROOT_OUT)/sbin/ueventd; \
     ln -sf ../init $(TARGET_ROOT_OUT)/sbin/watchdogd
@@ -112,8 +115,8 @@
 include $(BUILD_EXECUTABLE)
 
 
-
-
+# Unit tests.
+# =========================================================
 include $(CLEAR_VARS)
 LOCAL_MODULE := init_tests
 LOCAL_SRC_FILES := \
@@ -123,8 +126,10 @@
 LOCAL_SHARED_LIBRARIES += \
     libcutils \
     libbase \
+    libselinux \
 
 LOCAL_STATIC_LIBRARIES := libinit
 LOCAL_SANITIZE := integer
 LOCAL_CLANG := true
+LOCAL_CPPFLAGS := -Wall -Wextra -Werror
 include $(BUILD_NATIVE_TEST)
diff --git a/init/capabilities.cpp b/init/capabilities.cpp
new file mode 100644
index 0000000..4592adc
--- /dev/null
+++ b/init/capabilities.cpp
@@ -0,0 +1,166 @@
+// Copyright (C) 2016 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 "capabilities.h"
+
+#include <sys/capability.h>
+#include <sys/prctl.h>
+
+#include <map>
+#include <memory>
+
+#include <android-base/logging.h>
+#include <android-base/macros.h>
+
+#define CAP_MAP_ENTRY(cap) { #cap, CAP_##cap }
+
+namespace {
+const std::map<std::string, int> cap_map = {
+    CAP_MAP_ENTRY(CHOWN),
+    CAP_MAP_ENTRY(DAC_OVERRIDE),
+    CAP_MAP_ENTRY(DAC_READ_SEARCH),
+    CAP_MAP_ENTRY(FOWNER),
+    CAP_MAP_ENTRY(FSETID),
+    CAP_MAP_ENTRY(KILL),
+    CAP_MAP_ENTRY(SETGID),
+    CAP_MAP_ENTRY(SETUID),
+    CAP_MAP_ENTRY(SETPCAP),
+    CAP_MAP_ENTRY(LINUX_IMMUTABLE),
+    CAP_MAP_ENTRY(NET_BIND_SERVICE),
+    CAP_MAP_ENTRY(NET_BROADCAST),
+    CAP_MAP_ENTRY(NET_ADMIN),
+    CAP_MAP_ENTRY(NET_RAW),
+    CAP_MAP_ENTRY(IPC_LOCK),
+    CAP_MAP_ENTRY(IPC_OWNER),
+    CAP_MAP_ENTRY(SYS_MODULE),
+    CAP_MAP_ENTRY(SYS_RAWIO),
+    CAP_MAP_ENTRY(SYS_CHROOT),
+    CAP_MAP_ENTRY(SYS_PTRACE),
+    CAP_MAP_ENTRY(SYS_PACCT),
+    CAP_MAP_ENTRY(SYS_ADMIN),
+    CAP_MAP_ENTRY(SYS_BOOT),
+    CAP_MAP_ENTRY(SYS_NICE),
+    CAP_MAP_ENTRY(SYS_RESOURCE),
+    CAP_MAP_ENTRY(SYS_TIME),
+    CAP_MAP_ENTRY(SYS_TTY_CONFIG),
+    CAP_MAP_ENTRY(MKNOD),
+    CAP_MAP_ENTRY(LEASE),
+    CAP_MAP_ENTRY(AUDIT_WRITE),
+    CAP_MAP_ENTRY(AUDIT_CONTROL),
+    CAP_MAP_ENTRY(SETFCAP),
+    CAP_MAP_ENTRY(MAC_OVERRIDE),
+    CAP_MAP_ENTRY(MAC_ADMIN),
+    CAP_MAP_ENTRY(SYSLOG),
+    CAP_MAP_ENTRY(WAKE_ALARM),
+    CAP_MAP_ENTRY(BLOCK_SUSPEND),
+    CAP_MAP_ENTRY(AUDIT_READ),
+};
+
+static_assert(CAP_LAST_CAP == CAP_AUDIT_READ, "CAP_LAST_CAP is not CAP_AUDIT_READ");
+
+bool DropBoundingSet(const CapSet& to_keep) {
+    for (size_t cap = 0; cap < to_keep.size(); ++cap) {
+        if (to_keep.test(cap)) {
+            // No need to drop this capability.
+            continue;
+        }
+        if (cap_drop_bound(cap) == -1) {
+            PLOG(ERROR) << "cap_drop_bound(" << cap << ") failed";
+            return false;
+        }
+    }
+    return true;
+}
+
+bool SetProcCaps(const CapSet& to_keep, bool add_setpcap) {
+    cap_t caps = cap_init();
+    auto deleter = [](cap_t* p) { cap_free(*p); };
+    std::unique_ptr<cap_t, decltype(deleter)> ptr_caps(&caps, deleter);
+
+    cap_clear(caps);
+    cap_value_t value[1];
+    for (size_t cap = 0; cap <= to_keep.size(); ++cap) {
+        if (to_keep.test(cap)) {
+            value[0] = cap;
+            if (cap_set_flag(caps, CAP_INHERITABLE, arraysize(value), value, CAP_SET) != 0 ||
+                cap_set_flag(caps, CAP_PERMITTED, arraysize(value), value, CAP_SET) != 0) {
+                PLOG(ERROR) << "cap_set_flag(INHERITABLE|PERMITTED, " << cap << ") failed";
+                return false;
+            }
+        }
+    }
+
+    if (add_setpcap) {
+        value[0] = CAP_SETPCAP;
+        if (cap_set_flag(caps, CAP_PERMITTED, arraysize(value), value, CAP_SET) != 0 ||
+            cap_set_flag(caps, CAP_EFFECTIVE, arraysize(value), value, CAP_SET) != 0) {
+            PLOG(ERROR) << "cap_set_flag(PERMITTED|EFFECTIVE, " << CAP_SETPCAP << ") failed";
+            return false;
+        }
+    }
+
+    if (cap_set_proc(caps) != 0) {
+        PLOG(ERROR) << "cap_set_proc(" << to_keep.to_ulong() << ") failed";
+        return false;
+    }
+    return true;
+}
+
+bool SetAmbientCaps(const CapSet& to_raise) {
+    for (size_t cap = 0; cap < to_raise.size(); ++cap) {
+        if (to_raise.test(cap)) {
+            if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, cap, 0, 0) != 0) {
+                PLOG(ERROR) << "prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, " << cap << ") failed";
+                return false;
+            }
+        }
+    }
+    return true;
+}
+
+}  // namespace anonymous
+
+int LookupCap(const std::string& cap_name) {
+    auto e = cap_map.find(cap_name);
+    if (e != cap_map.end()) {
+        return e->second;
+    } else {
+        return -1;
+    }
+}
+
+bool SetCapsForExec(const CapSet& to_keep) {
+    // Need to keep SETPCAP to drop bounding set below.
+    bool add_setpcap = true;
+    if (!SetProcCaps(to_keep, add_setpcap)) {
+        LOG(ERROR) << "failed to apply initial capset";
+        return false;
+    }
+
+    if (!DropBoundingSet(to_keep)) {
+        return false;
+    }
+
+    // If SETPCAP wasn't specifically requested, drop it now.
+    add_setpcap = false;
+    if (!SetProcCaps(to_keep, add_setpcap)) {
+        LOG(ERROR) << "failed to apply final capset";
+        return false;
+    }
+
+    // Add the capabilities to the ambient set so that they are preserved across
+    // execve(2).
+    // See http://man7.org/linux/man-pages/man7/capabilities.7.html.
+    return SetAmbientCaps(to_keep);
+}
diff --git a/init/capabilities.h b/init/capabilities.h
new file mode 100644
index 0000000..368178d
--- /dev/null
+++ b/init/capabilities.h
@@ -0,0 +1,23 @@
+// Copyright (C) 2016 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 <linux/capability.h>
+
+#include <bitset>
+#include <string>
+
+using CapSet = std::bitset<CAP_LAST_CAP + 1>;
+
+int LookupCap(const std::string& cap_name);
+bool SetCapsForExec(const CapSet& to_keep);
diff --git a/init/descriptors.cpp b/init/descriptors.cpp
new file mode 100644
index 0000000..10aae88
--- /dev/null
+++ b/init/descriptors.cpp
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2016 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 "descriptors.h"
+
+#include <ctype.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <android-base/stringprintf.h>
+#include <cutils/files.h>
+#include <cutils/sockets.h>
+
+#include "init.h"
+#include "log.h"
+#include "util.h"
+
+DescriptorInfo::DescriptorInfo(const std::string& name, const std::string& type, uid_t uid,
+                               gid_t gid, int perm, const std::string& context)
+        : name_(name), type_(type), uid_(uid), gid_(gid), perm_(perm), context_(context) {
+}
+
+DescriptorInfo::~DescriptorInfo() {
+}
+
+std::ostream& operator<<(std::ostream& os, const DescriptorInfo& info) {
+  return os << "  descriptors " << info.name_ << " " << info.type_ << " " << std::oct << info.perm_;
+}
+
+bool DescriptorInfo::operator==(const DescriptorInfo& other) const {
+  return name_ == other.name_ && type_ == other.type_ && key() == other.key();
+}
+
+void DescriptorInfo::CreateAndPublish(const std::string& globalContext) const {
+  // Create
+  const std::string& contextStr = context_.empty() ? globalContext : context_;
+  int fd = Create(contextStr);
+  if (fd < 0) return;
+
+  // Publish
+  std::string publishedName = key() + name_;
+  std::for_each(publishedName.begin(), publishedName.end(),
+                [] (char& c) { c = isalnum(c) ? c : '_'; });
+
+  std::string val = android::base::StringPrintf("%d", fd);
+  add_environment(publishedName.c_str(), val.c_str());
+
+  // make sure we don't close on exec
+  fcntl(fd, F_SETFD, 0);
+}
+
+void DescriptorInfo::Clean() const {
+}
+
+SocketInfo::SocketInfo(const std::string& name, const std::string& type, uid_t uid,
+                       gid_t gid, int perm, const std::string& context)
+        : DescriptorInfo(name, type, uid, gid, perm, context) {
+}
+
+void SocketInfo::Clean() const {
+  unlink(android::base::StringPrintf(ANDROID_SOCKET_DIR "/%s", name().c_str()).c_str());
+}
+
+int SocketInfo::Create(const std::string& context) const {
+  int flags = ((type() == "stream" ? SOCK_STREAM :
+                (type() == "dgram" ? SOCK_DGRAM :
+                 SOCK_SEQPACKET)));
+  return create_socket(name().c_str(), flags, perm(), uid(), gid(), context.c_str());
+}
+
+const std::string SocketInfo::key() const {
+  return ANDROID_SOCKET_ENV_PREFIX;
+}
+
+FileInfo::FileInfo(const std::string& name, const std::string& type, uid_t uid,
+                   gid_t gid, int perm, const std::string& context)
+        : DescriptorInfo(name, type, uid, gid, perm, context) {
+}
+
+int FileInfo::Create(const std::string& context) const {
+  int flags = ((type() == "r" ? O_RDONLY :
+                (type() == "w" ? (O_WRONLY | O_CREAT) :
+                 (O_RDWR | O_CREAT))));
+  return create_file(name().c_str(), flags, perm(), uid(), gid(), context.c_str());
+}
+
+const std::string FileInfo::key() const {
+  return ANDROID_FILE_ENV_PREFIX;
+}
diff --git a/init/descriptors.h b/init/descriptors.h
new file mode 100644
index 0000000..ff276fb
--- /dev/null
+++ b/init/descriptors.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2016 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 _INIT_DESCRIPTORS_H
+#define _INIT_DESCRIPTORS_H
+
+#include <sys/types.h>
+
+#include <string>
+
+class DescriptorInfo {
+ public:
+  DescriptorInfo(const std::string& name, const std::string& type, uid_t uid,
+                 gid_t gid, int perm, const std::string& context);
+  virtual ~DescriptorInfo();
+
+  friend std::ostream& operator<<(std::ostream& os, const class DescriptorInfo& info);
+  bool operator==(const DescriptorInfo& other) const;
+
+  void CreateAndPublish(const std::string& globalContext) const;
+  virtual void Clean() const;
+
+ protected:
+  const std::string& name() const { return name_; }
+  const std::string& type() const { return type_; }
+  uid_t uid() const { return uid_; }
+  gid_t gid() const { return gid_; }
+  int perm() const { return perm_; }
+  const std::string& context() const { return context_; }
+
+ private:
+  std::string name_;
+  std::string type_;
+  uid_t uid_;
+  gid_t gid_;
+  int perm_;
+  std::string context_;
+
+  virtual int Create(const std::string& globalContext) const = 0;
+  virtual const std::string key() const = 0;
+};
+
+std::ostream& operator<<(std::ostream& os, const DescriptorInfo& info);
+
+class SocketInfo : public DescriptorInfo {
+ public:
+  SocketInfo(const std::string& name, const std::string& type, uid_t uid,
+             gid_t gid, int perm, const std::string& context);
+  void Clean() const override;
+ private:
+  virtual int Create(const std::string& context) const override;
+  virtual const std::string key() const override;
+};
+
+class FileInfo : public DescriptorInfo {
+ public:
+  FileInfo(const std::string& name, const std::string& type, uid_t uid,
+           gid_t gid, int perm, const std::string& context);
+ private:
+  virtual int Create(const std::string& context) const override;
+  virtual const std::string key() const override;
+};
+
+#endif
diff --git a/init/readme.txt b/init/readme.txt
index 77e5de2..5173ca6 100644
--- a/init/readme.txt
+++ b/init/readme.txt
@@ -141,33 +141,49 @@
   Set the environment variable <name> to <value> in the launched process.
 
 socket <name> <type> <perm> [ <user> [ <group> [ <seclabel> ] ] ]
-  Create a unix domain socket named /dev/socket/<name> and pass
-  its fd to the launched process.  <type> must be "dgram", "stream" or "seqpacket".
-  User and group default to 0.
-  'seclabel' is the SELinux security context for the socket.
-  It defaults to the service security context, as specified by seclabel or
-  computed based on the service executable file security context.
+  Create a unix domain socket named /dev/socket/<name> and pass its fd to the
+  launched process.  <type> must be "dgram", "stream" or "seqpacket".  User and
+  group default to 0.  'seclabel' is the SELinux security context for the
+  socket.  It defaults to the service security context, as specified by
+  seclabel or computed based on the service executable file security context.
+  For native executables see libcutils android_get_control_socket().
+
+file <path> <type> <perm> [ <user> [ <group> [ <seclabel> ] ] ]
+  Open/Create a file path and pass its fd to the launched process.  <type> must
+  be "r", "w" or "rw".  User and group default to 0.  'seclabel' is the SELinux
+  security context for the file if it must be created.  It defaults to the
+  service security context, as specified by seclabel or computed based on the
+  service executable file security context.  For native executables see
+  libcutils android_get_control_file().
 
 user <username>
-  Change to username before exec'ing this service.
+  Change to 'username' before exec'ing this service.
   Currently defaults to root.  (??? probably should default to nobody)
   As of Android M, processes should use this option even if they
-  require linux capabilities.  Previously, to acquire linux
+  require Linux capabilities.  Previously, to acquire Linux
   capabilities, a process would need to run as root, request the
   capabilities, then drop to its desired uid.  There is a new
   mechanism through fs_config that allows device manufacturers to add
-  linux capabilities to specific binaries on a file system that should
+  Linux capabilities to specific binaries on a file system that should
   be used instead. This mechanism is described on
   http://source.android.com/devices/tech/config/filesystem.html.  When
   using this new mechanism, processes can use the user option to
   select their desired uid without ever running as root.
+  As of Android O, processes can also request capabilities directly in their .rc
+  files. See the "capabilities" option below.
 
 group <groupname> [ <groupname> ]*
-  Change to groupname before exec'ing this service.  Additional
+  Change to 'groupname' before exec'ing this service.  Additional
   groupnames beyond the (required) first one are used to set the
   supplemental groups of the process (via setgroups()).
   Currently defaults to root.  (??? probably should default to nobody)
 
+capabilities <capability> [ <capability> ]*
+  Set capabilities when exec'ing this service. 'capability' should be a Linux
+  capability without the "CAP_" prefix, like "NET_ADMIN" or "SETPCAP". See
+  http://man7.org/linux/man-pages/man7/capabilities.7.html for a list of Linux
+  capabilities.
+
 seclabel <seclabel>
   Change to 'seclabel' before exec'ing this service.
   Primarily for use by services run from the rootfs, e.g. ueventd, adbd.
diff --git a/init/service.cpp b/init/service.cpp
index 92f1615..9fa11b8 100644
--- a/init/service.cpp
+++ b/init/service.cpp
@@ -17,6 +17,7 @@
 #include "service.h"
 
 #include <fcntl.h>
+#include <linux/securebits.h>
 #include <sched.h>
 #include <sys/mount.h>
 #include <sys/prctl.h>
@@ -35,7 +36,6 @@
 #include <android-base/stringprintf.h>
 #include <android-base/strings.h>
 #include <cutils/android_reboot.h>
-#include <cutils/sockets.h>
 #include <system/thread_defs.h>
 
 #include <processgroup/processgroup.h>
@@ -144,14 +144,6 @@
     strs->push_back(nullptr);
 }
 
-SocketInfo::SocketInfo() : uid(0), gid(0), perm(0) {
-}
-
-SocketInfo::SocketInfo(const std::string& name, const std::string& type, uid_t uid,
-                       gid_t gid, int perm, const std::string& socketcon)
-    : name(name), type(type), uid(uid), gid(gid), perm(perm), socketcon(socketcon) {
-}
-
 ServiceEnvironmentInfo::ServiceEnvironmentInfo() {
 }
 
@@ -171,14 +163,16 @@
 
 Service::Service(const std::string& name, const std::string& classname,
                  unsigned flags, uid_t uid, gid_t gid,
-                 const std::vector<gid_t>& supp_gids, unsigned namespace_flags,
+                 const std::vector<gid_t>& supp_gids,
+                 const CapSet& capabilities, unsigned namespace_flags,
                  const std::string& seclabel,
                  const std::vector<std::string>& args)
     : name_(name), classname_(classname), flags_(flags), pid_(0),
       time_started_(0), time_crashed_(0), nr_crashed_(0), uid_(uid), gid_(gid),
-      supp_gids_(supp_gids), namespace_flags_(namespace_flags),
-      seclabel_(seclabel), ioprio_class_(IoSchedClass_NONE), ioprio_pri_(0),
-      priority_(0), oom_score_adjust_(-1000), args_(args) {
+      supp_gids_(supp_gids), capabilities_(capabilities),
+      namespace_flags_(namespace_flags), seclabel_(seclabel),
+      ioprio_class_(IoSchedClass_NONE), ioprio_pri_(0), priority_(0),
+      oom_score_adjust_(-1000), args_(args) {
     onrestart_.InitSingleTrigger("onrestart");
 }
 
@@ -210,21 +204,14 @@
     }
 }
 
-void Service::CreateSockets(const std::string& context) {
-    for (const auto& si : sockets_) {
-        int socket_type = ((si.type == "stream" ? SOCK_STREAM :
-                            (si.type == "dgram" ? SOCK_DGRAM :
-                             SOCK_SEQPACKET)));
-        const char* socketcon = !si.socketcon.empty() ? si.socketcon.c_str() : context.c_str();
-
-        int s = create_socket(si.name.c_str(), socket_type, si.perm, si.uid, si.gid, socketcon);
-        if (s >= 0) {
-            PublishSocket(si.name, s);
+void Service::SetProcessAttributes() {
+    // Keep capabilites on uid change.
+    if (capabilities_.any() && uid_) {
+        if (prctl(PR_SET_SECUREBITS, SECBIT_KEEP_CAPS | SECBIT_KEEP_CAPS_LOCKED) != 0) {
+            PLOG(FATAL) << "prtcl(PR_SET_KEEPCAPS) failed for " << name_;
         }
     }
-}
 
-void Service::SetProcessAttributes() {
     // TODO: work out why this fails for `console` then upgrade to FATAL.
     if (setpgid(0, getpid()) == -1) PLOG(ERROR) << "setpgid failed for " << name_;
 
@@ -251,6 +238,11 @@
             PLOG(FATAL) << "setpriority failed for " << name_;
         }
     }
+    if (capabilities_.any()) {
+        if (!SetCapsForExec(capabilities_)) {
+            LOG(FATAL) << "cannot set capabilities for " << name_;
+        }
+    }
 }
 
 bool Service::Reap() {
@@ -258,11 +250,9 @@
         KillProcessGroup(SIGKILL);
     }
 
-    // Remove any sockets we may have created.
-    for (const auto& si : sockets_) {
-        std::string tmp = StringPrintf(ANDROID_SOCKET_DIR "/%s", si.name.c_str());
-        unlink(tmp.c_str());
-    }
+    // Remove any descriptor resources we may have created.
+    std::for_each(descriptors_.begin(), descriptors_.end(),
+                  std::bind(&DescriptorInfo::Clean, std::placeholders::_1));
 
     if (flags_ & SVC_EXEC) {
         LOG(INFO) << "SVC_EXEC pid " << pid_ << " finished...";
@@ -315,9 +305,23 @@
     LOG(INFO) << "service " << name_;
     LOG(INFO) << "  class '" << classname_ << "'";
     LOG(INFO) << "  exec "<< android::base::Join(args_, " ");
-    for (const auto& si : sockets_) {
-        LOG(INFO) << "  socket " << si.name << " " << si.type << " " << std::oct << si.perm;
+    std::for_each(descriptors_.begin(), descriptors_.end(),
+                  [] (const auto& info) { LOG(INFO) << *info; });
+}
+
+bool Service::ParseCapabilities(const std::vector<std::string>& args, std::string* err) {
+    capabilities_ = 0;
+
+    for (size_t i = 1; i < args.size(); i++) {
+        const std::string& arg = args[i];
+        int cap = LookupCap(arg);
+        if (cap == -1) {
+            *err = StringPrintf("invalid capability '%s'", arg.c_str());
+            return false;
+        }
+        capabilities_[cap] = true;
     }
+    return true;
 }
 
 bool Service::ParseClass(const std::vector<std::string>& args, std::string* err) {
@@ -439,20 +443,48 @@
     return true;
 }
 
-/* name type perm [ uid gid context ] */
+template <typename T>
+bool Service::AddDescriptor(const std::vector<std::string>& args, std::string* err) {
+    int perm = args.size() > 3 ? std::strtoul(args[3].c_str(), 0, 8) : -1;
+    uid_t uid = args.size() > 4 ? decode_uid(args[4].c_str()) : 0;
+    gid_t gid = args.size() > 5 ? decode_uid(args[5].c_str()) : 0;
+    std::string context = args.size() > 6 ? args[6] : "";
+
+    auto descriptor = std::make_unique<T>(args[1], args[2], uid, gid, perm, context);
+
+    auto old =
+        std::find_if(descriptors_.begin(), descriptors_.end(),
+                     [&descriptor] (const auto& other) { return descriptor.get() == other.get(); });
+
+    if (old != descriptors_.end()) {
+        *err = "duplicate descriptor " + args[1] + " " + args[2];
+        return false;
+    }
+
+    descriptors_.emplace_back(std::move(descriptor));
+    return true;
+}
+
+// name type perm [ uid gid context ]
 bool Service::ParseSocket(const std::vector<std::string>& args, std::string* err) {
     if (args[2] != "dgram" && args[2] != "stream" && args[2] != "seqpacket") {
         *err = "socket type must be 'dgram', 'stream' or 'seqpacket'";
         return false;
     }
+    return AddDescriptor<SocketInfo>(args, err);
+}
 
-    int perm = std::strtoul(args[3].c_str(), 0, 8);
-    uid_t uid = args.size() > 4 ? decode_uid(args[4].c_str()) : 0;
-    gid_t gid = args.size() > 5 ? decode_uid(args[5].c_str()) : 0;
-    std::string socketcon = args.size() > 6 ? args[6] : "";
-
-    sockets_.emplace_back(args[1], args[2], uid, gid, perm, socketcon);
-    return true;
+// name type perm [ uid gid context ]
+bool Service::ParseFile(const std::vector<std::string>& args, std::string* err) {
+    if (args[2] != "r" && args[2] != "w" && args[2] != "rw") {
+        *err = "file type must be 'r', 'w' or 'rw'";
+        return false;
+    }
+    if ((args[1][0] != '/') || (args[1].find("../") != std::string::npos)) {
+        *err = "file name must not be relative";
+        return false;
+    }
+    return AddDescriptor<FileInfo>(args, err);
 }
 
 bool Service::ParseUser(const std::vector<std::string>& args, std::string* err) {
@@ -476,6 +508,8 @@
 Service::OptionParserMap::Map& Service::OptionParserMap::map() const {
     constexpr std::size_t kMax = std::numeric_limits<std::size_t>::max();
     static const Map option_parsers = {
+        {"capabilities",
+                        {1,     kMax, &Service::ParseCapabilities}},
         {"class",       {1,     1,    &Service::ParseClass}},
         {"console",     {0,     1,    &Service::ParseConsole}},
         {"critical",    {0,     0,    &Service::ParseCritical}},
@@ -492,6 +526,7 @@
         {"seclabel",    {1,     1,    &Service::ParseSeclabel}},
         {"setenv",      {2,     2,    &Service::ParseSetenv}},
         {"socket",      {3,     6,    &Service::ParseSocket}},
+        {"file",        {2,     6,    &Service::ParseFile}},
         {"user",        {1,     1,    &Service::ParseUser}},
         {"writepid",    {1,     kMax, &Service::ParseWritepid}},
     };
@@ -581,7 +616,8 @@
             add_environment(ei.name.c_str(), ei.value.c_str());
         }
 
-        CreateSockets(scon);
+        std::for_each(descriptors_.begin(), descriptors_.end(),
+                      std::bind(&DescriptorInfo::CreateAndPublish, std::placeholders::_1, scon));
 
         std::string pid_str = StringPrintf("%d", getpid());
         for (const auto& file : writepid_files_) {
@@ -755,15 +791,6 @@
     close(fd);
 }
 
-void Service::PublishSocket(const std::string& name, int fd) const {
-    std::string key = StringPrintf(ANDROID_SOCKET_ENV_PREFIX "%s", name.c_str());
-    std::string val = StringPrintf("%d", fd);
-    add_environment(key.c_str(), val.c_str());
-
-    /* make sure we don't close-on-exec */
-    fcntl(fd, F_SETFD, 0);
-}
-
 int ServiceManager::exec_count_ = 0;
 
 ServiceManager::ServiceManager() {
@@ -807,6 +834,7 @@
     exec_count_++;
     std::string name = StringPrintf("exec %d (%s)", exec_count_, str_args[0].c_str());
     unsigned flags = SVC_EXEC | SVC_ONESHOT;
+    CapSet no_capabilities;
     unsigned namespace_flags = 0;
 
     std::string seclabel = "";
@@ -827,9 +855,9 @@
         }
     }
 
-    std::unique_ptr<Service> svc_p(new Service(name, "default", flags, uid, gid,
-                                               supp_gids, namespace_flags,
-                                               seclabel, str_args));
+    std::unique_ptr<Service> svc_p(new Service(name, "default", flags, uid, gid, supp_gids,
+                                               no_capabilities, namespace_flags, seclabel,
+                                               str_args));
     if (!svc_p) {
         LOG(ERROR) << "Couldn't allocate service for exec of '" << str_args[0] << "'";
         return nullptr;
diff --git a/init/service.h b/init/service.h
index 4a3412c..d9e8f57 100644
--- a/init/service.h
+++ b/init/service.h
@@ -26,6 +26,8 @@
 #include <vector>
 
 #include "action.h"
+#include "capabilities.h"
+#include "descriptors.h"
 #include "init_parser.h"
 #include "keyword_map.h"
 
@@ -47,18 +49,6 @@
 class Action;
 class ServiceManager;
 
-struct SocketInfo {
-    SocketInfo();
-    SocketInfo(const std::string& name, const std::string& type, uid_t uid,
-                       gid_t gid, int perm, const std::string& socketcon);
-    std::string name;
-    std::string type;
-    uid_t uid;
-    gid_t gid;
-    int perm;
-    std::string socketcon;
-};
-
 struct ServiceEnvironmentInfo {
     ServiceEnvironmentInfo();
     ServiceEnvironmentInfo(const std::string& name, const std::string& value);
@@ -73,8 +63,9 @@
 
     Service(const std::string& name, const std::string& classname,
             unsigned flags, uid_t uid, gid_t gid,
-            const std::vector<gid_t>& supp_gids, unsigned namespace_flags,
-            const std::string& seclabel, const std::vector<std::string>& args);
+            const std::vector<gid_t>& supp_gids, const CapSet& capabilities,
+            unsigned namespace_flags, const std::string& seclabel,
+            const std::vector<std::string>& args);
 
     bool ParseLine(const std::vector<std::string>& args, std::string* err);
     bool Start();
@@ -111,11 +102,10 @@
     void StopOrReset(int how);
     void ZapStdio() const;
     void OpenConsole() const;
-    void PublishSocket(const std::string& name, int fd) const;
     void KillProcessGroup(int signal);
-    void CreateSockets(const std::string& scon);
     void SetProcessAttributes();
 
+    bool ParseCapabilities(const std::vector<std::string>& args, std::string *err);
     bool ParseClass(const std::vector<std::string>& args, std::string* err);
     bool ParseConsole(const std::vector<std::string>& args, std::string* err);
     bool ParseCritical(const std::vector<std::string>& args, std::string* err);
@@ -131,9 +121,13 @@
     bool ParseSeclabel(const std::vector<std::string>& args, std::string* err);
     bool ParseSetenv(const std::vector<std::string>& args, std::string* err);
     bool ParseSocket(const std::vector<std::string>& args, std::string* err);
+    bool ParseFile(const std::vector<std::string>& args, std::string* err);
     bool ParseUser(const std::vector<std::string>& args, std::string* err);
     bool ParseWritepid(const std::vector<std::string>& args, std::string* err);
 
+    template <typename T>
+    bool AddDescriptor(const std::vector<std::string>& args, std::string* err);
+
     std::string name_;
     std::string classname_;
     std::string console_;
@@ -147,11 +141,12 @@
     uid_t uid_;
     gid_t gid_;
     std::vector<gid_t> supp_gids_;
+    CapSet capabilities_;
     unsigned namespace_flags_;
 
     std::string seclabel_;
 
-    std::vector<SocketInfo> sockets_;
+    std::vector<std::unique_ptr<DescriptorInfo>> descriptors_;
     std::vector<ServiceEnvironmentInfo> envvars_;
 
     Action onrestart_;  // Commands to execute on restart.
diff --git a/init/util.cpp b/init/util.cpp
index 660a66f..b280244 100644
--- a/init/util.cpp
+++ b/init/util.cpp
@@ -14,32 +14,32 @@
  * limitations under the License.
  */
 
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <ftw.h>
+#include <pwd.h>
 #include <stdarg.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
-#include <fcntl.h>
-#include <ctype.h>
-#include <errno.h>
 #include <time.h>
-#include <ftw.h>
-#include <pwd.h>
+#include <unistd.h>
 
-#include <selinux/label.h>
 #include <selinux/android.h>
+#include <selinux/label.h>
 
+#include <sys/socket.h>
 #include <sys/stat.h>
 #include <sys/types.h>
-#include <sys/socket.h>
 #include <sys/un.h>
 
 #include <android-base/file.h>
 #include <android-base/logging.h>
+#include <android-base/stringprintf.h>
 #include <android-base/strings.h>
-
 /* for ANDROID_SOCKET_* */
 #include <cutils/sockets.h>
-#include <android-base/stringprintf.h>
 
 #include "init.h"
 #include "log.h"
@@ -164,6 +164,76 @@
     return -1;
 }
 
+/*
+ * create_file - opens and creates a file as dictated in init.rc.
+ * This file is inherited by the daemon. We communicate the file
+ * descriptor's value via the environment variable ANDROID_FILE_<basename>
+ */
+int create_file(const char *path, int flags, mode_t perm, uid_t uid,
+                  gid_t gid, const char *filecon)
+{
+    char *secontext = NULL;
+    int ret;
+
+    if (filecon) {
+        if (setsockcreatecon(filecon) == -1) {
+            PLOG(ERROR) << "setsockcreatecon(\"" << filecon << "\") failed";
+            return -1;
+        }
+    } else if (sehandle) {
+        ret = selabel_lookup(sehandle, &secontext, path, perm);
+        if (ret != -1) {
+            ret = setfscreatecon(secontext);
+            if (ret == -1) {
+                freecon(secontext);
+                PLOG(ERROR) << "setfscreatecon(\"" << secontext << "\") failed";
+                return -1;
+            }
+        }
+    }
+
+    int fd = TEMP_FAILURE_RETRY(open(path, flags | O_NDELAY, perm));
+
+    if (filecon) {
+        setsockcreatecon(NULL);
+        lsetfilecon(path, filecon);
+    } else {
+        setfscreatecon(NULL);
+        freecon(secontext);
+    }
+
+    if (fd == -1) {
+        PLOG(ERROR) << "Failed to open/create file '" << path << "'";
+        goto out_close;
+    }
+
+    if (!(flags & O_NDELAY)) fcntl(fd, F_SETFD, flags);
+
+    ret = lchown(path, uid, gid);
+    if (ret) {
+        PLOG(ERROR) << "Failed to lchown file '" << path << "'";
+        goto out_close;
+    }
+    if (perm != static_cast<mode_t>(-1)) {
+        ret = fchmodat(AT_FDCWD, path, perm, AT_SYMLINK_NOFOLLOW);
+        if (ret) {
+            PLOG(ERROR) << "Failed to fchmodat file '" << path << "'";
+            goto out_close;
+        }
+    }
+
+    LOG(INFO) << "Created file '" << path << "'"
+              << ", mode " << std::oct << perm << std::dec
+              << ", user " << uid
+              << ", group " << gid;
+
+    return fd;
+
+out_close:
+    if (fd >= 0) close(fd);
+    return -1;
+}
+
 bool read_file(const char* path, std::string* content) {
     content->clear();
 
diff --git a/init/util.h b/init/util.h
index b83b9a0..b7531cc 100644
--- a/init/util.h
+++ b/init/util.h
@@ -27,6 +27,8 @@
 
 int create_socket(const char *name, int type, mode_t perm,
                   uid_t uid, gid_t gid, const char *socketcon);
+int create_file(const char *path, int mode, mode_t perm,
+                uid_t uid, gid_t gid, const char *filecon);
 
 bool read_file(const char* path, std::string* content);
 int write_file(const char* path, const char* content);
diff --git a/init/util_test.cpp b/init/util_test.cpp
index 228954b..6ecbf90 100644
--- a/init/util_test.cpp
+++ b/init/util_test.cpp
@@ -17,7 +17,15 @@
 #include "util.h"
 
 #include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <cutils/files.h>
 #include <gtest/gtest.h>
+#include <selinux/android.h>
 
 TEST(util, read_file_ENOENT) {
   std::string s("hello");
@@ -41,3 +49,51 @@
   EXPECT_EQ(UINT_MAX, decode_uid("toot"));
   EXPECT_EQ(123U, decode_uid("123"));
 }
+
+struct selabel_handle *sehandle;
+
+TEST(util, create_file) {
+  if (!sehandle) sehandle = selinux_android_file_context_handle();
+
+  static const char path[] = "/data/local/tmp/util.create_file.test";
+  static const char key[] = ANDROID_FILE_ENV_PREFIX "_data_local_tmp_util_create_file_test";
+  EXPECT_EQ(unsetenv(key), 0);
+  unlink(path);
+
+  int fd;
+  uid_t uid = decode_uid("logd");
+  gid_t gid = decode_uid("system");
+  mode_t perms = S_IRWXU | S_IWGRP | S_IRGRP | S_IROTH;
+  static const char context[] = "u:object_r:misc_logd_file:s0";
+  EXPECT_GE(fd = create_file(path, O_RDWR | O_CREAT, perms, uid, gid, context), 0);
+  if (fd < 0) return;
+  static const char hello[] = "hello world\n";
+  static const ssize_t len = strlen(hello);
+  EXPECT_EQ(write(fd, hello, len), len);
+  char buffer[sizeof(hello)];
+  memset(buffer, 0, sizeof(buffer));
+  EXPECT_GE(lseek(fd, 0, SEEK_SET), 0);
+  EXPECT_EQ(read(fd, buffer, sizeof(buffer)), len);
+  EXPECT_EQ(strcmp(hello, buffer), 0);
+  char val[32];
+  snprintf(val, sizeof(val), "%d", fd);
+  EXPECT_EQ(android_get_control_file(path), -1);
+  setenv(key, val, true);
+  EXPECT_EQ(android_get_control_file(path), fd);
+  close(fd);
+  EXPECT_EQ(android_get_control_file(path), -1);
+  EXPECT_EQ(unsetenv(key), 0);
+  struct stat st;
+  EXPECT_EQ(stat(path, &st), 0);
+  EXPECT_EQ(st.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO), perms);
+  EXPECT_EQ(st.st_uid, uid);
+  EXPECT_EQ(st.st_gid, gid);
+  security_context_t con;
+  EXPECT_GE(getfilecon(path, &con), 0);
+  EXPECT_NE(con, static_cast<security_context_t>(NULL));
+  if (con) {
+    EXPECT_EQ(context, std::string(con));
+  }
+  freecon(con);
+  EXPECT_EQ(unlink(path), 0);
+}
diff --git a/libcutils/Android.bp b/libcutils/Android.bp
index 943926b..f7b497d 100644
--- a/libcutils/Android.bp
+++ b/libcutils/Android.bp
@@ -34,6 +34,7 @@
     host_supported: true,
     srcs: [
         "config_utils.c",
+        "files.cpp",
         "fs_config.c",
         "canned_fs_config.c",
         "hashmap.c",
diff --git a/libcutils/files.cpp b/libcutils/files.cpp
new file mode 100644
index 0000000..bf15b42
--- /dev/null
+++ b/libcutils/files.cpp
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+// This file contains files implementation that can be shared between
+// platforms as long as the correct headers are included.
+#define _GNU_SOURCE 1 // for asprintf
+
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <cutils/files.h>
+
+#ifndef TEMP_FAILURE_RETRY // _WIN32 does not define
+#define TEMP_FAILURE_RETRY(exp) (exp)
+#endif
+
+int android_get_control_file(const char* path) {
+    if (!path) return -1;
+
+    char *key = NULL;
+    if (asprintf(&key, ANDROID_FILE_ENV_PREFIX "%s", path) < 0) return -1;
+    if (!key) return -1;
+
+    char *cp = key;
+    while (*cp) {
+        if (!isalnum(*cp)) *cp = '_';
+        ++cp;
+    }
+
+    const char* val = getenv(key);
+    free(key);
+    if (!val) return -1;
+
+    errno = 0;
+    long fd = strtol(val, NULL, 10);
+    if (errno) return -1;
+
+    // validity checking
+    if ((fd < 0) || (fd > INT_MAX)) return -1;
+#if defined(_SC_OPEN_MAX)
+    if (fd >= sysconf(_SC_OPEN_MAX)) return -1;
+#elif defined(OPEN_MAX)
+    if (fd >= OPEN_MAX) return -1;
+#elif defined(_POSIX_OPEN_MAX)
+    if (fd >= _POSIX_OPEN_MAX) return -1;
+#endif
+
+#if defined(F_GETFD)
+    if (TEMP_FAILURE_RETRY(fcntl(fd, F_GETFD)) < 0) return -1;
+#elif defined(F_GETFL)
+    if (TEMP_FAILURE_RETRY(fcntl(fd, F_GETFL)) < 0) return -1;
+#else
+    struct stat s;
+    if (TEMP_FAILURE_RETRY(fstat(fd, &s)) < 0) return -1;
+#endif
+
+#if defined(__linux__)
+    char *proc = NULL;
+    if (asprintf(&proc, "/proc/self/fd/%ld", fd) < 0) return -1;
+    if (!proc) return -1;
+
+    size_t len = strlen(path);
+    char *buf = static_cast<char *>(calloc(1, len + 2));
+    if (!buf) {
+        free(proc);
+        return -1;
+    }
+    ssize_t ret = TEMP_FAILURE_RETRY(readlink(proc, buf, len + 1));
+    free(proc);
+    int cmp = (len != static_cast<size_t>(ret)) || strcmp(buf, path);
+    free(buf);
+    if (ret < 0) return -1;
+    if (cmp != 0) return -1;
+#endif
+
+    // It is what we think it is
+    return static_cast<int>(fd);
+}
diff --git a/libcutils/fs_config.c b/libcutils/fs_config.c
index 293e78a..99f97d1 100644
--- a/libcutils/fs_config.c
+++ b/libcutils/fs_config.c
@@ -140,18 +140,39 @@
     { 06755, AID_ROOT,      AID_ROOT,      0, "system/xbin/procmem" },
 
     /* the following files have enhanced capabilities and ARE included in user builds. */
-    { 00750, AID_ROOT,      AID_SHELL,     CAP_MASK_LONG(CAP_SETUID) | CAP_MASK_LONG(CAP_SETGID), "system/bin/run-as" },
-    { 00700, AID_SYSTEM,    AID_SHELL,     CAP_MASK_LONG(CAP_BLOCK_SUSPEND), "system/bin/inputflinger" },
+    { 00550, AID_LOGD,      AID_LOGD,      CAP_MASK_LONG(CAP_SYSLOG) |
+                                           CAP_MASK_LONG(CAP_AUDIT_CONTROL) |
+                                           CAP_MASK_LONG(CAP_SETGID),
+                                              "system/bin/logd" },
+    { 00750, AID_ROOT,      AID_SHELL,     CAP_MASK_LONG(CAP_SETUID) |
+                                           CAP_MASK_LONG(CAP_SETGID),
+                                              "system/bin/run-as" },
+    { 00700, AID_SYSTEM,    AID_SHELL,     CAP_MASK_LONG(CAP_BLOCK_SUSPEND),
+                                              "system/bin/inputflinger" },
 
     /* Support FIFO scheduling mode in SurfaceFlinger. */
-    { 00755, AID_SYSTEM,    AID_GRAPHICS,     CAP_MASK_LONG(CAP_SYS_NICE), "system/bin/surfaceflinger" },
+    { 00755, AID_SYSTEM,    AID_GRAPHICS,  CAP_MASK_LONG(CAP_SYS_NICE),
+                                              "system/bin/surfaceflinger" },
 
     /* Support hostapd administering a network interface. */
-    { 00755, AID_WIFI,      AID_WIFI,     CAP_MASK_LONG(CAP_NET_ADMIN) |
-                                          CAP_MASK_LONG(CAP_NET_RAW),    "system/bin/hostapd" },
+    { 00755, AID_WIFI,      AID_WIFI,      CAP_MASK_LONG(CAP_NET_ADMIN) |
+                                           CAP_MASK_LONG(CAP_NET_RAW),
+                                              "system/bin/hostapd" },
 
     /* Support wifi_hal_legacy administering a network interface. */
-    { 00755, AID_WIFI,      AID_WIFI,     CAP_MASK_LONG(CAP_NET_ADMIN) | CAP_MASK_LONG(CAP_NET_RAW),    "system/bin/hw/android.hardware.wifi@1.0-service" },
+    { 00755, AID_WIFI,      AID_WIFI,      CAP_MASK_LONG(CAP_NET_ADMIN) |
+                                           CAP_MASK_LONG(CAP_NET_RAW),
+                                              "system/bin/hw/android.hardware.wifi@1.0-service" },
+
+    /* A non-privileged zygote that spawns isolated processes for web rendering. */
+    { 0750,  AID_ROOT,      AID_ROOT,      CAP_MASK_LONG(CAP_SETUID) |
+                                           CAP_MASK_LONG(CAP_SETGID) |
+                                           CAP_MASK_LONG(CAP_SETPCAP),
+                                              "system/bin/webview_zygote32" },
+    { 0750,  AID_ROOT,      AID_ROOT,      CAP_MASK_LONG(CAP_SETUID) |
+                                           CAP_MASK_LONG(CAP_SETGID) |
+                                           CAP_MASK_LONG(CAP_SETPCAP),
+                                              "system/bin/webview_zygote64" },
 
     { 00750, AID_ROOT,      AID_ROOT,      0, "system/bin/uncrypt" },
     { 00750, AID_ROOT,      AID_ROOT,      0, "system/bin/install-recovery.sh" },
diff --git a/libcutils/klog.cpp b/libcutils/klog.cpp
index 061af1b..9d823cf 100644
--- a/libcutils/klog.cpp
+++ b/libcutils/klog.cpp
@@ -24,6 +24,7 @@
 #include <sys/types.h>
 #include <unistd.h>
 
+#include <cutils/files.h>
 #include <cutils/klog.h>
 
 static int klog_level = KLOG_DEFAULT_LEVEL;
@@ -37,7 +38,11 @@
 }
 
 static int __open_klog(void) {
-    return TEMP_FAILURE_RETRY(open("/dev/kmsg", O_WRONLY | O_CLOEXEC));
+    static const char kmsg_device[] = "/dev/kmsg";
+
+    int ret = android_get_control_file(kmsg_device);
+    if (ret >= 0) return ret;
+    return TEMP_FAILURE_RETRY(open(kmsg_device, O_WRONLY | O_CLOEXEC));
 }
 
 #define LOG_BUF_MAX 512
diff --git a/libcutils/sockets.cpp b/libcutils/sockets.cpp
index bba63ac..63761a2 100644
--- a/libcutils/sockets.cpp
+++ b/libcutils/sockets.cpp
@@ -28,11 +28,31 @@
 
 // This file contains socket implementation that can be shared between
 // platforms as long as the correct headers are included.
+#define _GNU_SOURCE 1 // For asprintf
+
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#if !defined(_WIN32)
+#include <netinet/in.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#if !defined(_WIN32)
+#include <sys/un.h>
+#endif
+#include <unistd.h>
+
+#include <string>
 
 #include <cutils/sockets.h>
 
-#if !defined(_WIN32)
-#include <netinet/in.h>
+#ifndef TEMP_FAILURE_RETRY // _WIN32 does not define
+#define TEMP_FAILURE_RETRY(exp) (exp)
 #endif
 
 int socket_get_local_port(cutils_socket_t sock) {
@@ -47,22 +67,56 @@
 }
 
 int android_get_control_socket(const char* name) {
-    char key[64];
-    snprintf(key, sizeof(key), ANDROID_SOCKET_ENV_PREFIX "%s", name);
+    char *key = NULL;
+    if (asprintf(&key, ANDROID_SOCKET_ENV_PREFIX "%s", name) < 0) return -1;
+    if (!key) return -1;
+
+    char *cp = key;
+    while (*cp) {
+        if (!isalnum(*cp)) *cp = '_';
+        ++cp;
+    }
 
     const char* val = getenv(key);
-    if (!val) {
-        return -1;
-    }
+    free(key);
+    if (!val) return -1;
 
     errno = 0;
-    long ret = strtol(val, NULL, 10);
-    if (errno) {
-        return -1;
-    }
-    if (ret < 0 || ret > INT_MAX) {
-        return -1;
-    }
+    long fd = strtol(val, NULL, 10);
+    if (errno) return -1;
 
-    return static_cast<int>(ret);
+    // validity checking
+    if ((fd < 0) || (fd > INT_MAX)) return -1;
+#if defined(_SC_OPEN_MAX)
+    if (fd >= sysconf(_SC_OPEN_MAX)) return -1;
+#elif defined(OPEN_MAX)
+    if (fd >= OPEN_MAX) return -1;
+#elif defined(_POSIX_OPEN_MAX)
+    if (fd >= _POSIX_OPEN_MAX) return -1;
+#endif
+
+#if defined(F_GETFD)
+    if (TEMP_FAILURE_RETRY(fcntl(fd, F_GETFD)) < 0) return -1;
+#elif defined(F_GETFL)
+    if (TEMP_FAILURE_RETRY(fcntl(fd, F_GETFL)) < 0) return -1;
+#else
+    struct stat s;
+    if (TEMP_FAILURE_RETRY(fstat(fd, &s)) < 0) return -1;
+#endif
+
+#if !defined(_WIN32)
+    struct sockaddr_un addr;
+    socklen_t addrlen = sizeof(addr);
+    int ret = TEMP_FAILURE_RETRY(getsockname(fd, (struct sockaddr *)&addr, &addrlen));
+    if (ret < 0) return -1;
+    char *path = NULL;
+    if (asprintf(&path, ANDROID_SOCKET_DIR"/%s", name) < 0) return -1;
+    if (!path) return -1;
+    int cmp = strcmp(addr.sun_path, path);
+    free(path);
+    if (cmp != 0) return -1;
+#endif
+
+    // It is what we think it is
+    return static_cast<int>(fd);
 }
diff --git a/libcutils/tests/Android.bp b/libcutils/tests/Android.bp
index 06d0e28..bd35412 100644
--- a/libcutils/tests/Android.bp
+++ b/libcutils/tests/Android.bp
@@ -14,7 +14,7 @@
 
 cc_defaults {
     name: "libcutils_test_default",
-    srcs: ["sockets_test.cpp"],
+    srcs: ["sockets_test.cpp", "files_test.cpp"],
 
     target: {
         android: {
diff --git a/libcutils/tests/files_test.cpp b/libcutils/tests/files_test.cpp
new file mode 100644
index 0000000..1a7d673
--- /dev/null
+++ b/libcutils/tests/files_test.cpp
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2016 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 <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <time.h>
+
+#include <cutils/files.h>
+#include <gtest/gtest.h>
+
+TEST(FilesTest, android_get_control_file) {
+    static const char key[] = ANDROID_FILE_ENV_PREFIX "_dev_kmsg";
+    static const char name[] = "/dev/kmsg";
+
+    EXPECT_EQ(unsetenv(key), 0);
+    EXPECT_EQ(android_get_control_file(name), -1);
+
+    int fd;
+    ASSERT_GE(fd = open(name, O_RDONLY | O_CLOEXEC), 0);
+    EXPECT_EQ(android_get_control_file(name), -1);
+
+    char val[32];
+    snprintf(val, sizeof(val), "%d", fd);
+    EXPECT_EQ(setenv(key, val, true), 0);
+
+    EXPECT_EQ(android_get_control_file(name), fd);
+    close(fd);
+    EXPECT_EQ(android_get_control_file(name), -1);
+    EXPECT_EQ(unsetenv(key), 0);
+    EXPECT_EQ(android_get_control_file(name), -1);
+}
diff --git a/libcutils/tests/sockets_test.cpp b/libcutils/tests/sockets_test.cpp
index 0f682a2..adfbf4a 100644
--- a/libcutils/tests/sockets_test.cpp
+++ b/libcutils/tests/sockets_test.cpp
@@ -18,10 +18,14 @@
 // IPv6 capabilities. These tests assume that no UDP packets are lost, which
 // should be the case for loopback communication, but is not guaranteed.
 
-#include <cutils/sockets.h>
-
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/un.h>
 #include <time.h>
 
+#include <cutils/sockets.h>
 #include <gtest/gtest.h>
 
 // Makes sure the passed sockets are valid, sends data between them, and closes
@@ -185,3 +189,49 @@
 TEST(SocketsTest, TestSocketSendBuffersFailure) {
     EXPECT_EQ(-1, socket_send_buffers(INVALID_SOCKET, nullptr, 0));
 }
+
+#ifndef SOCK_NONBLOCK
+#define SOCK_NONBLOCK 0
+#endif
+
+#ifndef SOCK_CLOEXEC
+#define SOCK_CLOEXEC 0
+#endif
+
+TEST(SocketsTest, android_get_control_socket) {
+    static const char key[] = ANDROID_SOCKET_ENV_PREFIX "SocketsTest_android_get_control_socket";
+    static const char* name = key + strlen(ANDROID_SOCKET_ENV_PREFIX);
+
+    EXPECT_EQ(unsetenv(key), 0);
+    EXPECT_EQ(android_get_control_socket(name), -1);
+
+    int fd;
+    ASSERT_GE(fd = socket(PF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0), 0);
+#ifdef F_GETFL
+    int flags;
+    ASSERT_GE(flags = fcntl(fd, F_GETFL), 0);
+    ASSERT_GE(fcntl(fd, F_SETFL, flags | O_NONBLOCK), 0);
+#endif
+    EXPECT_EQ(android_get_control_socket(name), -1);
+
+    struct sockaddr_un addr;
+    memset(&addr, 0, sizeof(addr));
+    addr.sun_family = AF_UNIX;
+    snprintf(addr.sun_path, sizeof(addr.sun_path), ANDROID_SOCKET_DIR"/%s", name);
+    unlink(addr.sun_path);
+
+    EXPECT_EQ(bind(fd, (struct sockaddr*)&addr, sizeof(addr)), 0);
+    EXPECT_EQ(android_get_control_socket(name), -1);
+
+    char val[32];
+    snprintf(val, sizeof(val), "%d", fd);
+    EXPECT_EQ(setenv(key, val, true), 0);
+
+    EXPECT_EQ(android_get_control_socket(name), fd);
+    socket_close(fd);
+    EXPECT_EQ(android_get_control_socket(name), -1);
+    EXPECT_EQ(unlink(addr.sun_path), 0);
+    EXPECT_EQ(android_get_control_socket(name), -1);
+    EXPECT_EQ(unsetenv(key), 0);
+    EXPECT_EQ(android_get_control_socket(name), -1);
+}
diff --git a/liblog/tests/libc_test.cpp b/liblog/tests/libc_test.cpp
index 3d58147..f05a955 100644
--- a/liblog/tests/libc_test.cpp
+++ b/liblog/tests/libc_test.cpp
@@ -16,6 +16,7 @@
 
 #include <gtest/gtest.h>
 
+#include <errno.h>
 #include <stdio.h>
 
 TEST(libc, __pstore_append) {
@@ -23,6 +24,22 @@
     ASSERT_TRUE(NULL != (fp = fopen("/dev/pmsg0", "a")));
     static const char message[] = "libc.__pstore_append\n";
     ASSERT_EQ((size_t)1, fwrite(message, sizeof(message), 1, fp));
-    ASSERT_EQ(0, fclose(fp));
-    fprintf(stderr, "Reboot, ensure string libc.__pstore_append is in /sys/fs/pstore/pmsg-ramoops-0\n");
+    int fflushReturn = fflush(fp);
+    int fflushErrno = fflushReturn ? errno : 0;
+    ASSERT_EQ(0, fflushReturn);
+    ASSERT_EQ(0, fflushErrno);
+    int fcloseReturn = fclose(fp);
+    int fcloseErrno = fcloseReturn ? errno : 0;
+    ASSERT_EQ(0, fcloseReturn);
+    ASSERT_EQ(0, fcloseErrno);
+    if ((fcloseErrno == ENOMEM) || (fflushErrno == ENOMEM)) {
+        fprintf(stderr,
+                "Kernel does not have space allocated to pmsg pstore driver configured\n"
+               );
+    }
+    if (!fcloseReturn && !fcloseErrno && !fflushReturn && !fflushReturn) {
+        fprintf(stderr,
+                "Reboot, ensure string libc.__pstore_append is in /sys/fs/pstore/pmsg-ramoops-0\n"
+               );
+    }
 }
diff --git a/liblog/tests/liblog_test.cpp b/liblog/tests/liblog_test.cpp
index fd38849..9c09523 100644
--- a/liblog/tests/liblog_test.cpp
+++ b/liblog/tests/liblog_test.cpp
@@ -16,6 +16,7 @@
 
 #include <ctype.h>
 #include <dirent.h>
+#include <errno.h>
 #include <fcntl.h>
 #include <inttypes.h>
 #include <semaphore.h>
@@ -2655,12 +2656,19 @@
     bool logdwActiveAfter__android_log_close = isLogdwActive();
     EXPECT_FALSE(pmsgActiveAfter__android_log_close);
     EXPECT_FALSE(logdwActiveAfter__android_log_close);
-    EXPECT_LT(0, __android_log_pmsg_file_write(
+    int return__android_log_pmsg_file_write = __android_log_pmsg_file_write(
             LOG_ID_CRASH, ANDROID_LOG_VERBOSE,
-            __pmsg_file, max_payload_buf, sizeof(max_payload_buf)));
-    fprintf(stderr, "Reboot, ensure file %s matches\n"
-                    "with liblog.__android_log_msg_file_read test\n",
-                    __pmsg_file);
+            __pmsg_file, max_payload_buf, sizeof(max_payload_buf));
+    EXPECT_LT(0, return__android_log_pmsg_file_write);
+    if (return__android_log_pmsg_file_write == -ENOMEM) {
+        fprintf(stderr,
+                "Kernel does not have space allocated to pmsg pstore driver configured\n"
+               );
+    } else if (!return__android_log_pmsg_file_write) {
+        fprintf(stderr, "Reboot, ensure file %s matches\n"
+                        "with liblog.__android_log_msg_file_read test\n",
+                        __pmsg_file);
+    }
     bool pmsgActiveAfter__android_pmsg_file_write = isPmsgActive();
     bool logdwActiveAfter__android_pmsg_file_write = isLogdwActive();
     EXPECT_FALSE(pmsgActiveAfter__android_pmsg_file_write);
diff --git a/libnativeloader/native_loader.cpp b/libnativeloader/native_loader.cpp
index fb95cb6..e09cce3 100644
--- a/libnativeloader/native_loader.cpp
+++ b/libnativeloader/native_loader.cpp
@@ -473,14 +473,14 @@
 }
 
 #if defined(__ANDROID__)
+// native_bridge_namespaces are not supported for callers of this function.
+// This function will return nullptr in the case when application is running
+// on native bridge.
 android_namespace_t* FindNamespaceByClassLoader(JNIEnv* env, jobject class_loader) {
   std::lock_guard<std::mutex> guard(g_namespaces_mutex);
-  // native_bridge_namespaces are not supported for callers of this function.
-  // At the moment this is libwebviewchromium_loader and vulkan.
   NativeLoaderNamespace ns;
   if (g_namespaces->FindNamespaceByClassLoader(env, class_loader, &ns)) {
-    CHECK(ns.is_android_namespace());
-    return ns.get_android_ns();
+    return ns.is_android_namespace() ? ns.get_android_ns() : nullptr;
   }
 
   return nullptr;
diff --git a/logd/Android.mk b/logd/Android.mk
index 81637d2..7fe48d7 100644
--- a/logd/Android.mk
+++ b/logd/Android.mk
@@ -29,7 +29,7 @@
     libcutils \
     libbase \
     libpackagelistparser \
-    libminijail
+    libcap
 
 # This is what we want to do:
 #  event_logtags = $(shell \
diff --git a/logd/LogAudit.cpp b/logd/LogAudit.cpp
index 3811daa..c3ccd84 100644
--- a/logd/LogAudit.cpp
+++ b/logd/LogAudit.cpp
@@ -25,6 +25,7 @@
 #include <sys/uio.h>
 #include <syslog.h>
 
+#include <android-base/macros.h>
 #include <private/android_filesystem_config.h>
 #include <private/android_logger.h>
 
@@ -143,7 +144,7 @@
                     iov[2].iov_len = strlen(newline);
                 }
 
-                writev(fdDmesg, iov, sizeof(iov) / sizeof(iov[0]));
+                writev(fdDmesg, iov, arraysize(iov));
                 free(last_str);
                 last_str = NULL;
             }
@@ -165,7 +166,7 @@
             iov[2].iov_base = const_cast<char *>(newline);
             iov[2].iov_len = strlen(newline);
 
-            writev(fdDmesg, iov, sizeof(iov) / sizeof(iov[0]));
+            writev(fdDmesg, iov, arraysize(iov));
         }
     }
 
diff --git a/logd/LogStatistics.cpp b/logd/LogStatistics.cpp
index d68bfee..d4b48ef 100644
--- a/logd/LogStatistics.cpp
+++ b/logd/LogStatistics.cpp
@@ -547,6 +547,7 @@
         }
         spaces += spaces_total;
     }
+    totalSize += sizeOf();
     if (spaces < 0) spaces = 0;
     output += android::base::StringPrintf("%*s%zu", spaces, "", totalSize);
 
diff --git a/logd/LogStatistics.h b/logd/LogStatistics.h
index bfaafa4..1f598af 100644
--- a/logd/LogStatistics.h
+++ b/logd/LogStatistics.h
@@ -42,8 +42,32 @@
 
     std::unordered_map<TKey, TEntry> map;
 
+    size_t bucket_size() const {
+        size_t count = 0;
+        for (size_t idx = 0; idx < map.bucket_count(); ++idx) {
+            size_t bucket_size = map.bucket_size(idx);
+            if (bucket_size == 0) bucket_size = 1;
+            count += bucket_size;
+        }
+        float load_factor = map.max_load_factor();
+        if (load_factor < 1.0) return count;
+        return count * load_factor;
+    }
+
+    static const size_t unordered_map_per_entry_overhead = sizeof(void*);
+    static const size_t unordered_map_bucket_overhead = sizeof(void*);
+
 public:
 
+    size_t size() const { return map.size(); }
+
+    // Estimate unordered_map memory usage.
+    size_t sizeOf() const {
+        return sizeof(*this) +
+               (size() * (sizeof(TEntry) + unordered_map_per_entry_overhead)) +
+               (bucket_size() * sizeof(size_t) + unordered_map_bucket_overhead);
+    }
+
     typedef typename std::unordered_map<TKey, TEntry>::iterator iterator;
     typedef typename std::unordered_map<TKey, TEntry>::const_iterator const_iterator;
 
@@ -155,6 +179,7 @@
         }
         return output;
     }
+
 };
 
 namespace EntryBaseConstants {
@@ -472,7 +497,30 @@
     // security tag list
     tagTable_t securityTagTable;
 
+    size_t sizeOf() const {
+        size_t size = sizeof(*this) + pidTable.sizeOf() + tidTable.sizeOf() +
+                      tagTable.sizeOf() + securityTagTable.sizeOf() +
+                      (pidTable.size() * sizeof(pidTable_t::iterator)) +
+                      (tagTable.size() * sizeof(tagTable_t::iterator));
+        for(auto it : pidTable) {
+            const char* name = it.second.getName();
+            if (name) size += strlen(name) + 1;
+        }
+        for(auto it : tidTable) {
+            const char* name = it.second.getName();
+            if (name) size += strlen(name) + 1;
+        }
+        log_id_for_each(id) {
+            size += uidTable[id].sizeOf();
+            size += uidTable[id].size() * sizeof(uidTable_t::iterator);
+            size += pidSystemTable[id].sizeOf();
+            size += pidSystemTable[id].size() * sizeof(pidSystemTable_t::iterator);
+        }
+        return size;
+    }
+
 public:
+
     LogStatistics();
 
     void enableStatistics() { enable = true; }
diff --git a/logd/logd.rc b/logd/logd.rc
index 31ed4df..54349dd 100644
--- a/logd/logd.rc
+++ b/logd/logd.rc
@@ -2,10 +2,15 @@
     socket logd stream 0666 logd logd
     socket logdr seqpacket 0666 logd logd
     socket logdw dgram 0222 logd logd
-    group root system readproc
+    file /proc/kmsg r
+    file /dev/kmsg w
+    user logd
+    group logd system readproc
     writepid /dev/cpuset/system-background/tasks
 
 service logd-reinit /system/bin/logd --reinit
     oneshot
     disabled
+    user logd
+    group logd
     writepid /dev/cpuset/system-background/tasks
diff --git a/logd/main.cpp b/logd/main.cpp
index 0cb26dc..d698976 100644
--- a/logd/main.cpp
+++ b/logd/main.cpp
@@ -39,13 +39,12 @@
 #include <android-base/macros.h>
 #include <cutils/properties.h>
 #include <cutils/sched_policy.h>
+#include <cutils/files.h>
 #include <cutils/sockets.h>
-#include <libminijail.h>
 #include <log/event_tag_map.h>
 #include <packagelistparser/packagelistparser.h>
 #include <private/android_filesystem_config.h>
 #include <private/android_logger.h>
-#include <scoped_minijail.h>
 #include <utils/threads.h>
 
 #include "CommandListener.h"
@@ -90,29 +89,81 @@
 //    logd
 //
 
-static int drop_privs() {
+static int drop_privs(bool klogd, bool auditd) {
+    // Tricky, if ro.build.type is "eng" then this is true because of the
+    // side effect that ro.debuggable == 1 as well, else it is false.
+    bool eng = __android_logger_property_get_bool("ro.build.type", BOOL_DEFAULT_FALSE);
+
     struct sched_param param;
     memset(&param, 0, sizeof(param));
 
     if (set_sched_policy(0, SP_BACKGROUND) < 0) {
-        return -1;
+        android::prdebug("failed to set background scheduling policy");
+        if (!eng) return -1;
     }
 
     if (sched_setscheduler((pid_t) 0, SCHED_BATCH, &param) < 0) {
-        return -1;
+        android::prdebug("failed to set batch scheduler");
+        if (!eng) return -1;
     }
 
     if (setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_BACKGROUND) < 0) {
+        android::prdebug("failed to set background cgroup");
+        if (!eng) return -1;
+    }
+
+    if (!eng && (prctl(PR_SET_DUMPABLE, 0) < 0)) {
+        android::prdebug("failed to clear PR_SET_DUMPABLE");
         return -1;
     }
 
+    if (prctl(PR_SET_KEEPCAPS, 1) < 0) {
+        android::prdebug("failed to set PR_SET_KEEPCAPS");
+        if (!eng) return -1;
+    }
+
+    std::unique_ptr<struct _cap_struct, int(*)(void *)> caps(cap_init(), cap_free);
+    if (cap_clear(caps.get()) < 0) return -1;
+    cap_value_t cap_value[] = {
+        CAP_SETGID, // must be first for below
+        klogd ? CAP_SYSLOG : CAP_SETGID,
+        auditd ? CAP_AUDIT_CONTROL : CAP_SETGID
+    };
+    if (cap_set_flag(caps.get(), CAP_PERMITTED,
+                     arraysize(cap_value), cap_value,
+                     CAP_SET) < 0) return -1;
+    if (cap_set_flag(caps.get(), CAP_EFFECTIVE,
+                     arraysize(cap_value), cap_value,
+                     CAP_SET) < 0) return -1;
+    if (cap_set_proc(caps.get()) < 0) {
+        android::prdebug("failed to set CAP_SETGID, CAP_SYSLOG or CAP_AUDIT_CONTROL (%d)", errno);
+        if (!eng) return -1;
+    }
+
     gid_t groups[] = { AID_READPROC };
-    ScopedMinijail j(minijail_new());
-    minijail_set_supplementary_gids(j.get(), arraysize(groups), groups);
-    minijail_change_uid(j.get(), AID_LOGD);
-    minijail_change_gid(j.get(), AID_LOGD);
-    minijail_use_caps(j.get(), CAP_TO_MASK(CAP_SYSLOG) | CAP_TO_MASK(CAP_AUDIT_CONTROL));
-    minijail_enter(j.get());
+
+    if (setgroups(arraysize(groups), groups) == -1) {
+        android::prdebug("failed to set AID_READPROC groups");
+        if (!eng) return -1;
+    }
+
+    if (setgid(AID_LOGD) != 0) {
+        android::prdebug("failed to set AID_LOGD gid");
+        if (!eng) return -1;
+    }
+
+    if (setuid(AID_LOGD) != 0) {
+        android::prdebug("failed to set AID_LOGD uid");
+        if (!eng) return -1;
+    }
+
+    if (cap_set_flag(caps.get(), CAP_PERMITTED, 1, cap_value, CAP_CLEAR) < 0) return -1;
+    if (cap_set_flag(caps.get(), CAP_EFFECTIVE, 1, cap_value, CAP_CLEAR) < 0) return -1;
+    if (cap_set_proc(caps.get()) < 0) {
+        android::prdebug("failed to clear CAP_SETGID (%d)", errno);
+        if (!eng) return -1;
+    }
+
     return 0;
 }
 
@@ -184,11 +235,16 @@
     set_sched_policy(0, SP_BACKGROUND);
     setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_BACKGROUND);
 
-    // If we are AID_ROOT, we should drop to AID_SYSTEM, if we are anything
-    // else, we have even lesser privileges and accept our fate. Not worth
-    // checking for error returns setting this thread's privileges.
-    (void)setgid(AID_SYSTEM);
-    (void)setuid(AID_SYSTEM);
+    cap_t caps = cap_init();
+    (void)cap_clear(caps);
+    (void)cap_set_proc(caps);
+    (void)cap_free(caps);
+
+    // If we are AID_ROOT, we should drop to AID_LOGD+AID_SYSTEM, if we are
+    // anything else, we have even lesser privileges and accept our fate. Not
+    // worth checking for error returns setting this thread's privileges.
+    (void)setgid(AID_SYSTEM); // readonly access to /data/system/packages.list
+    (void)setuid(AID_LOGD);   // access to everything logd.
 
     while (reinit_running && !sem_wait(&reinit) && reinit_running) {
 
@@ -306,6 +362,39 @@
     }
 }
 
+static int issueReinit() {
+    cap_t caps = cap_init();
+    (void)cap_clear(caps);
+    (void)cap_set_proc(caps);
+    (void)cap_free(caps);
+
+    int sock = TEMP_FAILURE_RETRY(
+        socket_local_client("logd",
+                            ANDROID_SOCKET_NAMESPACE_RESERVED,
+                            SOCK_STREAM));
+    if (sock < 0) return -errno;
+
+    static const char reinitStr[] = "reinit";
+    ssize_t ret = TEMP_FAILURE_RETRY(write(sock, reinitStr, sizeof(reinitStr)));
+    if (ret < 0) return -errno;
+
+    struct pollfd p;
+    memset(&p, 0, sizeof(p));
+    p.fd = sock;
+    p.events = POLLIN;
+    ret = TEMP_FAILURE_RETRY(poll(&p, 1, 1000));
+    if (ret < 0) return -errno;
+    if ((ret == 0) || !(p.revents & POLLIN)) return -ETIME;
+
+    static const char success[] = "success";
+    char buffer[sizeof(success) - 1];
+    memset(buffer, 0, sizeof(buffer));
+    ret = TEMP_FAILURE_RETRY(read(sock, buffer, sizeof(buffer)));
+    if (ret < 0) return -errno;
+
+    return strncmp(buffer, success, sizeof(success) - 1) != 0;
+}
+
 // Foreground waits for exit of the main persistent threads
 // that are started here. The threads are created to manage
 // UNIX domain client sockets for writing, reading and
@@ -313,6 +402,17 @@
 // logging plugins like auditd and restart control. Additional
 // transitory per-client threads are created for each reader.
 int main(int argc, char *argv[]) {
+    // issue reinit command. KISS argument parsing.
+    if ((argc > 1) && argv[1] && !strcmp(argv[1], "--reinit")) {
+        return issueReinit();
+    }
+
+    static const char dev_kmsg[] = "/dev/kmsg";
+    fdDmesg = android_get_control_file(dev_kmsg);
+    if (fdDmesg < 0) {
+        fdDmesg = TEMP_FAILURE_RETRY(open(dev_kmsg, O_WRONLY | O_CLOEXEC));
+    }
+
     int fdPmesg = -1;
     bool klogd = __android_logger_property_get_bool("logd.kernel",
                                                     BOOL_DEFAULT_TRUE |
@@ -320,43 +420,13 @@
                                                     BOOL_DEFAULT_FLAG_ENG |
                                                     BOOL_DEFAULT_FLAG_SVELTE);
     if (klogd) {
-        fdPmesg = open("/proc/kmsg", O_RDONLY | O_NDELAY);
-    }
-    fdDmesg = open("/dev/kmsg", O_WRONLY);
-
-    // issue reinit command. KISS argument parsing.
-    if ((argc > 1) && argv[1] && !strcmp(argv[1], "--reinit")) {
-        int sock = TEMP_FAILURE_RETRY(
-            socket_local_client("logd",
-                                ANDROID_SOCKET_NAMESPACE_RESERVED,
-                                SOCK_STREAM));
-        if (sock < 0) {
-            return -errno;
+        static const char proc_kmsg[] = "/proc/kmsg";
+        fdPmesg = android_get_control_file(proc_kmsg);
+        if (fdPmesg < 0) {
+            fdPmesg = TEMP_FAILURE_RETRY(open(proc_kmsg,
+                                              O_RDONLY | O_NDELAY | O_CLOEXEC));
         }
-        static const char reinit[] = "reinit";
-        ssize_t ret = TEMP_FAILURE_RETRY(write(sock, reinit, sizeof(reinit)));
-        if (ret < 0) {
-            return -errno;
-        }
-        struct pollfd p;
-        memset(&p, 0, sizeof(p));
-        p.fd = sock;
-        p.events = POLLIN;
-        ret = TEMP_FAILURE_RETRY(poll(&p, 1, 1000));
-        if (ret < 0) {
-            return -errno;
-        }
-        if ((ret == 0) || !(p.revents & POLLIN)) {
-            return -ETIME;
-        }
-        static const char success[] = "success";
-        char buffer[sizeof(success) - 1];
-        memset(buffer, 0, sizeof(buffer));
-        ret = TEMP_FAILURE_RETRY(read(sock, buffer, sizeof(buffer)));
-        if (ret < 0) {
-            return -errno;
-        }
-        return strncmp(buffer, success, sizeof(success) - 1) != 0;
+        if (fdPmesg < 0) android::prdebug("Failed to open %s\n", proc_kmsg);
     }
 
     // Reinit Thread
@@ -381,7 +451,10 @@
         pthread_attr_destroy(&attr);
     }
 
-    if (drop_privs() != 0) {
+    bool auditd = __android_logger_property_get_bool("logd.auditd",
+                                                     BOOL_DEFAULT_TRUE |
+                                                     BOOL_DEFAULT_FLAG_PERSIST);
+    if (drop_privs(klogd, auditd) != 0) {
         return -1;
     }
 
@@ -436,9 +509,6 @@
     // initiated log messages. New log entries are added to LogBuffer
     // and LogReader is notified to send updates to connected clients.
 
-    bool auditd = __android_logger_property_get_bool("logd.auditd",
-                                                     BOOL_DEFAULT_TRUE |
-                                                     BOOL_DEFAULT_FLAG_PERSIST);
     LogAudit *al = NULL;
     if (auditd) {
         al = new LogAudit(logBuf, reader,
diff --git a/logd/tests/logd_test.cpp b/logd/tests/logd_test.cpp
index e0a4cc3..254a3f8 100644
--- a/logd/tests/logd_test.cpp
+++ b/logd/tests/logd_test.cpp
@@ -23,6 +23,7 @@
 
 #include <string>
 
+#include <android-base/macros.h>
 #include <android-base/stringprintf.h>
 #include <cutils/sockets.h>
 #include <gtest/gtest.h>
@@ -351,7 +352,7 @@
         "/dev/log/system", "/dev/log_system",
     };
 
-    for (unsigned int i = 0; i < (sizeof(loggers) / sizeof(loggers[0])); ++i) {
+    for (unsigned int i = 0; i < arraysize(loggers); ++i) {
         fd = open(loggers[i], O_RDONLY);
         if (fd < 0) {
             continue;
@@ -434,12 +435,12 @@
     static const unsigned int log_latency = 4;
     static const unsigned int log_delay = 5;
 
-    unsigned long ns[sizeof(benchmarks) / sizeof(benchmarks[0])];
+    unsigned long ns[arraysize(benchmarks)];
 
     memset(ns, 0, sizeof(ns));
 
     while (fgets(buffer, sizeof(buffer), fp)) {
-        for (unsigned i = 0; i < sizeof(ns) / sizeof(ns[0]); ++i) {
+        for (unsigned i = 0; i < arraysize(ns); ++i) {
             char *cp = strstr(buffer, benchmarks[i]);
             if (!cp) {
                 continue;
@@ -470,7 +471,7 @@
 
     EXPECT_GE(20000000UL, ns[log_delay]); // 10500289 user
 
-    for (unsigned i = 0; i < sizeof(ns) / sizeof(ns[0]); ++i) {
+    for (unsigned i = 0; i < arraysize(ns); ++i) {
         EXPECT_NE(0UL, ns[i]);
     }
 
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 31b1821..8f0b932 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -669,13 +669,3 @@
 service flash_recovery /system/bin/install-recovery.sh
     class main
     oneshot
-
-service hwservicemanager /system/bin/hwservicemanager
-    user system
-    disabled
-    group system readproc
-    critical
-    writepid /dev/cpuset/system-background/tasks
-
-on property:hwservicemanager.ready=true
-    class_start hal
diff --git a/rootdir/init.zygote32.rc b/rootdir/init.zygote32.rc
index 2d7d5c2..eedeba8 100644
--- a/rootdir/init.zygote32.rc
+++ b/rootdir/init.zygote32.rc
@@ -1,6 +1,8 @@
 service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
     class main
     priority -20
+    user root
+    group root readproc
     socket zygote stream 660 root system
     onrestart write /sys/android_power/request_state wake
     onrestart write /sys/power/state on
diff --git a/rootdir/init.zygote32_64.rc b/rootdir/init.zygote32_64.rc
index 4156847..84a907f 100644
--- a/rootdir/init.zygote32_64.rc
+++ b/rootdir/init.zygote32_64.rc
@@ -1,6 +1,8 @@
 service zygote /system/bin/app_process32 -Xzygote /system/bin --zygote --start-system-server --socket-name=zygote
     class main
     priority -20
+    user root
+    group root readproc
     socket zygote stream 660 root system
     onrestart write /sys/android_power/request_state wake
     onrestart write /sys/power/state on
@@ -13,6 +15,8 @@
 service zygote_secondary /system/bin/app_process64 -Xzygote /system/bin --zygote --socket-name=zygote_secondary
     class main
     priority -20
+    user root
+    group root readproc
     socket zygote_secondary stream 660 root system
     onrestart restart zygote
     writepid /dev/cpuset/foreground/tasks
diff --git a/rootdir/init.zygote64.rc b/rootdir/init.zygote64.rc
index 8584cbb..76e2b79 100644
--- a/rootdir/init.zygote64.rc
+++ b/rootdir/init.zygote64.rc
@@ -1,6 +1,8 @@
 service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server
     class main
     priority -20
+    user root
+    group root readproc
     socket zygote stream 660 root system
     onrestart write /sys/android_power/request_state wake
     onrestart write /sys/power/state on
diff --git a/rootdir/init.zygote64_32.rc b/rootdir/init.zygote64_32.rc
index 27eaa66..e918b67 100644
--- a/rootdir/init.zygote64_32.rc
+++ b/rootdir/init.zygote64_32.rc
@@ -1,6 +1,8 @@
 service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server --socket-name=zygote
     class main
     priority -20
+    user root
+    group root readproc
     socket zygote stream 660 root system
     onrestart write /sys/android_power/request_state wake
     onrestart write /sys/power/state on
@@ -13,6 +15,8 @@
 service zygote_secondary /system/bin/app_process32 -Xzygote /system/bin --zygote --socket-name=zygote_secondary
     class main
     priority -20
+    user root
+    group root readproc
     socket zygote_secondary stream 660 root system
     onrestart restart zygote
     writepid /dev/cpuset/foreground/tasks