am 87044e66: am 5a50b16e: am 8ea5dd8c: Merge "Remove LogMessage::LogLineLowStack."
* commit '87044e667e0a0f7fbbb893742c441209072096a0':
Remove LogMessage::LogLineLowStack.
diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp
index e139bcd..e35cc70 100644
--- a/fastboot/fastboot.cpp
+++ b/fastboot/fastboot.cpp
@@ -285,9 +285,8 @@
" Can override the fs type and/or\n"
" size the bootloader reports.\n"
" getvar <variable> display a bootloader variable\n"
- " boot <kernel> [ <ramdisk> [ <second> ] ] download and boot kernel\n"
- " flash:raw boot <kernel> [ <ramdisk> [ <second> ] ] create bootimage and \n"
- " flash it\n"
+ " boot <kernel> [ <ramdisk> ] download and boot kernel\n"
+ " flash:raw boot <kernel> [ <ramdisk> ] create bootimage and flash it\n"
" devices list all connected devices\n"
" continue continue with autoboot\n"
" reboot [bootloader] reboot device, optionally into bootloader\n"
@@ -315,11 +314,10 @@
}
void *load_bootable_image(const char *kernel, const char *ramdisk,
- const char *secondstage, unsigned *sz,
- const char *cmdline)
+ unsigned *sz, const char *cmdline)
{
- void *kdata = 0, *rdata = 0, *sdata = 0;
- unsigned ksize = 0, rsize = 0, ssize = 0;
+ void *kdata = 0, *rdata = 0;
+ unsigned ksize = 0, rsize = 0;
void *bdata;
unsigned bsize;
@@ -355,18 +353,10 @@
}
}
- if (secondstage) {
- sdata = load_file(secondstage, &ssize);
- if(sdata == 0) {
- fprintf(stderr,"cannot load '%s': %s\n", secondstage, strerror(errno));
- return 0;
- }
- }
-
fprintf(stderr,"creating boot image...\n");
bdata = mkbootimg(kdata, ksize, kernel_offset,
rdata, rsize, ramdisk_offset,
- sdata, ssize, second_offset,
+ 0, 0, second_offset,
page_size, base_addr, tags_offset, &bsize);
if(bdata == 0) {
fprintf(stderr,"failed to create boot.img\n");
@@ -1134,7 +1124,6 @@
} else if(!strcmp(*argv, "boot")) {
char *kname = 0;
char *rname = 0;
- char *sname = 0;
skip(1);
if (argc > 0) {
kname = argv[0];
@@ -1144,11 +1133,7 @@
rname = argv[0];
skip(1);
}
- if (argc > 0) {
- sname = argv[0];
- skip(1);
- }
- data = load_bootable_image(kname, rname, sname, &sz, cmdline);
+ data = load_bootable_image(kname, rname, &sz, cmdline);
if (data == 0) return 1;
fb_queue_download("boot.img", data, sz);
fb_queue_command("boot", "booting");
@@ -1172,18 +1157,14 @@
char *pname = argv[1];
char *kname = argv[2];
char *rname = 0;
- char *sname = 0;
require(3);
- skip(3);
- if (argc > 0) {
- rname = argv[0];
- skip(1);
+ if(argc > 3) {
+ rname = argv[3];
+ skip(4);
+ } else {
+ skip(3);
}
- if (argc > 0) {
- sname = argv[0];
- skip(1);
- }
- data = load_bootable_image(kname, rname, sname, &sz, cmdline);
+ data = load_bootable_image(kname, rname, &sz, cmdline);
if (data == 0) die("cannot load bootable image");
fb_queue_flash(pname, data, sz);
} else if(!strcmp(*argv, "flashall")) {
diff --git a/fs_mgr/fs_mgr_fstab.c b/fs_mgr/fs_mgr_fstab.c
index 8b0f714..4451b82 100644
--- a/fs_mgr/fs_mgr_fstab.c
+++ b/fs_mgr/fs_mgr_fstab.c
@@ -70,6 +70,7 @@
{ "zramsize=", MF_ZRAMSIZE },
{ "verify", MF_VERIFY },
{ "noemulatedsd", MF_NOEMULATEDSD },
+ { "notrim", MF_NOTRIM },
{ "defaults", 0 },
{ 0, 0 },
};
@@ -448,3 +449,8 @@
{
return fstab->fs_mgr_flags & MF_NOEMULATEDSD;
}
+
+int fs_mgr_is_notrim(struct fstab_rec *fstab)
+{
+ return fstab->fs_mgr_flags & MF_NOTRIM;
+}
diff --git a/fs_mgr/fs_mgr_priv.h b/fs_mgr/fs_mgr_priv.h
index d56111a..ee944c1 100644
--- a/fs_mgr/fs_mgr_priv.h
+++ b/fs_mgr/fs_mgr_priv.h
@@ -76,6 +76,7 @@
#define MF_FORCECRYPT 0x400
#define MF_NOEMULATEDSD 0x800 /* no emulated sdcard daemon, sd card is the only
external storage */
+#define MF_NOTRIM 0x1000
#define MF_FILEENCRYPTION 0x2000
#define DM_BUF_SIZE 4096
diff --git a/fs_mgr/include/fs_mgr.h b/fs_mgr/include/fs_mgr.h
index b5e02f9..7e1377d 100644
--- a/fs_mgr/include/fs_mgr.h
+++ b/fs_mgr/include/fs_mgr.h
@@ -103,6 +103,7 @@
int fs_mgr_is_encryptable(const struct fstab_rec *fstab);
int fs_mgr_is_file_encrypted(const struct fstab_rec *fstab);
int fs_mgr_is_noemulatedsd(const struct fstab_rec *fstab);
+int fs_mgr_is_notrim(struct fstab_rec *fstab);
int fs_mgr_swapon_all(struct fstab *fstab);
#ifdef __cplusplus
}
diff --git a/healthd/healthd.cpp b/healthd/healthd.cpp
index 1fee855..b0002cc 100644
--- a/healthd/healthd.cpp
+++ b/healthd/healthd.cpp
@@ -53,6 +53,7 @@
.batteryCurrentAvgPath = String8(String8::kEmptyString),
.batteryChargeCounterPath = String8(String8::kEmptyString),
.energyCounter = NULL,
+ .boot_min_cap = 0,
.screen_on = NULL,
};
diff --git a/healthd/healthd.h b/healthd/healthd.h
index 4704f0b..84b6d76 100644
--- a/healthd/healthd.h
+++ b/healthd/healthd.h
@@ -67,6 +67,7 @@
android::String8 batteryChargeCounterPath;
int (*energyCounter)(int64_t *);
+ int boot_min_cap;
bool (*screen_on)(android::BatteryProperties *props);
};
diff --git a/healthd/healthd_mode_charger.cpp b/healthd/healthd_mode_charger.cpp
index 9ed5944..352510b 100644
--- a/healthd/healthd_mode_charger.cpp
+++ b/healthd/healthd_mode_charger.cpp
@@ -116,6 +116,7 @@
struct animation *batt_anim;
gr_surface surf_unknown;
+ int boot_min_cap;
};
static struct frame batt_anim_frames[] = {
@@ -520,19 +521,29 @@
LOGW("[%" PRId64 "] booting from charger mode\n", now);
property_set("sys.boot_from_charger_mode", "1");
} else {
- LOGW("[%" PRId64 "] rebooting\n", now);
- android_reboot(ANDROID_RB_RESTART, 0, 0);
+ if (charger->batt_anim->capacity >= charger->boot_min_cap) {
+ LOGW("[%" PRId64 "] rebooting\n", now);
+ android_reboot(ANDROID_RB_RESTART, 0, 0);
+ } else {
+ LOGV("[%" PRId64 "] ignore power-button press, battery level "
+ "less than minimum\n", now);
+ }
}
} else {
/* if the key is pressed but timeout hasn't expired,
* make sure we wake up at the right-ish time to check
*/
set_next_key_check(charger, key, POWER_ON_KEY_TIME);
+
+ /* Turn on the display and kick animation on power-key press
+ * rather than on key release
+ */
+ kick_animation(charger->batt_anim);
+ request_suspend(false);
}
} else {
/* if the power key got released, force screen state cycle */
if (key->pending) {
- request_suspend(false);
kick_animation(charger->batt_anim);
}
}
@@ -555,6 +566,11 @@
return;
if (!charger->charger_connected) {
+
+ /* Last cycle would have stopped at the extreme top of battery-icon
+ * Need to show the correct level corresponding to capacity.
+ */
+ kick_animation(charger->batt_anim);
request_suspend(false);
if (charger->next_pwr_check == -1) {
charger->next_pwr_check = now + UNPLUGGED_SHUTDOWN_TIME;
@@ -705,4 +721,5 @@
charger->next_key_check = -1;
charger->next_pwr_check = -1;
healthd_config = config;
+ charger->boot_min_cap = config->boot_min_cap;
}
diff --git a/include/netutils/dhcp.h b/include/netutils/dhcp.h
index de6bc82..008dbd8 100644
--- a/include/netutils/dhcp.h
+++ b/include/netutils/dhcp.h
@@ -23,26 +23,18 @@
__BEGIN_DECLS
extern int do_dhcp(char *iname);
-extern int dhcp_do_request(const char *ifname,
- char *ipaddr,
- char *gateway,
- uint32_t *prefixLength,
- char *dns[],
- char *server,
- uint32_t *lease,
- char *vendorInfo,
- char *domain,
- char *mtu);
-extern int dhcp_do_request_renew(const char *ifname,
- char *ipaddr,
- char *gateway,
- uint32_t *prefixLength,
- char *dns[],
- char *server,
- uint32_t *lease,
- char *vendorInfo,
- char *domain,
- char *mtu);
+extern int dhcp_start(const char *ifname);
+extern int dhcp_start_renew(const char *ifname);
+extern int dhcp_get_results(const char *ifname,
+ char *ipaddr,
+ char *gateway,
+ uint32_t *prefixLength,
+ char *dns[],
+ char *server,
+ uint32_t *lease,
+ char *vendorInfo,
+ char *domain,
+ char *mtu);
extern int dhcp_stop(const char *ifname);
extern int dhcp_release_lease(const char *ifname);
extern char *dhcp_get_errmsg();
diff --git a/include/private/android_filesystem_capability.h b/include/private/android_filesystem_capability.h
index 0505cda..b92d3db 100644
--- a/include/private/android_filesystem_capability.h
+++ b/include/private/android_filesystem_capability.h
@@ -105,7 +105,9 @@
#define CAP_MAC_ADMIN 33
#define CAP_SYSLOG 34
#define CAP_WAKE_ALARM 35
-#define CAP_LAST_CAP CAP_WAKE_ALARM
+#define CAP_BLOCK_SUSPEND 36
+#define CAP_AUDIT_READ 37
+#define CAP_LAST_CAP CAP_AUDIT_READ
#define cap_valid(x) ((x) >= 0 && (x) <= CAP_LAST_CAP)
#define CAP_TO_INDEX(x) ((x) >> 5)
#define CAP_TO_MASK(x) (1 << ((x) & 31))
diff --git a/include/private/android_filesystem_config.h b/include/private/android_filesystem_config.h
index a3d11a7..74e5c82 100644
--- a/include/private/android_filesystem_config.h
+++ b/include/private/android_filesystem_config.h
@@ -249,6 +249,7 @@
/* the following files have enhanced capabilities and ARE included in user builds. */
{ 00750, AID_ROOT, AID_SHELL, (1 << CAP_SETUID) | (1 << CAP_SETGID), "system/bin/run-as" },
+ { 00700, AID_SYSTEM, AID_SHELL, (1 << CAP_BLOCK_SUSPEND), "system/bin/inputflinger" },
{ 00750, AID_ROOT, AID_ROOT, 0, "system/bin/uncrypt" },
{ 00750, AID_ROOT, AID_ROOT, 0, "system/bin/install-recovery.sh" },
diff --git a/include/system/audio.h b/include/system/audio.h
index 181a171..2a85de1 100644
--- a/include/system/audio.h
+++ b/include/system/audio.h
@@ -194,7 +194,7 @@
AUDIO_FORMAT_PCM_SUB_16_BIT = 0x1, /* DO NOT CHANGE - PCM signed 16 bits */
AUDIO_FORMAT_PCM_SUB_8_BIT = 0x2, /* DO NOT CHANGE - PCM unsigned 8 bits */
AUDIO_FORMAT_PCM_SUB_32_BIT = 0x3, /* PCM signed .31 fixed point */
- AUDIO_FORMAT_PCM_SUB_8_24_BIT = 0x4, /* PCM signed 7.24 fixed point */
+ AUDIO_FORMAT_PCM_SUB_8_24_BIT = 0x4, /* PCM signed 8.23 fixed point */
AUDIO_FORMAT_PCM_SUB_FLOAT = 0x5, /* PCM single-precision floating point */
AUDIO_FORMAT_PCM_SUB_24_BIT_PACKED = 0x6, /* PCM signed .23 fixed point packed in 3 bytes */
} audio_format_pcm_sub_fmt_t;
@@ -234,6 +234,7 @@
AUDIO_FORMAT_VORBIS_SUB_NONE = 0x0,
} audio_format_vorbis_sub_fmt_t;
+
/* Audio format consists of a main format field (upper 8 bits) and a sub format
* field (lower 24 bits).
*
@@ -257,6 +258,8 @@
AUDIO_FORMAT_OPUS = 0x08000000UL,
AUDIO_FORMAT_AC3 = 0x09000000UL,
AUDIO_FORMAT_E_AC3 = 0x0A000000UL,
+ AUDIO_FORMAT_DTS = 0x0B000000UL,
+ AUDIO_FORMAT_DTS_HD = 0x0C000000UL,
AUDIO_FORMAT_MAIN_MASK = 0xFF000000UL,
AUDIO_FORMAT_SUB_MASK = 0x00FFFFFFUL,
@@ -872,6 +875,8 @@
typedef int audio_port_handle_t;
#define AUDIO_PORT_HANDLE_NONE 0
+/* the maximum length for the human-readable device name */
+#define AUDIO_PORT_MAX_NAME_LEN 128
/* maximum audio device address length */
#define AUDIO_DEVICE_MAX_ADDRESS_LEN 32
@@ -966,11 +971,11 @@
audio_session_t session; /* audio session */
};
-
struct audio_port {
audio_port_handle_t id; /* port unique ID */
audio_port_role_t role; /* sink or source */
audio_port_type_t type; /* device, mix ... */
+ char name[AUDIO_PORT_MAX_NAME_LEN];
unsigned int num_sample_rates; /* number of sampling rates in following array */
unsigned int sample_rates[AUDIO_PORT_MAX_SAMPLING_RATES];
unsigned int num_channel_masks; /* number of channel masks in following array */
@@ -1313,6 +1318,8 @@
case AUDIO_FORMAT_OPUS:
case AUDIO_FORMAT_AC3:
case AUDIO_FORMAT_E_AC3:
+ case AUDIO_FORMAT_DTS:
+ case AUDIO_FORMAT_DTS_HD:
return true;
default:
return false;
diff --git a/include/system/camera.h b/include/system/camera.h
index 7a4dd53..09c915d 100644
--- a/include/system/camera.h
+++ b/include/system/camera.h
@@ -194,7 +194,12 @@
/** The facing of the camera is opposite to that of the screen. */
CAMERA_FACING_BACK = 0,
/** The facing of the camera is the same as that of the screen. */
- CAMERA_FACING_FRONT = 1
+ CAMERA_FACING_FRONT = 1,
+ /**
+ * The facing of the camera is not fixed relative to the screen.
+ * The cameras with this facing are external cameras, e.g. USB cameras.
+ */
+ CAMERA_FACING_EXTERNAL = 2
};
enum {
diff --git a/include/system/graphics.h b/include/system/graphics.h
index c3fca97..c0f03fa 100644
--- a/include/system/graphics.h
+++ b/include/system/graphics.h
@@ -45,9 +45,12 @@
/*
* "linear" color pixel formats:
*
- * The pixel formats below contain sRGB data but are otherwise treated
- * as linear formats, i.e.: no special operation is performed when
- * reading or writing into a buffer in one of these formats
+ * When used with ANativeWindow, the dataSpace field describes the color
+ * space of the buffer.
+ *
+ * The color space determines, for example, if the formats are linear or
+ * gamma-corrected; or whether any special operations are performed when
+ * reading or writing into a buffer in one of these formats.
*/
HAL_PIXEL_FORMAT_RGBA_8888 = 1,
HAL_PIXEL_FORMAT_RGBX_8888 = 2,
@@ -56,28 +59,6 @@
HAL_PIXEL_FORMAT_BGRA_8888 = 5,
/*
- * sRGB color pixel formats:
- *
- * The red, green and blue components are stored in sRGB space, and converted
- * to linear space when read, using the standard sRGB to linear equation:
- *
- * Clinear = Csrgb / 12.92 for Csrgb <= 0.04045
- * = (Csrgb + 0.055 / 1.055)^2.4 for Csrgb > 0.04045
- *
- * When written the inverse transformation is performed:
- *
- * Csrgb = 12.92 * Clinear for Clinear <= 0.0031308
- * = 1.055 * Clinear^(1/2.4) - 0.055 for Clinear > 0.0031308
- *
- *
- * The alpha component, if present, is always stored in linear space and
- * is left unmodified when read or written.
- *
- */
- HAL_PIXEL_FORMAT_sRGB_A_8888 = 0xC,
- HAL_PIXEL_FORMAT_sRGB_X_8888 = 0xD,
-
- /*
* 0x100 - 0x1FF
*
* This range is reserved for pixel formats that are specific to the HAL
@@ -111,6 +92,8 @@
* cr_offset = y_size
* cb_offset = y_size + c_size
*
+ * When used with ANativeWindow, the dataSpace field describes the color
+ * space of the buffer.
*/
HAL_PIXEL_FORMAT_YV12 = 0x32315659, // YCrCb 4:2:0 Planar
@@ -135,6 +118,8 @@
*
* size = stride * height
*
+ * When used with ANativeWindow, the dataSpace field describes the color
+ * space of the buffer.
*/
HAL_PIXEL_FORMAT_Y8 = 0x20203859,
@@ -159,6 +144,10 @@
*
* size = stride * height * 2
*
+ * When used with ANativeWindow, the dataSpace field describes the color
+ * space of the buffer, except that dataSpace field
+ * HAL_DATASPACE_DEPTH indicates that this buffer contains a depth
+ * image where each sample is a distance value measured by a depth camera.
*/
HAL_PIXEL_FORMAT_Y16 = 0x20363159,
@@ -167,7 +156,7 @@
*
* This format is exposed outside of the camera HAL to applications.
*
- * RAW_SENSOR is a single-channel, 16-bit, little endian format, typically
+ * RAW16 is a single-channel, 16-bit, little endian format, typically
* representing raw Bayer-pattern images from an image sensor, with minimal
* processing.
*
@@ -193,9 +182,12 @@
* - GRALLOC_USAGE_HW_CAMERA_*
* - GRALLOC_USAGE_SW_*
* - GRALLOC_USAGE_RENDERSCRIPT
+ *
+ * When used with ANativeWindow, the dataSpace should be
+ * HAL_DATASPACE_ARBITRARY, as raw image sensor buffers require substantial
+ * extra metadata to define.
*/
HAL_PIXEL_FORMAT_RAW16 = 0x20,
- HAL_PIXEL_FORMAT_RAW_SENSOR = 0x20, // TODO(rubenbrunk): Remove RAW_SENSOR.
/*
* Android RAW10 format:
@@ -244,10 +236,64 @@
* - 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.
@@ -261,6 +307,10 @@
* - GRALLOC_USAGE_HW_CAMERA_*
* - GRALLOC_USAGE_SW_*
* - GRALLOC_USAGE_RENDERSCRIPT
+ *
+ * When used with ANativeWindow, the dataSpace field should be
+ * HAL_DATASPACE_ARBITRARY, as raw image sensor buffers require substantial
+ * extra metadata to define.
*/
HAL_PIXEL_FORMAT_RAW_OPAQUE = 0x24,
@@ -276,6 +326,16 @@
*
* Buffers of this format must have a height of 1, and width equal to their
* size in bytes.
+ *
+ * When used with ANativeWindow, the mapping of the dataSpace field to
+ * buffer contents for BLOB is as follows:
+ *
+ * dataSpace value | Buffer contents
+ * -------------------------------+-----------------------------------------
+ * HAL_DATASPACE_JFIF | An encoded JPEG image
+ * HAL_DATASPACE_DEPTH | An android_depth_points buffer
+ * Other | Unsupported
+ *
*/
HAL_PIXEL_FORMAT_BLOB = 0x21,
@@ -292,6 +352,8 @@
* framework will assume that sampling the texture will always return an
* alpha value of 1.0 (i.e. the buffer contains only opaque pixel values).
*
+ * When used with ANativeWindow, the dataSpace field describes the color
+ * space of the buffer.
*/
HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED = 0x22,
@@ -311,6 +373,9 @@
*
* This format is locked for use by gralloc's (*lock_ycbcr) method, and
* locking with the (*lock) method will return an error.
+ *
+ * When used with ANativeWindow, the dataSpace field describes the color
+ * space of the buffer.
*/
HAL_PIXEL_FORMAT_YCbCr_420_888 = 0x23,
@@ -355,6 +420,42 @@
};
/**
+ * Structure used to define depth point clouds for format HAL_PIXEL_FORMAT_BLOB
+ * with dataSpace value of HAL_DATASPACE_DEPTH.
+ * When locking a native buffer of the above format and dataSpace value,
+ * the vaddr pointer can be cast to this structure.
+ *
+ * A variable-length list of (x,y,z) 3D points, as floats.
+ *
+ * @num_points is the number of points in the list
+ *
+ * @xyz_points is the flexible array of floating-point values.
+ * It contains (num_points) * 3 floats.
+ *
+ * For example:
+ * android_depth_points d = get_depth_buffer();
+ * struct {
+ * float x; float y; float z;
+ * } firstPoint, lastPoint;
+ *
+ * firstPoint.x = d.xyz_points[0];
+ * firstPoint.y = d.xyz_points[1];
+ * firstPoint.z = d.xyz_points[2];
+ * lastPoint.x = d.xyz_points[(d.num_points - 1) * 3 + 0];
+ * lastPoint.y = d.xyz_points[(d.num_points - 1) * 3 + 1];
+ * lastPoint.z = d.xyz_points[(d.num_points - 1) * 3 + 2];
+ */
+
+struct android_depth_points {
+ uint32_t num_points;
+
+ /** reserved for future use, set to 0 by gralloc's (*lock)() */
+ uint32_t reserved[8];
+
+ float xyz_points[];
+};
+
+/**
* Transformation definitions
*
* IMPORTANT NOTE:
@@ -378,19 +479,33 @@
};
/**
- * Colorspace Definitions
+ * Dataspace Definitions
* ======================
*
- * Colorspace is the definition of how pixel values should be interpreted.
- * It includes primaries (including white point) and the transfer
- * characteristic function, which describes both gamma curve and numeric
- * range (within the bit depth).
+ * Dataspace is the definition of how pixel values should be interpreted.
+ *
+ * For many formats, this is the colorspace of the image data, which includes
+ * primaries (including white point) and the transfer characteristic function,
+ * which describes both gamma curve and numeric range (within the bit depth).
+ *
+ * Other dataspaces include depth measurement data from a depth camera.
*/
-enum {
+typedef enum android_dataspace {
/*
- * Arbitrary colorspace with manually defined characteristics.
- * Colorspace definition must be communicated separately.
+ * Default-assumption data space, when not explicitly specified.
+ *
+ * It is safest to assume the buffer is an image with sRGB primaries and
+ * encoding ranges, but the consumer and/or the producer of the data may
+ * simply be using defaults. No automatic gamma transform should be
+ * expected, except for a possible display gamma transform when drawn to a
+ * screen.
+ */
+ HAL_DATASPACE_UNKNOWN = 0x0,
+
+ /*
+ * Arbitrary dataspace with manually defined characteristics. Definition
+ * for colorspaces or other meaning must be communicated separately.
*
* This is used when specifying primaries, transfer characteristics,
* etc. separately.
@@ -399,7 +514,57 @@
* where a colorspace can have separately defined primaries, transfer
* characteristics, etc.
*/
- HAL_COLORSPACE_ARBITRARY = 0x1,
+ HAL_DATASPACE_ARBITRARY = 0x1,
+
+ /*
+ * RGB Colorspaces
+ * -----------------
+ *
+ * Primaries are given using (x,y) coordinates in the CIE 1931 definition
+ * of x and y specified by ISO 11664-1.
+ *
+ * Transfer characteristics are the opto-electronic transfer characteristic
+ * at the source as a function of linear optical intensity (luminance).
+ */
+
+ /*
+ * sRGB linear encoding:
+ *
+ * The red, green, and blue components are stored in sRGB space, but
+ * are linear, not gamma-encoded.
+ * The RGB primaries and the white point are the same as BT.709.
+ *
+ * The values are encoded using the full range ([0,255] for 8-bit) for all
+ * components.
+ */
+ HAL_DATASPACE_SRGB_LINEAR = 0x200,
+
+ /*
+ * sRGB gamma encoding:
+ *
+ * The red, green and blue components are stored in sRGB space, and
+ * converted to linear space when read, using the standard sRGB to linear
+ * equation:
+ *
+ * Clinear = Csrgb / 12.92 for Csrgb <= 0.04045
+ * = (Csrgb + 0.055 / 1.055)^2.4 for Csrgb > 0.04045
+ *
+ * When written the inverse transformation is performed:
+ *
+ * Csrgb = 12.92 * Clinear for Clinear <= 0.0031308
+ * = 1.055 * Clinear^(1/2.4) - 0.055 for Clinear > 0.0031308
+ *
+ *
+ * The alpha component, if present, is always stored in linear space and
+ * is left unmodified when read or written.
+ *
+ * The RGB primaries and the white point are the same as BT.709.
+ *
+ * The values are encoded using the full range ([0,255] for 8-bit) for all
+ * components.
+ *
+ */
+ HAL_DATASPACE_SRGB = 0x201,
/*
* YCbCr Colorspaces
@@ -429,7 +594,7 @@
* red 0.640 0.330
* white (D65) 0.3127 0.3290
*/
- HAL_COLORSPACE_JFIF = 0x101,
+ HAL_DATASPACE_JFIF = 0x101,
/*
* ITU-R Recommendation 601 (BT.601) - 625-line
@@ -456,7 +621,7 @@
* red 0.640 0.330
* white (D65) 0.3127 0.3290
*/
- HAL_COLORSPACE_BT601_625 = 0x102,
+ HAL_DATASPACE_BT601_625 = 0x102,
/*
* ITU-R Recommendation 601 (BT.601) - 525-line
@@ -483,7 +648,7 @@
* red 0.630 0.340
* white (D65) 0.3127 0.3290
*/
- HAL_COLORSPACE_BT601_525 = 0x103,
+ HAL_DATASPACE_BT601_525 = 0x103,
/*
* ITU-R Recommendation 709 (BT.709)
@@ -504,8 +669,20 @@
* red 0.640 0.330
* white (D65) 0.3127 0.3290
*/
- HAL_COLORSPACE_BT709 = 0x104,
-};
+ HAL_DATASPACE_BT709 = 0x104,
+
+ /*
+ * The buffer contains depth ranging measurements from a depth camera.
+ * This value is valid with formats:
+ * HAL_PIXEL_FORMAT_Y16: 16-bit single channel depth image.
+ * HAL_PIXEL_FORMAT_BLOB: A depth point cloud, as
+ * a variable-length float (x,y,z) coordinate point list.
+ * The point cloud will be represented with the android_depth_points
+ * structure.
+ */
+ HAL_DATASPACE_DEPTH = 0x1000
+
+} android_dataspace_t;
#ifdef __cplusplus
}
diff --git a/include/system/radio.h b/include/system/radio.h
new file mode 100644
index 0000000..a088526
--- /dev/null
+++ b/include/system/radio.h
@@ -0,0 +1,247 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_RADIO_H
+#define ANDROID_RADIO_H
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+
+#define RADIO_NUM_BANDS_MAX 16
+#define RADIO_NUM_SPACINGS_MAX 16
+#define RADIO_STRING_LEN_MAX 128
+
+/*
+ * Radio hardware module class. A given radio hardware module HAL is of one class
+ * only. The platform can not have more than one hardware module of each class.
+ * Current version of the framework only supports RADIO_CLASS_AM_FM.
+ */
+typedef enum {
+ RADIO_CLASS_AM_FM = 0, /* FM (including HD radio) and AM */
+ RADIO_CLASS_SAT = 1, /* Satellite Radio */
+ RADIO_CLASS_DT = 2, /* Digital Radio (DAB) */
+} radio_class_t;
+
+/* value for field "type" of radio band described in struct radio_hal_band_config */
+typedef enum {
+ RADIO_BAND_AM = 0, /* Amplitude Modulation band: LW, MW, SW */
+ RADIO_BAND_FM = 1, /* Frequency Modulation band: FM */
+ RADIO_BAND_FM_HD = 2, /* FM HD Radio / DRM (IBOC) */
+ RADIO_BAND_AM_HD = 3, /* AM HD Radio / DRM (IBOC) */
+} radio_band_t;
+
+/* RDS variant implemented. A struct radio_hal_fm_band_config can list none or several. */
+enum {
+ RADIO_RDS_NONE = 0x0,
+ RADIO_RDS_WORLD = 0x01,
+ RADIO_RDS_US = 0x02,
+};
+typedef unsigned int radio_rds_t;
+
+/* FM deemphasis variant implemented. A struct radio_hal_fm_band_config can list one or more. */
+enum {
+ RADIO_DEEMPHASIS_50 = 0x1,
+ RADIO_DEEMPHASIS_75 = 0x2,
+};
+typedef unsigned int radio_deemphasis_t;
+
+/* Region a particular radio band configuration corresponds to. Not used at the HAL.
+ * Derived by the framework when converting the band descriptors retrieved from the HAL to
+ * individual band descriptors for each supported region. */
+typedef enum {
+ RADIO_REGION_NONE = -1,
+ RADIO_REGION_ITU_1 = 0,
+ RADIO_REGION_ITU_2 = 1,
+ RADIO_REGION_OIRT = 2,
+ RADIO_REGION_JAPAN = 3,
+ RADIO_REGION_KOREA = 4,
+} radio_region_t;
+
+/* scanning direction for scan() and step() tuner APIs */
+typedef enum {
+ RADIO_DIRECTION_UP,
+ RADIO_DIRECTION_DOWN
+} radio_direction_t;
+
+/* unique handle allocated to a radio module */
+typedef unsigned int radio_handle_t;
+
+/* Opaque meta data structure used by radio meta data API (see system/radio_metadata.h) */
+typedef struct radio_medtadata radio_metadata_t;
+
+
+/* Additional attributes for an FM band configuration */
+typedef struct radio_hal_fm_band_config {
+ radio_deemphasis_t deemphasis; /* deemphasis variant */
+ bool stereo; /* stereo supported */
+ radio_rds_t rds; /* RDS variants supported */
+ bool ta; /* Traffic Announcement supported */
+ bool af; /* Alternate Frequency supported */
+} radio_hal_fm_band_config_t;
+
+/* Additional attributes for an AM band configuration */
+typedef struct radio_hal_am_band_config {
+ bool stereo; /* stereo supported */
+} radio_hal_am_band_config_t;
+
+/* Radio band configuration. Describes a given band supported by the radio module.
+ * The HAL can expose only one band per type with the the maximum range supported and all options.
+ * THe framework will derive the actual regions were this module can operate and expose separate
+ * band configurations for applications to chose from. */
+typedef struct radio_hal_band_config {
+ radio_band_t type;
+ bool antenna_connected;
+ unsigned int lower_limit;
+ unsigned int upper_limit;
+ unsigned int num_spacings;
+ unsigned int spacings[RADIO_NUM_SPACINGS_MAX];
+ union {
+ radio_hal_fm_band_config_t fm;
+ radio_hal_am_band_config_t am;
+ };
+} radio_hal_band_config_t;
+
+/* Used internally by the framework to represent a band for s specific region */
+typedef struct radio_band_config {
+ radio_region_t region;
+ radio_hal_band_config_t band;
+} radio_band_config_t;
+
+
+/* Exposes properties of a given hardware radio module.
+ * NOTE: current framework implementation supports only one audio source (num_audio_sources = 1).
+ * The source corresponds to AUDIO_DEVICE_IN_FM_TUNER.
+ * If more than one tuner is supported (num_tuners > 1), only one can be connected to the audio
+ * source. */
+typedef struct radio_hal_properties {
+ radio_class_t class_id; /* Class of this module. E.g RADIO_CLASS_AM_FM */
+ char implementor[RADIO_STRING_LEN_MAX]; /* implementor name */
+ char product[RADIO_STRING_LEN_MAX]; /* product name */
+ char version[RADIO_STRING_LEN_MAX]; /* product version */
+ char serial[RADIO_STRING_LEN_MAX]; /* serial number (for subscription services) */
+ unsigned int num_tuners; /* number of tuners controllable independently */
+ unsigned int num_audio_sources; /* number of audio sources driven simultaneously */
+ bool supports_capture; /* the hardware supports capture of audio source audio HAL */
+ unsigned int num_bands; /* number of band descriptors */
+ radio_hal_band_config_t bands[RADIO_NUM_BANDS_MAX]; /* band descriptors */
+} radio_hal_properties_t;
+
+/* Used internally by the framework. Same information as in struct radio_hal_properties plus a
+ * unique handle and one band configuration per region. */
+typedef struct radio_properties {
+ radio_handle_t handle;
+ radio_class_t class_id;
+ char implementor[RADIO_STRING_LEN_MAX];
+ char product[RADIO_STRING_LEN_MAX];
+ char version[RADIO_STRING_LEN_MAX];
+ char serial[RADIO_STRING_LEN_MAX];
+ unsigned int num_tuners;
+ unsigned int num_audio_sources;
+ bool supports_capture;
+ unsigned int num_bands;
+ radio_band_config_t bands[RADIO_NUM_BANDS_MAX];
+} radio_properties_t;
+
+/* Radio program information. Returned by the HAL with event RADIO_EVENT_TUNED.
+ * Contains information on currently tuned channel.
+ */
+typedef struct radio_program_info {
+ unsigned int channel; /* current channel. (e.g kHz for band type RADIO_BAND_FM) */
+ unsigned int sub_channel; /* current sub channel. (used for RADIO_BAND_FM_HD) */
+ bool tuned; /* tuned to a program or not */
+ bool stereo; /* program is stereo or not */
+ bool digital; /* digital program or not (e.g HD Radio program) */
+ unsigned int signal_strength; /* signal strength from 0 to 100 */
+ radio_metadata_t *metadata; /* non null if meta data are present (e.g PTY, song title ...) */
+} radio_program_info_t;
+
+
+/* Events sent to the framework via the HAL callback. An event can notify the completion of an
+ * asynchronous command (configuration, tune, scan ...) or a spontaneous change (antenna connection,
+ * failure, AF switching, meta data reception... */
+enum {
+ RADIO_EVENT_HW_FAILURE = 0, /* hardware module failure. Requires reopening the tuner */
+ RADIO_EVENT_CONFIG = 1, /* configuration change completed */
+ RADIO_EVENT_ANTENNA = 2, /* Antenna connected, disconnected */
+ RADIO_EVENT_TUNED = 3, /* tune, step, scan completed */
+ RADIO_EVENT_METADATA = 4, /* New meta data received */
+ RADIO_EVENT_TA = 5, /* Traffic announcement start or stop */
+ RADIO_EVENT_AF_SWITCH = 6, /* Switch to Alternate Frequency */
+ // begin framework only events
+ RADIO_EVENT_CONTROL = 100, /* loss/gain of tuner control */
+ RADIO_EVENT_SERVER_DIED = 101, /* radio service died */
+};
+typedef unsigned int radio_event_type_t;
+
+/* Event passed to the framework by the HAL callback */
+typedef struct radio_hal_event {
+ radio_event_type_t type; /* event type */
+ int status; /* used by RADIO_EVENT_CONFIG, RADIO_EVENT_TUNED */
+ union {
+ bool on; /* RADIO_EVENT_ANTENNA, RADIO_EVENT_TA */
+ radio_hal_band_config_t config; /* RADIO_EVENT_CONFIG */
+ radio_program_info_t info; /* RADIO_EVENT_TUNED, RADIO_EVENT_AF_SWITCH */
+ radio_metadata_t *metadata; /* RADIO_EVENT_METADATA */
+ };
+} radio_hal_event_t;
+
+/* Used internally by the framework. Same information as in struct radio_hal_event */
+typedef struct radio_event {
+ radio_event_type_t type;
+ int status;
+ union {
+ bool on;
+ radio_band_config_t config;
+ radio_program_info_t info;
+ radio_metadata_t *metadata; /* offset from start of struct when in shared memory */
+ };
+} radio_event_t;
+
+
+static radio_rds_t radio_rds_for_region(bool rds, radio_region_t region) {
+ if (!rds)
+ return RADIO_RDS_NONE;
+ switch(region) {
+ case RADIO_REGION_ITU_1:
+ case RADIO_REGION_OIRT:
+ case RADIO_REGION_JAPAN:
+ case RADIO_REGION_KOREA:
+ return RADIO_RDS_WORLD;
+ case RADIO_REGION_ITU_2:
+ return RADIO_RDS_US;
+ default:
+ return RADIO_REGION_NONE;
+ }
+}
+
+static radio_deemphasis_t radio_demephasis_for_region(radio_region_t region) {
+ switch(region) {
+ case RADIO_REGION_KOREA:
+ case RADIO_REGION_ITU_2:
+ return RADIO_DEEMPHASIS_75;
+ case RADIO_REGION_ITU_1:
+ case RADIO_REGION_OIRT:
+ case RADIO_REGION_JAPAN:
+ default:
+ return RADIO_DEEMPHASIS_50;
+ }
+}
+
+#endif // ANDROID_RADIO_H
diff --git a/include/system/window.h b/include/system/window.h
index bf93b79..af0418b 100644
--- a/include/system/window.h
+++ b/include/system/window.h
@@ -262,6 +262,12 @@
* the aspect ratio of the buffers produced.
*/
NATIVE_WINDOW_STICKY_TRANSFORM = 11,
+
+ /**
+ * The default data space for the buffers as set by the consumer.
+ * The values are defined in graphics.h.
+ */
+ NATIVE_WINDOW_DEFAULT_DATASPACE = 12
};
/* Valid operations for the (*perform)() hook.
@@ -294,6 +300,7 @@
NATIVE_WINDOW_SET_POST_TRANSFORM_CROP = 16, /* private */
NATIVE_WINDOW_SET_BUFFERS_STICKY_TRANSFORM = 17,/* private */
NATIVE_WINDOW_SET_SIDEBAND_STREAM = 18,
+ NATIVE_WINDOW_SET_BUFFERS_DATASPACE = 19
};
/* parameter for NATIVE_WINDOW_[API_][DIS]CONNECT */
@@ -498,6 +505,7 @@
* NATIVE_WINDOW_SET_BUFFERS_GEOMETRY (deprecated)
* NATIVE_WINDOW_SET_BUFFERS_TRANSFORM
* NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP
+ * NATIVE_WINDOW_SET_BUFFERS_DATASPACE
* NATIVE_WINDOW_SET_BUFFERS_DIMENSIONS
* NATIVE_WINDOW_SET_BUFFERS_FORMAT
* NATIVE_WINDOW_SET_SCALING_MODE (private)
@@ -799,6 +807,26 @@
}
/*
+ * native_window_set_buffers_data_space(..., int dataSpace)
+ * All buffers queued after this call will be associated with the dataSpace
+ * parameter specified.
+ *
+ * dataSpace specifies additional information about the buffer that's dependent
+ * on the buffer format and the endpoints. For example, it can be used to convey
+ * the color space of the image data in the buffer, or it can be used to
+ * indicate that the buffers contain depth measurement data instead of color
+ * images. The default dataSpace is 0, HAL_DATASPACE_UNKNOWN, unless it has been
+ * overridden by the consumer.
+ */
+static inline int native_window_set_buffers_data_space(
+ struct ANativeWindow* window,
+ android_dataspace_t dataSpace)
+{
+ return window->perform(window, NATIVE_WINDOW_SET_BUFFERS_DATASPACE,
+ dataSpace);
+}
+
+/*
* native_window_set_buffers_transform(..., int transform)
* All buffers queued after this call will be displayed transformed according
* to the transform parameter specified.
diff --git a/include/sysutils/NetlinkEvent.h b/include/sysutils/NetlinkEvent.h
index 4fa49c5..b80f3ea 100644
--- a/include/sysutils/NetlinkEvent.h
+++ b/include/sysutils/NetlinkEvent.h
@@ -21,25 +21,29 @@
#define NL_PARAMS_MAX 32
class NetlinkEvent {
+public:
+ enum class Action {
+ kUnknown = 0,
+ kAdd = 1,
+ kRemove = 2,
+ kChange = 3,
+ kLinkUp = 4,
+ kLinkDown = 5,
+ kAddressUpdated = 6,
+ kAddressRemoved = 7,
+ kRdnss = 8,
+ kRouteUpdated = 9,
+ kRouteRemoved = 10,
+ };
+
+private:
int mSeq;
char *mPath;
- int mAction;
+ Action mAction;
char *mSubsystem;
char *mParams[NL_PARAMS_MAX];
public:
- const static int NlActionUnknown;
- const static int NlActionAdd;
- const static int NlActionRemove;
- const static int NlActionChange;
- const static int NlActionLinkDown;
- const static int NlActionLinkUp;
- const static int NlActionAddressUpdated;
- const static int NlActionAddressRemoved;
- const static int NlActionRdnss;
- const static int NlActionRouteUpdated;
- const static int NlActionRouteRemoved;
-
NetlinkEvent();
virtual ~NetlinkEvent();
@@ -47,7 +51,7 @@
const char *findParam(const char *paramName);
const char *getSubsystem() { return mSubsystem; }
- int getAction() { return mAction; }
+ Action getAction() { return mAction; }
void dump();
diff --git a/include/utils/Looper.h b/include/utils/Looper.h
index 15c9891..da2d5f2 100644
--- a/include/utils/Looper.h
+++ b/include/utils/Looper.h
@@ -386,11 +386,12 @@
void removeMessages(const sp<MessageHandler>& handler, int what);
/**
- * Return whether this looper's thread is currently idling -- that is, whether it
- * stopped waiting for more work to do. Note that this is intrinsically racy, since
- * its state can change before you get the result back.
+ * Returns whether this looper's thread is currently polling for more work to do.
+ * This is a good signal that the loop is still alive rather than being stuck
+ * handling a callback. Note that this method is intrinsically racy, since the
+ * state of the loop can change before you get the result back.
*/
- bool isIdling() const;
+ bool isPolling() const;
/**
* Prepares a looper associated with the calling thread, and returns it.
@@ -419,8 +420,12 @@
struct Request {
int fd;
int ident;
+ int events;
+ int seq;
sp<LooperCallback> callback;
void* data;
+
+ void initEventItem(struct epoll_event* eventItem) const;
};
struct Response {
@@ -442,8 +447,7 @@
const bool mAllowNonCallbacks; // immutable
- int mWakeReadPipeFd; // immutable
- int mWakeWritePipeFd; // immutable
+ int mWakeEventFd; // immutable
Mutex mLock;
Vector<MessageEnvelope> mMessageEnvelopes; // guarded by mLock
@@ -451,12 +455,14 @@
// Whether we are currently waiting for work. Not protected by a lock,
// any use of it is racy anyway.
- volatile bool mIdling;
+ volatile bool mPolling;
- int mEpollFd; // immutable
+ int mEpollFd; // guarded by mLock but only modified on the looper thread
+ bool mEpollRebuildRequired; // guarded by mLock
// Locked list of file descriptor monitoring requests.
KeyedVector<int, Request> mRequests; // guarded by mLock
+ int mNextRequestSeq;
// This state is only used privately by pollOnce and does not require a lock since
// it runs on a single thread.
@@ -465,11 +471,15 @@
nsecs_t mNextMessageUptime; // set to LLONG_MAX when none
int pollInner(int timeoutMillis);
+ int removeFd(int fd, int seq);
void awoken();
void pushResponse(int events, const Request& request);
+ void rebuildEpollLocked();
+ void scheduleEpollRebuildLocked();
static void initTLSKey();
static void threadDestructor(void *st);
+ static void initEpollEvent(struct epoll_event* eventItem);
};
} // namespace android
diff --git a/libion/ion.c b/libion/ion.c
index 4908932..d1984bd 100644
--- a/libion/ion.c
+++ b/libion/ion.c
@@ -91,6 +91,7 @@
int flags, off_t offset, unsigned char **ptr, int *map_fd)
{
int ret;
+ unsigned char *tmp_ptr;
struct ion_fd_data data = {
.handle = handle,
};
@@ -103,16 +104,17 @@
ret = ion_ioctl(fd, ION_IOC_MAP, &data);
if (ret < 0)
return ret;
- *map_fd = data.fd;
- if (*map_fd < 0) {
+ if (data.fd < 0) {
ALOGE("map ioctl returned negative fd\n");
return -EINVAL;
}
- *ptr = mmap(NULL, length, prot, flags, *map_fd, offset);
- if (*ptr == MAP_FAILED) {
+ tmp_ptr = mmap(NULL, length, prot, flags, data.fd, offset);
+ if (tmp_ptr == MAP_FAILED) {
ALOGE("mmap failed: %s\n", strerror(errno));
return -errno;
}
+ *map_fd = data.fd;
+ *ptr = tmp_ptr;
return ret;
}
@@ -129,11 +131,11 @@
ret = ion_ioctl(fd, ION_IOC_SHARE, &data);
if (ret < 0)
return ret;
- *share_fd = data.fd;
- if (*share_fd < 0) {
+ if (data.fd < 0) {
ALOGE("share ioctl returned negative fd\n");
return -EINVAL;
}
+ *share_fd = data.fd;
return ret;
}
diff --git a/libnetutils/dhcp_utils.c b/libnetutils/dhcp_utils.c
index 70e37c6..c6b9fe4 100644
--- a/libnetutils/dhcp_utils.c
+++ b/libnetutils/dhcp_utils.c
@@ -1,16 +1,16 @@
/*
* Copyright 2008, The Android Open Source Project
*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
*
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
* limitations under the License.
*/
@@ -33,7 +33,7 @@
static const int NAP_TIME = 200; /* wait for 200ms at a time */
/* when polling for property values */
static const char DAEMON_NAME_RENEW[] = "iprenew";
-static char errmsg[100];
+static char errmsg[100] = "\0";
/* interface length for dhcpcd daemon start (dhcpcd_<interface> as defined in init.rc file)
* or for filling up system properties dhcpcd.<interface>.ipaddress, dhcpcd.<interface>.dns1
* and other properties on a successful bind
@@ -74,7 +74,7 @@
while (maxnaps-- >= 0) {
if (property_get(name, value, NULL)) {
- if (desired_value == NULL ||
+ if (desired_value == NULL ||
strcmp(value, desired_value) == 0) {
return 0;
}
@@ -169,6 +169,47 @@
}
/*
+ * Get any available DHCP results.
+ */
+int dhcp_get_results(const char *interface,
+ char *ipaddr,
+ char *gateway,
+ uint32_t *prefixLength,
+ char *dns[],
+ char *server,
+ uint32_t *lease,
+ char *vendorInfo,
+ char *domain,
+ char *mtu)
+{
+ char result_prop_name[PROPERTY_KEY_MAX];
+ char prop_value[PROPERTY_VALUE_MAX];
+
+ /* Interface name after converting p2p0-p2p0-X to p2p to reuse system properties */
+ char p2p_interface[MAX_INTERFACE_LENGTH];
+ get_p2p_interface_replacement(interface, p2p_interface);
+ snprintf(result_prop_name, sizeof(result_prop_name), "%s.%s.result",
+ DHCP_PROP_NAME_PREFIX,
+ p2p_interface);
+
+ memset(prop_value, '\0', PROPERTY_VALUE_MAX);
+ if (!property_get(result_prop_name, prop_value, NULL)) {
+ snprintf(errmsg, sizeof(errmsg), "%s", "DHCP result property was not set");
+ return -1;
+ }
+ if (strcmp(prop_value, "ok") == 0) {
+ if (fill_ip_info(interface, ipaddr, gateway, prefixLength, dns,
+ server, lease, vendorInfo, domain, mtu) == -1) {
+ return -1;
+ }
+ return 0;
+ } else {
+ snprintf(errmsg, sizeof(errmsg), "DHCP result was %s", prop_value);
+ return -1;
+ }
+}
+
+/*
* Start the dhcp client daemon, and wait for it to finish
* configuring the interface.
*
@@ -177,16 +218,7 @@
* Example:
* service dhcpcd_<interface> /system/bin/dhcpcd -ABKL -f dhcpcd.conf
*/
-int dhcp_do_request(const char *interface,
- char *ipaddr,
- char *gateway,
- uint32_t *prefixLength,
- char *dns[],
- char *server,
- uint32_t *lease,
- char *vendorInfo,
- char *domain,
- char *mtu)
+int dhcp_start(const char *interface)
{
char result_prop_name[PROPERTY_KEY_MAX];
char daemon_prop_name[PROPERTY_KEY_MAX];
@@ -230,21 +262,7 @@
return -1;
}
- if (!property_get(result_prop_name, prop_value, NULL)) {
- /* shouldn't ever happen, given the success of wait_for_property() */
- snprintf(errmsg, sizeof(errmsg), "%s", "DHCP result property was not set");
- return -1;
- }
- if (strcmp(prop_value, "ok") == 0) {
- if (fill_ip_info(interface, ipaddr, gateway, prefixLength, dns,
- server, lease, vendorInfo, domain, mtu) == -1) {
- return -1;
- }
- return 0;
- } else {
- snprintf(errmsg, sizeof(errmsg), "DHCP result was %s", prop_value);
- return -1;
- }
+ return 0;
}
/**
@@ -320,16 +338,7 @@
* service iprenew_<interface> /system/bin/dhcpcd -n
*
*/
-int dhcp_do_request_renew(const char *interface,
- char *ipaddr,
- char *gateway,
- uint32_t *prefixLength,
- char *dns[],
- char *server,
- uint32_t *lease,
- char *vendorInfo,
- char *domain,
- char *mtu)
+int dhcp_start_renew(const char *interface)
{
char result_prop_name[PROPERTY_KEY_MAX];
char prop_value[PROPERTY_VALUE_MAX] = {'\0'};
@@ -359,16 +368,5 @@
return -1;
}
- if (!property_get(result_prop_name, prop_value, NULL)) {
- /* shouldn't ever happen, given the success of wait_for_property() */
- snprintf(errmsg, sizeof(errmsg), "%s", "DHCP Renew result property was not set");
- return -1;
- }
- if (strcmp(prop_value, "ok") == 0) {
- return fill_ip_info(interface, ipaddr, gateway, prefixLength, dns,
- server, lease, vendorInfo, domain, mtu);
- } else {
- snprintf(errmsg, sizeof(errmsg), "DHCP Renew result was %s", prop_value);
- return -1;
- }
+ return 0;
}
diff --git a/libsysutils/src/NetlinkEvent.cpp b/libsysutils/src/NetlinkEvent.cpp
index 909df86..ef30017 100644
--- a/libsysutils/src/NetlinkEvent.cpp
+++ b/libsysutils/src/NetlinkEvent.cpp
@@ -47,20 +47,8 @@
#include <netlink/handlers.h>
#include <netlink/msg.h>
-const int NetlinkEvent::NlActionUnknown = 0;
-const int NetlinkEvent::NlActionAdd = 1;
-const int NetlinkEvent::NlActionRemove = 2;
-const int NetlinkEvent::NlActionChange = 3;
-const int NetlinkEvent::NlActionLinkUp = 4;
-const int NetlinkEvent::NlActionLinkDown = 5;
-const int NetlinkEvent::NlActionAddressUpdated = 6;
-const int NetlinkEvent::NlActionAddressRemoved = 7;
-const int NetlinkEvent::NlActionRdnss = 8;
-const int NetlinkEvent::NlActionRouteUpdated = 9;
-const int NetlinkEvent::NlActionRouteRemoved = 10;
-
NetlinkEvent::NetlinkEvent() {
- mAction = NlActionUnknown;
+ mAction = Action::kUnknown;
memset(mParams, 0, sizeof(mParams));
mPath = NULL;
mSubsystem = NULL;
@@ -154,8 +142,8 @@
switch(rta->rta_type) {
case IFLA_IFNAME:
asprintf(&mParams[0], "INTERFACE=%s", (char *) RTA_DATA(rta));
- mAction = (ifi->ifi_flags & IFF_LOWER_UP) ? NlActionLinkUp :
- NlActionLinkDown;
+ mAction = (ifi->ifi_flags & IFF_LOWER_UP) ? Action::kLinkUp :
+ Action::kLinkDown;
mSubsystem = strdup("net");
return true;
}
@@ -244,8 +232,8 @@
}
// Fill in netlink event information.
- mAction = (type == RTM_NEWADDR) ? NlActionAddressUpdated :
- NlActionAddressRemoved;
+ mAction = (type == RTM_NEWADDR) ? Action::kAddressUpdated :
+ Action::kAddressRemoved;
mSubsystem = strdup("net");
asprintf(&mParams[0], "ADDRESS=%s/%d", addrstr,
ifaddr->ifa_prefixlen);
@@ -276,7 +264,7 @@
asprintf(&mParams[0], "ALERT_NAME=%s", pm->prefix);
asprintf(&mParams[1], "INTERFACE=%s", devname);
mSubsystem = strdup("qlog");
- mAction = NlActionChange;
+ mAction = Action::kChange;
return true;
}
@@ -311,7 +299,7 @@
asprintf(&mParams[0], "UID=%d", uid);
mParams[1] = hex;
mSubsystem = strdup("strict");
- mAction = NlActionChange;
+ mAction = Action::kChange;
return true;
}
@@ -397,8 +385,8 @@
return false;
// Fill in netlink event information.
- mAction = (type == RTM_NEWROUTE) ? NlActionRouteUpdated :
- NlActionRouteRemoved;
+ mAction = (type == RTM_NEWROUTE) ? Action::kRouteUpdated :
+ Action::kRouteRemoved;
mSubsystem = strdup("net");
asprintf(&mParams[0], "ROUTE=%s/%d", dst, prefixLength);
asprintf(&mParams[1], "GATEWAY=%s", (*gw) ? gw : "");
@@ -497,7 +485,7 @@
}
buf[pos] = '\0';
- mAction = NlActionRdnss;
+ mAction = Action::kRdnss;
mSubsystem = strdup("net");
asprintf(&mParams[0], "INTERFACE=%s", ifname);
asprintf(&mParams[1], "LIFETIME=%u", lifetime);
@@ -617,11 +605,11 @@
const char* a;
if ((a = HAS_CONST_PREFIX(s, end, "ACTION=")) != NULL) {
if (!strcmp(a, "add"))
- mAction = NlActionAdd;
+ mAction = Action::kAdd;
else if (!strcmp(a, "remove"))
- mAction = NlActionRemove;
+ mAction = Action::kRemove;
else if (!strcmp(a, "change"))
- mAction = NlActionChange;
+ mAction = Action::kChange;
} else if ((a = HAS_CONST_PREFIX(s, end, "SEQNUM=")) != NULL) {
mSeq = atoi(a);
} else if ((a = HAS_CONST_PREFIX(s, end, "SUBSYSTEM=")) != NULL) {
diff --git a/libsysutils/src/SocketListener.cpp b/libsysutils/src/SocketListener.cpp
index 527a6a0..3011ed7 100644
--- a/libsysutils/src/SocketListener.cpp
+++ b/libsysutils/src/SocketListener.cpp
@@ -86,6 +86,7 @@
return -1;
}
SLOGV("got mSock = %d for %s", mSock, mSocketName);
+ fcntl(mSock, F_SETFD, FD_CLOEXEC);
}
if (mListen && listen(mSock, backlog) < 0) {
@@ -212,6 +213,7 @@
sleep(1);
continue;
}
+ fcntl(c, F_SETFD, FD_CLOEXEC);
pthread_mutex_lock(&mClientsLock);
mClients->push_back(new SocketClient(c, true, mUseCmdNum));
pthread_mutex_unlock(&mClientsLock);
diff --git a/libutils/Looper.cpp b/libutils/Looper.cpp
index 9a2dd6c..e69784d 100644
--- a/libutils/Looper.cpp
+++ b/libutils/Looper.cpp
@@ -20,6 +20,8 @@
#include <unistd.h>
#include <fcntl.h>
#include <limits.h>
+#include <inttypes.h>
+#include <sys/eventfd.h>
namespace android {
@@ -68,41 +70,20 @@
Looper::Looper(bool allowNonCallbacks) :
mAllowNonCallbacks(allowNonCallbacks), mSendingMessage(false),
- mResponseIndex(0), mNextMessageUptime(LLONG_MAX) {
- int wakeFds[2];
- int result = pipe(wakeFds);
- LOG_ALWAYS_FATAL_IF(result != 0, "Could not create wake pipe. errno=%d", errno);
+ mPolling(false), mEpollFd(-1), mEpollRebuildRequired(false),
+ mNextRequestSeq(0), mResponseIndex(0), mNextMessageUptime(LLONG_MAX) {
+ mWakeEventFd = eventfd(0, EFD_NONBLOCK);
+ LOG_ALWAYS_FATAL_IF(mWakeEventFd < 0, "Could not make wake event fd. errno=%d", errno);
- mWakeReadPipeFd = wakeFds[0];
- mWakeWritePipeFd = wakeFds[1];
-
- result = fcntl(mWakeReadPipeFd, F_SETFL, O_NONBLOCK);
- LOG_ALWAYS_FATAL_IF(result != 0, "Could not make wake read pipe non-blocking. errno=%d",
- errno);
-
- result = fcntl(mWakeWritePipeFd, F_SETFL, O_NONBLOCK);
- LOG_ALWAYS_FATAL_IF(result != 0, "Could not make wake write pipe non-blocking. errno=%d",
- errno);
-
- mIdling = false;
-
- // Allocate the epoll instance and register the wake pipe.
- mEpollFd = epoll_create(EPOLL_SIZE_HINT);
- LOG_ALWAYS_FATAL_IF(mEpollFd < 0, "Could not create epoll instance. errno=%d", errno);
-
- struct epoll_event eventItem;
- memset(& eventItem, 0, sizeof(epoll_event)); // zero out unused members of data field union
- eventItem.events = EPOLLIN;
- eventItem.data.fd = mWakeReadPipeFd;
- result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeReadPipeFd, & eventItem);
- LOG_ALWAYS_FATAL_IF(result != 0, "Could not add wake read pipe to epoll instance. errno=%d",
- errno);
+ AutoMutex _l(mLock);
+ rebuildEpollLocked();
}
Looper::~Looper() {
- close(mWakeReadPipeFd);
- close(mWakeWritePipeFd);
- close(mEpollFd);
+ close(mWakeEventFd);
+ if (mEpollFd >= 0) {
+ close(mEpollFd);
+ }
}
void Looper::initTLSKey() {
@@ -156,6 +137,50 @@
return mAllowNonCallbacks;
}
+void Looper::rebuildEpollLocked() {
+ // Close old epoll instance if we have one.
+ if (mEpollFd >= 0) {
+#if DEBUG_CALLBACKS
+ ALOGD("%p ~ rebuildEpollLocked - rebuilding epoll set", this);
+#endif
+ close(mEpollFd);
+ }
+
+ // Allocate the new epoll instance and register the wake pipe.
+ mEpollFd = epoll_create(EPOLL_SIZE_HINT);
+ LOG_ALWAYS_FATAL_IF(mEpollFd < 0, "Could not create epoll instance. errno=%d", errno);
+
+ struct epoll_event eventItem;
+ memset(& eventItem, 0, sizeof(epoll_event)); // zero out unused members of data field union
+ eventItem.events = EPOLLIN;
+ eventItem.data.fd = mWakeEventFd;
+ int result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeEventFd, & eventItem);
+ LOG_ALWAYS_FATAL_IF(result != 0, "Could not add wake event fd to epoll instance. errno=%d",
+ errno);
+
+ for (size_t i = 0; i < mRequests.size(); i++) {
+ const Request& request = mRequests.valueAt(i);
+ struct epoll_event eventItem;
+ request.initEventItem(&eventItem);
+
+ int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, request.fd, & eventItem);
+ if (epollResult < 0) {
+ ALOGE("Error adding epoll events for fd %d while rebuilding epoll set, errno=%d",
+ request.fd, errno);
+ }
+ }
+}
+
+void Looper::scheduleEpollRebuildLocked() {
+ if (!mEpollRebuildRequired) {
+#if DEBUG_CALLBACKS
+ ALOGD("%p ~ scheduleEpollRebuildLocked - scheduling epoll set rebuild", this);
+#endif
+ mEpollRebuildRequired = true;
+ wake();
+ }
+}
+
int Looper::pollOnce(int timeoutMillis, int* outFd, int* outEvents, void** outData) {
int result = 0;
for (;;) {
@@ -206,7 +231,7 @@
timeoutMillis = messageTimeoutMillis;
}
#if DEBUG_POLL_AND_WAKE
- ALOGD("%p ~ pollOnce - next message in %lldns, adjusted timeout: timeoutMillis=%d",
+ ALOGD("%p ~ pollOnce - next message in %" PRId64 "ns, adjusted timeout: timeoutMillis=%d",
this, mNextMessageUptime - now, timeoutMillis);
#endif
}
@@ -217,17 +242,24 @@
mResponseIndex = 0;
// We are about to idle.
- mIdling = true;
+ mPolling = true;
struct epoll_event eventItems[EPOLL_MAX_EVENTS];
int eventCount = epoll_wait(mEpollFd, eventItems, EPOLL_MAX_EVENTS, timeoutMillis);
// No longer idling.
- mIdling = false;
+ mPolling = false;
// Acquire lock.
mLock.lock();
+ // Rebuild epoll set if needed.
+ if (mEpollRebuildRequired) {
+ mEpollRebuildRequired = false;
+ rebuildEpollLocked();
+ goto Done;
+ }
+
// Check for poll error.
if (eventCount < 0) {
if (errno == EINTR) {
@@ -255,11 +287,11 @@
for (int i = 0; i < eventCount; i++) {
int fd = eventItems[i].data.fd;
uint32_t epollEvents = eventItems[i].events;
- if (fd == mWakeReadPipeFd) {
+ if (fd == mWakeEventFd) {
if (epollEvents & EPOLLIN) {
awoken();
} else {
- ALOGW("Ignoring unexpected epoll events 0x%x on wake read pipe.", epollEvents);
+ ALOGW("Ignoring unexpected epoll events 0x%x on wake event fd.", epollEvents);
}
} else {
ssize_t requestIndex = mRequests.indexOfKey(fd);
@@ -326,10 +358,14 @@
ALOGD("%p ~ pollOnce - invoking fd event callback %p: fd=%d, events=0x%x, data=%p",
this, response.request.callback.get(), fd, events, data);
#endif
+ // Invoke the callback. Note that the file descriptor may be closed by
+ // the callback (and potentially even reused) before the function returns so
+ // we need to be a little careful when removing the file descriptor afterwards.
int callbackResult = response.request.callback->handleEvent(fd, events, data);
if (callbackResult == 0) {
- removeFd(fd);
+ removeFd(fd, response.request.seq);
}
+
// Clear the callback reference in the response structure promptly because we
// will not clear the response vector itself until the next poll.
response.request.callback.clear();
@@ -370,12 +406,9 @@
ALOGD("%p ~ wake", this);
#endif
- ssize_t nWrite;
- do {
- nWrite = write(mWakeWritePipeFd, "W", 1);
- } while (nWrite == -1 && errno == EINTR);
-
- if (nWrite != 1) {
+ uint64_t inc = 1;
+ ssize_t nWrite = TEMP_FAILURE_RETRY(write(mWakeEventFd, &inc, sizeof(uint64_t)));
+ if (nWrite != sizeof(uint64_t)) {
if (errno != EAGAIN) {
ALOGW("Could not write wake signal, errno=%d", errno);
}
@@ -387,11 +420,8 @@
ALOGD("%p ~ awoken", this);
#endif
- char buffer[16];
- ssize_t nRead;
- do {
- nRead = read(mWakeReadPipeFd, buffer, sizeof(buffer));
- } while ((nRead == -1 && errno == EINTR) || nRead == sizeof(buffer));
+ uint64_t counter;
+ TEMP_FAILURE_RETRY(read(mWakeEventFd, &counter, sizeof(uint64_t)));
}
void Looper::pushResponse(int events, const Request& request) {
@@ -425,23 +455,20 @@
ident = POLL_CALLBACK;
}
- int epollEvents = 0;
- if (events & EVENT_INPUT) epollEvents |= EPOLLIN;
- if (events & EVENT_OUTPUT) epollEvents |= EPOLLOUT;
-
{ // acquire lock
AutoMutex _l(mLock);
Request request;
request.fd = fd;
request.ident = ident;
+ request.events = events;
+ request.seq = mNextRequestSeq++;
request.callback = callback;
request.data = data;
+ if (mNextRequestSeq == -1) mNextRequestSeq = 0; // reserve sequence number -1
struct epoll_event eventItem;
- memset(& eventItem, 0, sizeof(epoll_event)); // zero out unused members of data field union
- eventItem.events = epollEvents;
- eventItem.data.fd = fd;
+ request.initEventItem(&eventItem);
ssize_t requestIndex = mRequests.indexOfKey(fd);
if (requestIndex < 0) {
@@ -454,8 +481,36 @@
} else {
int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_MOD, fd, & eventItem);
if (epollResult < 0) {
- ALOGE("Error modifying epoll events for fd %d, errno=%d", fd, errno);
- return -1;
+ if (errno == ENOENT) {
+ // Tolerate ENOENT because it means that an older file descriptor was
+ // closed before its callback was unregistered and meanwhile a new
+ // file descriptor with the same number has been created and is now
+ // being registered for the first time. This error may occur naturally
+ // when a callback has the side-effect of closing the file descriptor
+ // before returning and unregistering itself. Callback sequence number
+ // checks further ensure that the race is benign.
+ //
+ // Unfortunately due to kernel limitations we need to rebuild the epoll
+ // set from scratch because it may contain an old file handle that we are
+ // now unable to remove since its file descriptor is no longer valid.
+ // No such problem would have occurred if we were using the poll system
+ // call instead, but that approach carries others disadvantages.
+#if DEBUG_CALLBACKS
+ ALOGD("%p ~ addFd - EPOLL_CTL_MOD failed due to file descriptor "
+ "being recycled, falling back on EPOLL_CTL_ADD, errno=%d",
+ this, errno);
+#endif
+ epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, fd, & eventItem);
+ if (epollResult < 0) {
+ ALOGE("Error modifying or adding epoll events for fd %d, errno=%d",
+ fd, errno);
+ return -1;
+ }
+ scheduleEpollRebuildLocked();
+ } else {
+ ALOGE("Error modifying epoll events for fd %d, errno=%d", fd, errno);
+ return -1;
+ }
}
mRequests.replaceValueAt(requestIndex, request);
}
@@ -464,8 +519,12 @@
}
int Looper::removeFd(int fd) {
+ return removeFd(fd, -1);
+}
+
+int Looper::removeFd(int fd, int seq) {
#if DEBUG_CALLBACKS
- ALOGD("%p ~ removeFd - fd=%d", this, fd);
+ ALOGD("%p ~ removeFd - fd=%d, seq=%d", this, fd, seq);
#endif
{ // acquire lock
@@ -475,13 +534,43 @@
return 0;
}
- int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_DEL, fd, NULL);
- if (epollResult < 0) {
- ALOGE("Error removing epoll events for fd %d, errno=%d", fd, errno);
- return -1;
+ // Check the sequence number if one was given.
+ if (seq != -1 && mRequests.valueAt(requestIndex).seq != seq) {
+#if DEBUG_CALLBACKS
+ ALOGD("%p ~ removeFd - sequence number mismatch, oldSeq=%d",
+ this, mRequests.valueAt(requestIndex).seq);
+#endif
+ return 0;
}
+ // Always remove the FD from the request map even if an error occurs while
+ // updating the epoll set so that we avoid accidentally leaking callbacks.
mRequests.removeItemsAt(requestIndex);
+
+ int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_DEL, fd, NULL);
+ if (epollResult < 0) {
+ if (seq != -1 && (errno == EBADF || errno == ENOENT)) {
+ // Tolerate EBADF or ENOENT when the sequence number is known because it
+ // means that the file descriptor was closed before its callback was
+ // unregistered. This error may occur naturally when a callback has the
+ // side-effect of closing the file descriptor before returning and
+ // unregistering itself.
+ //
+ // Unfortunately due to kernel limitations we need to rebuild the epoll
+ // set from scratch because it may contain an old file handle that we are
+ // now unable to remove since its file descriptor is no longer valid.
+ // No such problem would have occurred if we were using the poll system
+ // call instead, but that approach carries others disadvantages.
+#if DEBUG_CALLBACKS
+ ALOGD("%p ~ removeFd - EPOLL_CTL_DEL failed due to file descriptor "
+ "being closed, errno=%d", this, errno);
+#endif
+ scheduleEpollRebuildLocked();
+ } else {
+ ALOGE("Error removing epoll events for fd %d, errno=%d", fd, errno);
+ return -1;
+ }
+ }
} // release lock
return 1;
}
@@ -500,7 +589,7 @@
void Looper::sendMessageAtTime(nsecs_t uptime, const sp<MessageHandler>& handler,
const Message& message) {
#if DEBUG_CALLBACKS
- ALOGD("%p ~ sendMessageAtTime - uptime=%lld, handler=%p, what=%d",
+ ALOGD("%p ~ sendMessageAtTime - uptime=%" PRId64 ", handler=%p, what=%d",
this, uptime, handler.get(), message.what);
#endif
@@ -566,8 +655,18 @@
} // release lock
}
-bool Looper::isIdling() const {
- return mIdling;
+bool Looper::isPolling() const {
+ return mPolling;
+}
+
+void Looper::Request::initEventItem(struct epoll_event* eventItem) const {
+ int epollEvents = 0;
+ if (events & EVENT_INPUT) epollEvents |= EPOLLIN;
+ if (events & EVENT_OUTPUT) epollEvents |= EPOLLOUT;
+
+ memset(eventItem, 0, sizeof(epoll_event)); // zero out unused members of data field union
+ eventItem->events = epollEvents;
+ eventItem->data.fd = fd;
}
} // namespace android
diff --git a/logwrapper/logwrap.c b/logwrapper/logwrap.c
index 3a6276e..83576fb 100644
--- a/logwrapper/logwrap.c
+++ b/logwrapper/logwrap.c
@@ -325,7 +325,7 @@
if (log_target & LOG_KLOG) {
snprintf(log_info.klog_fmt, sizeof(log_info.klog_fmt),
- "<6>%.*s: %%s", MAX_KLOG_TAG, log_info.btag);
+ "<6>%.*s: %%s\n", MAX_KLOG_TAG, log_info.btag);
}
if ((log_target & LOG_FILE) && !file_path) {
diff --git a/rootdir/init.environ.rc.in b/rootdir/init.environ.rc.in
index 0064790..b34ea01 100644
--- a/rootdir/init.environ.rc.in
+++ b/rootdir/init.environ.rc.in
@@ -5,7 +5,7 @@
export ANDROID_ASSETS /system/app
export ANDROID_DATA /data
export ANDROID_STORAGE /storage
+ export EXTERNAL_STORAGE /sdcard
export ASEC_MOUNTPOINT /mnt/asec
- export LOOP_MOUNTPOINT /mnt/obb
export BOOTCLASSPATH %BOOTCLASSPATH%
export SYSTEMSERVERCLASSPATH %SYSTEMSERVERCLASSPATH%
diff --git a/rootdir/init.rc b/rootdir/init.rc
index cda79ce..3da6cc7 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -26,9 +26,6 @@
start ueventd
- # create mountpoints
- mkdir /mnt 0775 root system
-
on init
sysclktz 0
@@ -62,28 +59,29 @@
mkdir /cache 0770 system cache
mkdir /config 0500 root root
+ # Mount staging areas for devices managed by vold
# See storage config details at http://source.android.com/tech/storage/
- mkdir /mnt/shell 0700 shell shell
- mkdir /mnt/media_rw 0700 media_rw media_rw
- mkdir /storage 0751 root sdcard_r
+ mkdir /mnt 0755 root system
+ mount tmpfs tmpfs /mnt mode=0755,uid=0,gid=1000
+ restorecon_recursive /mnt
- # Directory for putting things only root should see.
mkdir /mnt/secure 0700 root root
+ mkdir /mnt/secure/asec 0700 root root
+ mkdir /mnt/asec 0755 root system
+ mkdir /mnt/obb 0755 root system
+ mkdir /mnt/media_rw 0750 root media_rw
+ mkdir /mnt/user 0755 root root
+ mkdir /mnt/user/0 0755 root root
- # Directory for staging bindmounts
- mkdir /mnt/secure/staging 0700 root root
+ # sdcard_r is GID 1028
+ mkdir /storage 0751 root sdcard_r
+ mount tmpfs tmpfs /storage mode=0751,uid=0,gid=1028
+ restorecon_recursive /storage
- # Directory-target for where the secure container
- # imagefile directory will be bind-mounted
- mkdir /mnt/secure/asec 0700 root root
-
- # Secure container public mount points.
- mkdir /mnt/asec 0700 root system
- mount tmpfs tmpfs /mnt/asec mode=0755,gid=1000
-
- # Filesystem image public mount points.
- mkdir /mnt/obb 0700 root system
- mount tmpfs tmpfs /mnt/obb mode=0755,gid=1000
+ # Symlink to keep legacy apps working in multi-user world
+ mkdir /storage/self 0751 root sdcard_r
+ symlink /storage/self/primary /sdcard
+ symlink /mnt/user/0/primary /storage/self/primary
# memory control cgroup
mkdir /dev/memcg 0700 root system
@@ -111,6 +109,10 @@
# set fwmark on accepted sockets
write /proc/sys/net/ipv4/tcp_fwmark_accept 1
+ # disable icmp redirects
+ write /proc/sys/net/ipv4/conf/all/accept_redirects 0
+ write /proc/sys/net/ipv6/conf/all/accept_redirects 0
+
# Create cgroup mount points for process groups
mkdir /dev/cpuctl
mount cgroup none /dev/cpuctl cpu
@@ -233,6 +235,9 @@
# We restorecon /data in case the userdata partition has been reset.
restorecon /data
+ # Emulated internal storage area
+ mkdir /data/media 0770 media_rw media_rw
+
# Start bootcharting as soon as possible after the data partition is
# mounted to collect more data.
mkdir /data/bootchart 0755 shell shell
@@ -265,6 +270,7 @@
chmod 0660 /data/misc/wifi/wpa_supplicant.conf
mkdir /data/local 0751 root root
mkdir /data/misc/media 0700 media media
+ mkdir /data/misc/vold 0700 root root
# For security reasons, /data/local/tmp should always be empty.
# Do not place files or directories in /data/local/tmp
@@ -340,9 +346,9 @@
write /proc/sys/vm/overcommit_memory 1
write /proc/sys/vm/min_free_order_shift 4
chown root system /sys/module/lowmemorykiller/parameters/adj
- chmod 0220 /sys/module/lowmemorykiller/parameters/adj
+ chmod 0664 /sys/module/lowmemorykiller/parameters/adj
chown root system /sys/module/lowmemorykiller/parameters/minfree
- chmod 0220 /sys/module/lowmemorykiller/parameters/minfree
+ chmod 0664 /sys/module/lowmemorykiller/parameters/minfree
# Tweak background writeout
write /proc/sys/vm/dirty_expire_centisecs 200
@@ -530,7 +536,9 @@
onrestart restart surfaceflinger
onrestart restart drm
-service vold /system/bin/vold
+service vold /system/bin/vold \
+ --blkid_context=u:r:blkid:s0 --blkid_untrusted_context=u:r:blkid_untrusted:s0 \
+ --fsck_context=u:r:fsck:s0 --fsck_untrusted_context=u:r:fsck_untrusted:s0
class core
socket vold stream 0660 root mount
ioprio be 2
diff --git a/sdcard/sdcard.c b/sdcard/sdcard.c
index 39ce0eb..942c181 100644
--- a/sdcard/sdcard.c
+++ b/sdcard/sdcard.c
@@ -146,8 +146,6 @@
PERM_ANDROID_OBB,
/* This node is "/Android/media" */
PERM_ANDROID_MEDIA,
- /* This node is "/Android/user" */
- PERM_ANDROID_USER,
} perm_t;
/* Permissions structure to derive */
@@ -250,7 +248,7 @@
__u32 inode_ctr;
Hashmap* package_to_appid;
- Hashmap* appid_with_rw;
+ Hashmap* uid_with_rw;
};
/* Private data used by a single fuse handler. */
@@ -472,6 +470,8 @@
/* Legacy internal layout places users at top level */
node->perm = PERM_ROOT;
node->userid = strtoul(node->name, NULL, 10);
+ node->gid = multiuser_get_uid(node->userid, AID_SDCARD_R);
+ node->mode = 0771;
break;
case PERM_ROOT:
/* Assume masked off by default. */
@@ -483,14 +483,14 @@
} else if (fuse->split_perms) {
if (!strcasecmp(node->name, "DCIM")
|| !strcasecmp(node->name, "Pictures")) {
- node->gid = AID_SDCARD_PICS;
+ node->gid = multiuser_get_uid(node->userid, AID_SDCARD_PICS);
} else if (!strcasecmp(node->name, "Alarms")
|| !strcasecmp(node->name, "Movies")
|| !strcasecmp(node->name, "Music")
|| !strcasecmp(node->name, "Notifications")
|| !strcasecmp(node->name, "Podcasts")
|| !strcasecmp(node->name, "Ringtones")) {
- node->gid = AID_SDCARD_AV;
+ node->gid = multiuser_get_uid(node->userid, AID_SDCARD_AV);
}
}
break;
@@ -510,13 +510,6 @@
/* App-specific directories inside; let anyone traverse */
node->perm = PERM_ANDROID_MEDIA;
node->mode = 0771;
- } else if (!strcasecmp(node->name, "user")) {
- /* User directories must only be accessible to system, protected
- * by sdcard_all. Zygote will bind mount the appropriate user-
- * specific path. */
- node->perm = PERM_ANDROID_USER;
- node->gid = AID_SDCARD_ALL;
- node->mode = 0770;
}
break;
case PERM_ANDROID_DATA:
@@ -528,13 +521,6 @@
}
node->mode = 0770;
break;
- case PERM_ANDROID_USER:
- /* Root of a secondary user */
- node->perm = PERM_ROOT;
- node->userid = strtoul(node->name, NULL, 10);
- node->gid = AID_SDCARD_R;
- node->mode = 0771;
- break;
}
}
@@ -545,8 +531,7 @@
return true;
}
- appid_t appid = multiuser_get_app_id(hdr->uid);
- return hashmapContainsKey(fuse->appid_with_rw, (void*) (uintptr_t) appid);
+ return hashmapContainsKey(fuse->uid_with_rw, (void*) (uintptr_t) hdr->uid);
}
/* Kernel has already enforced everything we returned through
@@ -725,7 +710,7 @@
}
static void fuse_init(struct fuse *fuse, int fd, const char *source_path,
- gid_t write_gid, derive_t derive, bool split_perms) {
+ gid_t write_gid, userid_t owner_user, derive_t derive, bool split_perms) {
pthread_mutex_init(&fuse->lock, NULL);
fuse->fd = fd;
@@ -757,10 +742,10 @@
* places user_id at the top directory level, with the actual roots
* just below that. Shared OBB path is also at top level. */
fuse->root.perm = PERM_LEGACY_PRE_ROOT;
- fuse->root.mode = 0771;
+ fuse->root.mode = 0711;
fuse->root.gid = AID_SDCARD_R;
fuse->package_to_appid = hashmapCreate(256, str_hash, str_icase_equals);
- fuse->appid_with_rw = hashmapCreate(128, int_hash, int_equals);
+ fuse->uid_with_rw = hashmapCreate(128, int_hash, int_equals);
snprintf(fuse->obbpath, sizeof(fuse->obbpath), "%s/obb", source_path);
fs_prepare_dir(fuse->obbpath, 0775, getuid(), getgid());
break;
@@ -769,9 +754,10 @@
* /Android/user and shared OBB path under /Android/obb. */
fuse->root.perm = PERM_ROOT;
fuse->root.mode = 0771;
- fuse->root.gid = AID_SDCARD_R;
+ fuse->root.userid = owner_user;
+ fuse->root.gid = multiuser_get_uid(owner_user, AID_SDCARD_R);
fuse->package_to_appid = hashmapCreate(256, str_hash, str_icase_equals);
- fuse->appid_with_rw = hashmapCreate(128, int_hash, int_equals);
+ fuse->uid_with_rw = hashmapCreate(128, int_hash, int_equals);
snprintf(fuse->obbpath, sizeof(fuse->obbpath), "%s/Android/obb", source_path);
break;
}
@@ -1692,7 +1678,7 @@
pthread_mutex_lock(&fuse->lock);
hashmapForEach(fuse->package_to_appid, remove_str_to_int, fuse->package_to_appid);
- hashmapForEach(fuse->appid_with_rw, remove_int_to_null, fuse->appid_with_rw);
+ hashmapForEach(fuse->uid_with_rw, remove_int_to_null, fuse->uid_with_rw);
FILE* file = fopen(kPackagesListFile, "r");
if (!file) {
@@ -1713,9 +1699,14 @@
char* token = strtok(gids, ",");
while (token != NULL) {
- if (strtoul(token, NULL, 10) == fuse->write_gid) {
- hashmapPut(fuse->appid_with_rw, (void*) (uintptr_t) appid, (void*) (uintptr_t) 1);
- break;
+ // Current packages.list format is a bit funky; it blends per
+ // user GID membership into a single per-app line. Here we
+ // work backwards from the groups to build the per-user UIDs
+ // that have write permission.
+ gid_t gid = strtoul(token, NULL, 10);
+ if (multiuser_get_app_id(gid) == fuse->write_gid) {
+ uid_t uid = multiuser_get_uid(multiuser_get_user_id(gid), appid);
+ hashmapPut(fuse->uid_with_rw, (void*) (uintptr_t) uid, (void*) (uintptr_t) 1);
}
token = strtok(NULL, ",");
}
@@ -1724,7 +1715,7 @@
TRACE("read_package_list: found %zu packages, %zu with write_gid\n",
hashmapSize(fuse->package_to_appid),
- hashmapSize(fuse->appid_with_rw));
+ hashmapSize(fuse->uid_with_rw));
fclose(file);
pthread_mutex_unlock(&fuse->lock);
return 0;
@@ -1849,7 +1840,7 @@
}
static int run(const char* source_path, const char* dest_path, uid_t uid,
- gid_t gid, gid_t write_gid, int num_threads, derive_t derive,
+ gid_t gid, gid_t write_gid, userid_t owner_user, int num_threads, derive_t derive,
bool split_perms) {
int fd;
char opts[256];
@@ -1894,7 +1885,7 @@
goto error;
}
- fuse_init(&fuse, fd, source_path, write_gid, derive, split_perms);
+ fuse_init(&fuse, fd, source_path, write_gid, owner_user, derive, split_perms);
umask(0);
res = ignite_fuse(&fuse, num_threads);
@@ -1915,6 +1906,7 @@
uid_t uid = 0;
gid_t gid = 0;
gid_t write_gid = AID_SDCARD_RW;
+ userid_t owner_user = 0;
int num_threads = DEFAULT_NUM_THREADS;
derive_t derive = DERIVE_NONE;
bool split_perms = false;
@@ -1923,7 +1915,7 @@
int fs_version;
int opt;
- while ((opt = getopt(argc, argv, "u:g:w:t:dls")) != -1) {
+ while ((opt = getopt(argc, argv, "u:g:w:o:t:dls")) != -1) {
switch (opt) {
case 'u':
uid = strtoul(optarg, NULL, 10);
@@ -1934,6 +1926,9 @@
case 'w':
write_gid = strtoul(optarg, NULL, 10);
break;
+ case 'o':
+ owner_user = strtoul(optarg, NULL, 10);
+ break;
case 't':
num_threads = strtoul(optarg, NULL, 10);
break;
@@ -2000,6 +1995,7 @@
sleep(1);
}
- res = run(source_path, dest_path, uid, gid, write_gid, num_threads, derive, split_perms);
+ res = run(source_path, dest_path, uid, gid, write_gid, owner_user,
+ num_threads, derive, split_perms);
return res < 0 ? 1 : 0;
}