am a06bbdf5: am 67db9d5f: am b2ac4243: am f76c8fe6: am 328c3ef6: Merge "Fix typo in fs.h"
* commit 'a06bbdf54334870c233ff4206c78dd2b7fc265eb':
diff --git a/CleanSpec.mk b/CleanSpec.mk
index 0254bd2..e78fc88 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -53,3 +53,4 @@
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/bin/reboot)
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/root/default.prop)
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/recovery/root/default.prop)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/lmkd_intermediates/import_includes)
diff --git a/adb/sockets.c b/adb/sockets.c
index de14a22..faa9564 100644
--- a/adb/sockets.c
+++ b/adb/sockets.c
@@ -23,6 +23,10 @@
#include "sysdeps.h"
+#if !ADB_HOST
+#include <cutils/properties.h>
+#endif
+
#define TRACE_TAG TRACE_SOCKETS
#include "adb.h"
@@ -428,6 +432,9 @@
{
asocket *s;
int fd;
+#if !ADB_HOST
+ char debug[PROPERTY_VALUE_MAX];
+#endif
#if !ADB_HOST
if (!strcmp(name,"jdwp")) {
@@ -444,7 +451,11 @@
D("LS(%d): bound to '%s' via %d\n", s->id, name, fd);
#if !ADB_HOST
- if ((!strncmp(name, "root:", 5) && getuid() != 0)
+ if (!strncmp(name, "root:", 5))
+ property_get("ro.debuggable", debug, "");
+
+ if ((!strncmp(name, "root:", 5) && getuid() != 0
+ && strcmp(debug, "1") == 0)
|| !strncmp(name, "usb:", 4)
|| !strncmp(name, "tcpip:", 6)) {
D("LS(%d): enabling exit_on_close\n", s->id);
diff --git a/debuggerd/Android.mk b/debuggerd/Android.mk
index e4d7ecc..c33b263 100644
--- a/debuggerd/Android.mk
+++ b/debuggerd/Android.mk
@@ -22,13 +22,6 @@
-Wunused \
-Werror \
-ifeq ($(ARCH_ARM_HAVE_VFP),true)
-LOCAL_CFLAGS_arm += -DWITH_VFP
-endif # ARCH_ARM_HAVE_VFP
-ifeq ($(ARCH_ARM_HAVE_VFP_D32),true)
-LOCAL_CFLAGS_arm += -DWITH_VFP_D32
-endif # ARCH_ARM_HAVE_VFP_D32
-
LOCAL_SHARED_LIBRARIES := \
libbacktrace \
libcutils \
@@ -45,6 +38,8 @@
include $(BUILD_EXECUTABLE)
+
+
include $(CLEAR_VARS)
LOCAL_SRC_FILES := crasher.c
LOCAL_SRC_FILES_arm := arm/crashglue.S
@@ -59,36 +54,14 @@
#LOCAL_FORCE_STATIC_EXECUTABLE := true
LOCAL_SHARED_LIBRARIES := libcutils liblog libc
+# The arm emulator has VFP but not VFPv3-D32.
+ifeq ($(ARCH_ARM_HAVE_VFP_D32),true)
+LOCAL_ASFLAGS_arm += -DHAS_VFP_D32
+endif
+
LOCAL_MODULE := crasher
LOCAL_MODULE_STEM_32 := crasher
LOCAL_MODULE_STEM_64 := crasher64
LOCAL_MULTILIB := both
include $(BUILD_EXECUTABLE)
-
-include $(CLEAR_VARS)
-
-ifeq ($(ARCH_ARM_HAVE_VFP),true)
-LOCAL_MODULE_TARGET_ARCH += arm
-LOCAL_SRC_FILES_arm := arm/vfp.S
-LOCAL_CFLAGS_arm += -DWITH_VFP
-ifeq ($(ARCH_ARM_HAVE_VFP_D32),true)
-LOCAL_CFLAGS_arm += -DWITH_VFP_D32
-endif # ARCH_ARM_HAVE_VFP_D32
-endif # ARCH_ARM_HAVE_VFP == true
-LOCAL_CFLAGS += -Werror
-
-LOCAL_SRC_FILES_arm64 := arm64/vfp.S
-LOCAL_MODULE_TARGET_ARCH += arm64
-
-LOCAL_SRC_FILES := vfp-crasher.c
-LOCAL_MODULE := vfp-crasher
-LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES)
-LOCAL_MODULE_TAGS := optional
-LOCAL_SHARED_LIBRARIES := libcutils liblog libc
-
-LOCAL_MODULE_STEM_32 := vfp-crasher
-LOCAL_MODULE_STEM_64 := vfp-crasher64
-LOCAL_MULTILIB := both
-
-include $(BUILD_EXECUTABLE)
diff --git a/debuggerd/arm/crashglue.S b/debuggerd/arm/crashglue.S
index eb9d0e3..4fbfd6e 100644
--- a/debuggerd/arm/crashglue.S
+++ b/debuggerd/arm/crashglue.S
@@ -1,8 +1,5 @@
.globl crash1
.type crash1, %function
-.globl crashnostack
-.type crashnostack, %function
-
crash1:
ldr r0, =0xa5a50000
ldr r1, =0xa5a50001
@@ -18,11 +15,48 @@
ldr r11, =0xa5a50011
ldr r12, =0xa5a50012
+
+ fconstd d0, #0
+ fconstd d1, #1
+ fconstd d2, #2
+ fconstd d3, #3
+ fconstd d4, #4
+ fconstd d5, #5
+ fconstd d6, #6
+ fconstd d7, #7
+ fconstd d8, #8
+ fconstd d9, #9
+ fconstd d10, #10
+ fconstd d11, #11
+ fconstd d12, #12
+ fconstd d13, #13
+ fconstd d14, #14
+ fconstd d15, #15
+#if defined(HAS_VFP_D32)
+ fconstd d16, #16
+ fconstd d17, #17
+ fconstd d18, #18
+ fconstd d19, #19
+ fconstd d20, #20
+ fconstd d21, #21
+ fconstd d22, #22
+ fconstd d23, #23
+ fconstd d24, #24
+ fconstd d25, #25
+ fconstd d26, #26
+ fconstd d27, #27
+ fconstd d28, #28
+ fconstd d29, #29
+ fconstd d30, #30
+ fconstd d31, #31
+#endif
+
mov lr, #0
ldr lr, [lr]
b .
-
+.globl crashnostack
+.type crashnostack, %function
crashnostack:
mov sp, #0
mov r0, #0
diff --git a/debuggerd/arm/machine.cpp b/debuggerd/arm/machine.cpp
index 839d47a..8270066 100644
--- a/debuggerd/arm/machine.cpp
+++ b/debuggerd/arm/machine.cpp
@@ -27,21 +27,8 @@
#include "../utility.h"
#include "../machine.h"
-// enable to dump memory pointed to by every register
-#define DUMP_MEMORY_FOR_ALL_REGISTERS 1
-
-#ifdef WITH_VFP
-#ifdef WITH_VFP_D32
-#define NUM_VFP_REGS 32
-#else
-#define NUM_VFP_REGS 16
-#endif
-#endif
-
-// If configured to do so, dump memory around *all* registers
-// for the crashing thread.
void dump_memory_and_code(log_t* log, pid_t tid) {
- struct pt_regs regs;
+ pt_regs regs;
if (ptrace(PTRACE_GETREGS, tid, 0, ®s)) {
return;
}
@@ -73,7 +60,7 @@
}
void dump_registers(log_t* log, pid_t tid) {
- struct pt_regs r;
+ pt_regs r;
if (ptrace(PTRACE_GETREGS, tid, 0, &r)) {
_LOG(log, logtype::REGISTERS, "cannot get registers: %s\n", strerror(errno));
return;
@@ -93,19 +80,15 @@
static_cast<uint32_t>(r.ARM_lr), static_cast<uint32_t>(r.ARM_pc),
static_cast<uint32_t>(r.ARM_cpsr));
-#ifdef WITH_VFP
- struct user_vfp vfp_regs;
- int i;
-
+ user_vfp vfp_regs;
if (ptrace(PTRACE_GETVFPREGS, tid, 0, &vfp_regs)) {
_LOG(log, logtype::REGISTERS, "cannot get registers: %s\n", strerror(errno));
return;
}
- for (i = 0; i < NUM_VFP_REGS; i += 2) {
+ for (size_t i = 0; i < 32; i += 2) {
_LOG(log, logtype::REGISTERS, " d%-2d %016llx d%-2d %016llx\n",
i, vfp_regs.fpregs[i], i+1, vfp_regs.fpregs[i+1]);
}
_LOG(log, logtype::REGISTERS, " scr %08lx\n", vfp_regs.fpscr);
-#endif
}
diff --git a/debuggerd/arm/vfp.S b/debuggerd/arm/vfp.S
deleted file mode 100644
index 9744f6f..0000000
--- a/debuggerd/arm/vfp.S
+++ /dev/null
@@ -1,43 +0,0 @@
- .text
- .align 2
- .global crash
- .type crash, %function
-crash:
- fconstd d0, #0
- fconstd d1, #1
- fconstd d2, #2
- fconstd d3, #3
- fconstd d4, #4
- fconstd d5, #5
- fconstd d6, #6
- fconstd d7, #7
- fconstd d8, #8
- fconstd d9, #9
- fconstd d10, #10
- fconstd d11, #11
- fconstd d12, #12
- fconstd d13, #13
- fconstd d14, #14
- fconstd d15, #15
-#ifdef WITH_VFP_D32
- fconstd d16, #16
- fconstd d17, #17
- fconstd d18, #18
- fconstd d19, #19
- fconstd d20, #20
- fconstd d21, #21
- fconstd d22, #22
- fconstd d23, #23
- fconstd d24, #24
- fconstd d25, #25
- fconstd d26, #26
- fconstd d27, #27
- fconstd d28, #28
- fconstd d29, #29
- fconstd d30, #30
- fconstd d31, #31
-#endif
- mov r0, #0
- str r0, [r0]
- bx lr
-
diff --git a/debuggerd/arm64/crashglue.S b/debuggerd/arm64/crashglue.S
index b06b67c..e58b542 100644
--- a/debuggerd/arm64/crashglue.S
+++ b/debuggerd/arm64/crashglue.S
@@ -1,8 +1,5 @@
.globl crash1
.type crash1, %function
-.globl crashnostack
-.type crashnostack, %function
-
crash1:
ldr x0, =0xa5a50000
ldr x1, =0xa5a50001
@@ -35,11 +32,46 @@
ldr x28, =0xa5a50028
ldr x29, =0xa5a50029
+ fmov d0, -1.0 // -1 is more convincing than 0.
+ fmov d1, 1.0
+ fmov d2, 2.0
+ fmov d3, 3.0
+ fmov d4, 4.0
+ fmov d5, 5.0
+ fmov d6, 6.0
+ fmov d7, 7.0
+ fmov d8, 8.0
+ fmov d9, 9.0
+ fmov d10, 10.0
+ fmov d11, 11.0
+ fmov d12, 12.0
+ fmov d13, 13.0
+ fmov d14, 14.0
+ fmov d15, 15.0
+ fmov d16, 16.0
+ fmov d17, 17.0
+ fmov d18, 18.0
+ fmov d19, 19.0
+ fmov d20, 20.0
+ fmov d21, 21.0
+ fmov d22, 22.0
+ fmov d23, 23.0
+ fmov d24, 24.0
+ fmov d25, 25.0
+ fmov d26, 26.0
+ fmov d27, 27.0
+ fmov d28, 28.0
+ fmov d29, 29.0
+ fmov d30, 30.0
+ fmov d31, 31.0
+
mov x30, xzr
ldr x30, [x30]
b .
+.globl crashnostack
+.type crashnostack, %function
crashnostack:
mov x0, xzr
add sp, x0, xzr
diff --git a/debuggerd/arm64/machine.cpp b/debuggerd/arm64/machine.cpp
index 48308c3..ec664bd 100644
--- a/debuggerd/arm64/machine.cpp
+++ b/debuggerd/arm64/machine.cpp
@@ -30,13 +30,6 @@
#include "../utility.h"
#include "../machine.h"
-/* enable to dump memory pointed to by every register */
-#define DUMP_MEMORY_FOR_ALL_REGISTERS 1
-
-/*
- * If configured to do so, dump memory around *all* registers
- * for the crashing thread.
- */
void dump_memory_and_code(log_t* log, pid_t tid) {
struct user_pt_regs regs;
struct iovec io;
diff --git a/debuggerd/arm64/vfp.S b/debuggerd/arm64/vfp.S
deleted file mode 100644
index bf12c22..0000000
--- a/debuggerd/arm64/vfp.S
+++ /dev/null
@@ -1,42 +0,0 @@
- .text
- .align 2
- .global crash
- .type crash, %function
-crash:
- fmov d0, XZR
- fmov d1, 1.0
- fmov d2, 2.0
- fmov d3, 3.0
- fmov d4, 4.0
- fmov d5, 5.0
- fmov d6, 6.0
- fmov d7, 7.0
- fmov d8, 8.0
- fmov d9, 9.0
- fmov d10, 10.0
- fmov d11, 11.0
- fmov d12, 12.0
- fmov d13, 13.0
- fmov d14, 14.0
- fmov d15, 15.0
- fmov d16, 16.0
- fmov d17, 17.0
- fmov d18, 18.0
- fmov d19, 19.0
- fmov d20, 20.0
- fmov d21, 21.0
- fmov d22, 22.0
- fmov d23, 23.0
- fmov d24, 24.0
- fmov d25, 25.0
- fmov d26, 26.0
- fmov d27, 27.0
- fmov d28, 28.0
- fmov d29, 29.0
- fmov d30, 30.0
- fmov d31, 31.0
-
- mov x0, xzr
- str x0, [x0]
- br x30
-
diff --git a/debuggerd/vfp-crasher.c b/debuggerd/vfp-crasher.c
deleted file mode 100644
index 7a19cdd..0000000
--- a/debuggerd/vfp-crasher.c
+++ /dev/null
@@ -1,7 +0,0 @@
-int main()
-{
- extern void crash(void);
-
- crash();
- return 0;
-}
diff --git a/healthd/BatteryMonitor.cpp b/healthd/BatteryMonitor.cpp
index 1ee33a1..4a6b702 100644
--- a/healthd/BatteryMonitor.cpp
+++ b/healthd/BatteryMonitor.cpp
@@ -35,6 +35,8 @@
#define POWER_SUPPLY_SUBSYSTEM "power_supply"
#define POWER_SUPPLY_SYSFS_PATH "/sys/class/" POWER_SUPPLY_SUBSYSTEM
+#define FAKE_BATTERY_CAPACITY 42
+#define FAKE_BATTERY_TEMPERATURE 424
namespace android {
@@ -530,11 +532,11 @@
KLOG_WARNING(LOG_TAG, "BatteryTechnologyPath not found\n");
}
- if (property_get("persist.sys.battery.capacity", pval, NULL) > 0)
- mBatteryFixedCapacity = (int) strtol(pval, NULL, 10);
-
- if (property_get("persist.sys.battery.temperature", pval, NULL) > 0)
- mBatteryFixedTemperature = (int) strtol(pval, NULL, 10);
+ if (property_get("ro.boot.fake_battery", pval, NULL) > 0
+ && strtol(pval, NULL, 10) != 0) {
+ mBatteryFixedCapacity = FAKE_BATTERY_CAPACITY;
+ mBatteryFixedTemperature = FAKE_BATTERY_TEMPERATURE;
+ }
}
}; // namespace android
diff --git a/include/system/audio.h b/include/system/audio.h
index 8530efa..f42c640 100644
--- a/include/system/audio.h
+++ b/include/system/audio.h
@@ -52,7 +52,9 @@
AUDIO_STREAM_ALARM = 4,
AUDIO_STREAM_NOTIFICATION = 5,
AUDIO_STREAM_BLUETOOTH_SCO = 6,
- AUDIO_STREAM_ENFORCED_AUDIBLE = 7, /* Sounds that cannot be muted by user and must be routed to speaker */
+ AUDIO_STREAM_ENFORCED_AUDIBLE = 7, /* Sounds that cannot be muted by user
+ * and must be routed to speaker
+ */
AUDIO_STREAM_DTMF = 8,
AUDIO_STREAM_TTS = 9,
@@ -200,7 +202,16 @@
/* AAC sub format field definition: specify profile or bitrate for recording... */
typedef enum {
- AUDIO_FORMAT_AAC_SUB_NONE = 0x0,
+ AUDIO_FORMAT_AAC_SUB_MAIN = 0x1,
+ AUDIO_FORMAT_AAC_SUB_LC = 0x2,
+ AUDIO_FORMAT_AAC_SUB_SSR = 0x4,
+ AUDIO_FORMAT_AAC_SUB_LTP = 0x8,
+ AUDIO_FORMAT_AAC_SUB_HE_V1 = 0x10,
+ AUDIO_FORMAT_AAC_SUB_SCALABLE = 0x20,
+ AUDIO_FORMAT_AAC_SUB_ERLC = 0x40,
+ AUDIO_FORMAT_AAC_SUB_LD = 0x80,
+ AUDIO_FORMAT_AAC_SUB_HE_V2 = 0x100,
+ AUDIO_FORMAT_AAC_SUB_ELD = 0x200,
} audio_format_aac_sub_fmt_t;
/* VORBIS sub format field definition: specify quality for recording... */
@@ -225,8 +236,8 @@
AUDIO_FORMAT_AMR_NB = 0x02000000UL,
AUDIO_FORMAT_AMR_WB = 0x03000000UL,
AUDIO_FORMAT_AAC = 0x04000000UL,
- AUDIO_FORMAT_HE_AAC_V1 = 0x05000000UL,
- AUDIO_FORMAT_HE_AAC_V2 = 0x06000000UL,
+ AUDIO_FORMAT_HE_AAC_V1 = 0x05000000UL, /* Deprecated, Use AUDIO_FORMAT_AAC_HE_V1*/
+ AUDIO_FORMAT_HE_AAC_V2 = 0x06000000UL, /* Deprecated, Use AUDIO_FORMAT_AAC_HE_V2*/
AUDIO_FORMAT_VORBIS = 0x07000000UL,
AUDIO_FORMAT_OPUS = 0x08000000UL,
AUDIO_FORMAT_AC3 = 0x09000000UL,
@@ -249,10 +260,41 @@
AUDIO_FORMAT_PCM_SUB_FLOAT),
AUDIO_FORMAT_PCM_24_BIT_PACKED = (AUDIO_FORMAT_PCM |
AUDIO_FORMAT_PCM_SUB_24_BIT_PACKED),
+ AUDIO_FORMAT_AAC_MAIN = (AUDIO_FORMAT_AAC |
+ AUDIO_FORMAT_AAC_SUB_MAIN),
+ AUDIO_FORMAT_AAC_LC = (AUDIO_FORMAT_AAC |
+ AUDIO_FORMAT_AAC_SUB_LC),
+ AUDIO_FORMAT_AAC_SSR = (AUDIO_FORMAT_AAC |
+ AUDIO_FORMAT_AAC_SUB_SSR),
+ AUDIO_FORMAT_AAC_LTP = (AUDIO_FORMAT_AAC |
+ AUDIO_FORMAT_AAC_SUB_LTP),
+ AUDIO_FORMAT_AAC_HE_V1 = (AUDIO_FORMAT_AAC |
+ AUDIO_FORMAT_AAC_SUB_HE_V1),
+ AUDIO_FORMAT_AAC_SCALABLE = (AUDIO_FORMAT_AAC |
+ AUDIO_FORMAT_AAC_SUB_SCALABLE),
+ AUDIO_FORMAT_AAC_ERLC = (AUDIO_FORMAT_AAC |
+ AUDIO_FORMAT_AAC_SUB_ERLC),
+ AUDIO_FORMAT_AAC_LD = (AUDIO_FORMAT_AAC |
+ AUDIO_FORMAT_AAC_SUB_LD),
+ AUDIO_FORMAT_AAC_HE_V2 = (AUDIO_FORMAT_AAC |
+ AUDIO_FORMAT_AAC_SUB_HE_V2),
+ AUDIO_FORMAT_AAC_ELD = (AUDIO_FORMAT_AAC |
+ AUDIO_FORMAT_AAC_SUB_ELD),
} audio_format_t;
+/* For the channel mask for position assignment representation */
enum {
+
+/* These can be a complete audio_channel_mask_t. */
+
AUDIO_CHANNEL_NONE = 0x0,
+ AUDIO_CHANNEL_INVALID = 0xC0000000,
+
+/* These can be the bits portion of an audio_channel_mask_t
+ * with representation AUDIO_CHANNEL_REPRESENTATION_POSITION.
+ * Using these bits as a complete audio_channel_mask_t is deprecated.
+ */
+
/* output channels */
AUDIO_CHANNEL_OUT_FRONT_LEFT = 0x1,
AUDIO_CHANNEL_OUT_FRONT_RIGHT = 0x2,
@@ -273,6 +315,8 @@
AUDIO_CHANNEL_OUT_TOP_BACK_CENTER = 0x10000,
AUDIO_CHANNEL_OUT_TOP_BACK_RIGHT = 0x20000,
+/* TODO: should these be considered complete channel masks, or only bits? */
+
AUDIO_CHANNEL_OUT_MONO = AUDIO_CHANNEL_OUT_FRONT_LEFT,
AUDIO_CHANNEL_OUT_STEREO = (AUDIO_CHANNEL_OUT_FRONT_LEFT |
AUDIO_CHANNEL_OUT_FRONT_RIGHT),
@@ -328,6 +372,8 @@
AUDIO_CHANNEL_OUT_TOP_BACK_CENTER|
AUDIO_CHANNEL_OUT_TOP_BACK_RIGHT),
+/* These are bits only, not complete values */
+
/* input channels */
AUDIO_CHANNEL_IN_LEFT = 0x4,
AUDIO_CHANNEL_IN_RIGHT = 0x8,
@@ -344,6 +390,8 @@
AUDIO_CHANNEL_IN_VOICE_UPLINK = 0x4000,
AUDIO_CHANNEL_IN_VOICE_DNLINK = 0x8000,
+/* TODO: should these be considered complete channel masks, or only bits, or deprecated? */
+
AUDIO_CHANNEL_IN_MONO = AUDIO_CHANNEL_IN_FRONT,
AUDIO_CHANNEL_IN_STEREO = (AUDIO_CHANNEL_IN_LEFT | AUDIO_CHANNEL_IN_RIGHT),
AUDIO_CHANNEL_IN_FRONT_BACK = (AUDIO_CHANNEL_IN_FRONT | AUDIO_CHANNEL_IN_BACK),
@@ -365,9 +413,95 @@
/* A channel mask per se only defines the presence or absence of a channel, not the order.
* But see AUDIO_INTERLEAVE_* below for the platform convention of order.
+ *
+ * audio_channel_mask_t is an opaque type and its internal layout should not
+ * be assumed as it may change in the future.
+ * Instead, always use the functions declared in this header to examine.
+ *
+ * These are the current representations:
+ *
+ * AUDIO_CHANNEL_REPRESENTATION_POSITION
+ * is a channel mask representation for position assignment.
+ * Each low-order bit corresponds to the spatial position of a transducer (output),
+ * or interpretation of channel (input).
+ * The user of a channel mask needs to know the context of whether it is for output or input.
+ * The constants AUDIO_CHANNEL_OUT_* or AUDIO_CHANNEL_IN_* apply to the bits portion.
+ * It is not permitted for no bits to be set.
+ *
+ * AUDIO_CHANNEL_REPRESENTATION_INDEX
+ * is a channel mask representation for index assignment.
+ * Each low-order bit corresponds to a selected channel.
+ * There is no platform interpretation of the various bits.
+ * There is no concept of output or input.
+ * It is not permitted for no bits to be set.
+ *
+ * All other representations are reserved for future use.
+ *
+ * Warning: current representation distinguishes between input and output, but this will not the be
+ * case in future revisions of the platform. Wherever there is an ambiguity between input and output
+ * that is currently resolved by checking the channel mask, the implementer should look for ways to
+ * fix it with additional information outside of the mask.
*/
typedef uint32_t audio_channel_mask_t;
+/* Maximum number of channels for all representations */
+#define AUDIO_CHANNEL_COUNT_MAX 30
+
+/* log(2) of maximum number of representations, not part of public API */
+#define AUDIO_CHANNEL_REPRESENTATION_LOG2 2
+
+/* Representations */
+typedef enum {
+ AUDIO_CHANNEL_REPRESENTATION_POSITION = 0, // must be zero for compatibility
+ // 1 is reserved for future use
+ AUDIO_CHANNEL_REPRESENTATION_INDEX = 2,
+ // 3 is reserved for future use
+} audio_channel_representation_t;
+
+/* The return value is undefined if the channel mask is invalid. */
+static inline uint32_t audio_channel_mask_get_bits(audio_channel_mask_t channel)
+{
+ return channel & ((1 << AUDIO_CHANNEL_COUNT_MAX) - 1);
+}
+
+/* The return value is undefined if the channel mask is invalid. */
+static inline audio_channel_representation_t audio_channel_mask_get_representation(
+ audio_channel_mask_t channel)
+{
+ // The right shift should be sufficient, but also "and" for safety in case mask is not 32 bits
+ return (audio_channel_representation_t)
+ ((channel >> AUDIO_CHANNEL_COUNT_MAX) & ((1 << AUDIO_CHANNEL_REPRESENTATION_LOG2) - 1));
+}
+
+/* Returns true if the channel mask is valid,
+ * or returns false for AUDIO_CHANNEL_NONE, AUDIO_CHANNEL_INVALID, and other invalid values.
+ * This function is unable to determine whether a channel mask for position assignment
+ * is invalid because an output mask has an invalid output bit set,
+ * or because an input mask has an invalid input bit set.
+ * All other APIs that take a channel mask assume that it is valid.
+ */
+static inline bool audio_channel_mask_is_valid(audio_channel_mask_t channel)
+{
+ uint32_t bits = audio_channel_mask_get_bits(channel);
+ audio_channel_representation_t representation = audio_channel_mask_get_representation(channel);
+ switch (representation) {
+ case AUDIO_CHANNEL_REPRESENTATION_POSITION:
+ case AUDIO_CHANNEL_REPRESENTATION_INDEX:
+ break;
+ default:
+ bits = 0;
+ break;
+ }
+ return bits != 0;
+}
+
+/* Not part of public API */
+static inline audio_channel_mask_t audio_channel_mask_from_representation_and_bits(
+ audio_channel_representation_t representation, uint32_t bits)
+{
+ return (audio_channel_mask_t) ((representation << AUDIO_CHANNEL_COUNT_MAX) | bits);
+}
+
/* Expresses the convention when stereo audio samples are stored interleaved
* in an array. This should improve readability by allowing code to use
* symbolic indices instead of hard-coded [0] and [1].
@@ -645,10 +779,10 @@
audio_gain_mode_t mode; /* mode requested for this command */
audio_channel_mask_t channel_mask; /* channels which gain value follows.
N/A in joint mode */
- int values[sizeof(audio_channel_mask_t)]; /* gain values in millibels for each
- channel ordered from LSb to MSb in channel mask.
- The number of values is 1 in joint mode or
- popcount(channel_mask) */
+ int values[sizeof(audio_channel_mask_t) * 8]; /* gain values in millibels
+ for each channel ordered from LSb to MSb in
+ channel mask. The number of values is 1 in joint
+ mode or popcount(channel_mask) */
unsigned int ramp_duration_ms; /* ramp duration in ms */
};
@@ -913,81 +1047,182 @@
return false;
}
+/* Returns true if:
+ * representation is valid, and
+ * there is at least one channel bit set which _could_ correspond to an input channel, and
+ * there are no channel bits set which could _not_ correspond to an input channel.
+ * Otherwise returns false.
+ */
static inline bool audio_is_input_channel(audio_channel_mask_t channel)
{
- if ((channel & ~AUDIO_CHANNEL_IN_ALL) == 0)
- return channel != 0;
- else
+ uint32_t bits = audio_channel_mask_get_bits(channel);
+ switch (audio_channel_mask_get_representation(channel)) {
+ case AUDIO_CHANNEL_REPRESENTATION_POSITION:
+ if (bits & ~AUDIO_CHANNEL_IN_ALL) {
+ bits = 0;
+ }
+ // fall through
+ case AUDIO_CHANNEL_REPRESENTATION_INDEX:
+ return bits != 0;
+ default:
return false;
+ }
}
+/* Returns true if:
+ * representation is valid, and
+ * there is at least one channel bit set which _could_ correspond to an output channel, and
+ * there are no channel bits set which could _not_ correspond to an output channel.
+ * Otherwise returns false.
+ */
static inline bool audio_is_output_channel(audio_channel_mask_t channel)
{
- if ((channel & ~AUDIO_CHANNEL_OUT_ALL) == 0)
- return channel != 0;
- else
+ uint32_t bits = audio_channel_mask_get_bits(channel);
+ switch (audio_channel_mask_get_representation(channel)) {
+ case AUDIO_CHANNEL_REPRESENTATION_POSITION:
+ if (bits & ~AUDIO_CHANNEL_OUT_ALL) {
+ bits = 0;
+ }
+ // fall through
+ case AUDIO_CHANNEL_REPRESENTATION_INDEX:
+ return bits != 0;
+ default:
return false;
+ }
}
/* Returns the number of channels from an input channel mask,
* used in the context of audio input or recording.
+ * If a channel bit is set which could _not_ correspond to an input channel,
+ * it is excluded from the count.
+ * Returns zero if the representation is invalid.
*/
static inline uint32_t audio_channel_count_from_in_mask(audio_channel_mask_t channel)
{
- return popcount(channel & AUDIO_CHANNEL_IN_ALL);
+ uint32_t bits = audio_channel_mask_get_bits(channel);
+ switch (audio_channel_mask_get_representation(channel)) {
+ case AUDIO_CHANNEL_REPRESENTATION_POSITION:
+ // TODO: We can now merge with from_out_mask and remove anding
+ bits &= AUDIO_CHANNEL_IN_ALL;
+ // fall through
+ case AUDIO_CHANNEL_REPRESENTATION_INDEX:
+ return popcount(bits);
+ default:
+ return 0;
+ }
}
/* Returns the number of channels from an output channel mask,
* used in the context of audio output or playback.
+ * If a channel bit is set which could _not_ correspond to an output channel,
+ * it is excluded from the count.
+ * Returns zero if the representation is invalid.
*/
static inline uint32_t audio_channel_count_from_out_mask(audio_channel_mask_t channel)
{
- return popcount(channel & AUDIO_CHANNEL_OUT_ALL);
+ uint32_t bits = audio_channel_mask_get_bits(channel);
+ switch (audio_channel_mask_get_representation(channel)) {
+ case AUDIO_CHANNEL_REPRESENTATION_POSITION:
+ // TODO: We can now merge with from_in_mask and remove anding
+ bits &= AUDIO_CHANNEL_OUT_ALL;
+ // fall through
+ case AUDIO_CHANNEL_REPRESENTATION_INDEX:
+ return popcount(bits);
+ default:
+ return 0;
+ }
}
-/* Derive an output channel mask from a channel count.
+/* Derive an output channel mask for position assignment from a channel count.
* This is to be used when the content channel mask is unknown. The 1, 2, 4, 5, 6, 7 and 8 channel
* cases are mapped to the standard game/home-theater layouts, but note that 4 is mapped to quad,
* and not stereo + FC + mono surround. A channel count of 3 is arbitrarily mapped to stereo + FC
* for continuity with stereo.
- * Returns the matching channel mask, or 0 if the number of channels exceeds that of the
- * configurations for which a default channel mask is defined.
+ * Returns the matching channel mask,
+ * or AUDIO_CHANNEL_NONE if the channel count is zero,
+ * or AUDIO_CHANNEL_INVALID if the channel count exceeds that of the
+ * configurations for which a default output channel mask is defined.
*/
static inline audio_channel_mask_t audio_channel_out_mask_from_count(uint32_t channel_count)
{
+ uint32_t bits;
switch (channel_count) {
+ case 0:
+ return AUDIO_CHANNEL_NONE;
case 1:
- return AUDIO_CHANNEL_OUT_MONO;
+ bits = AUDIO_CHANNEL_OUT_MONO;
+ break;
case 2:
- return AUDIO_CHANNEL_OUT_STEREO;
+ bits = AUDIO_CHANNEL_OUT_STEREO;
+ break;
case 3:
- return (AUDIO_CHANNEL_OUT_STEREO | AUDIO_CHANNEL_OUT_FRONT_CENTER);
+ bits = AUDIO_CHANNEL_OUT_STEREO | AUDIO_CHANNEL_OUT_FRONT_CENTER;
+ break;
case 4: // 4.0
- return AUDIO_CHANNEL_OUT_QUAD;
+ bits = AUDIO_CHANNEL_OUT_QUAD;
+ break;
case 5: // 5.0
- return (AUDIO_CHANNEL_OUT_QUAD | AUDIO_CHANNEL_OUT_FRONT_CENTER);
+ bits = AUDIO_CHANNEL_OUT_QUAD | AUDIO_CHANNEL_OUT_FRONT_CENTER;
+ break;
case 6: // 5.1
- return AUDIO_CHANNEL_OUT_5POINT1;
+ bits = AUDIO_CHANNEL_OUT_5POINT1;
+ break;
case 7: // 6.1
- return (AUDIO_CHANNEL_OUT_5POINT1 | AUDIO_CHANNEL_OUT_BACK_CENTER);
+ bits = AUDIO_CHANNEL_OUT_5POINT1 | AUDIO_CHANNEL_OUT_BACK_CENTER;
+ break;
case 8:
- return AUDIO_CHANNEL_OUT_7POINT1;
+ bits = AUDIO_CHANNEL_OUT_7POINT1;
+ break;
default:
- return 0;
+ return AUDIO_CHANNEL_INVALID;
}
+ return audio_channel_mask_from_representation_and_bits(
+ AUDIO_CHANNEL_REPRESENTATION_POSITION, bits);
}
-/* Similar to above, but for input. Currently handles only mono and stereo. */
+/* Derive an input channel mask for position assignment from a channel count.
+ * Currently handles only mono and stereo.
+ * Returns the matching channel mask,
+ * or AUDIO_CHANNEL_NONE if the channel count is zero,
+ * or AUDIO_CHANNEL_INVALID if the channel count exceeds that of the
+ * configurations for which a default input channel mask is defined.
+ */
static inline audio_channel_mask_t audio_channel_in_mask_from_count(uint32_t channel_count)
{
+ uint32_t bits;
switch (channel_count) {
+ case 0:
+ return AUDIO_CHANNEL_NONE;
case 1:
- return AUDIO_CHANNEL_IN_MONO;
+ bits = AUDIO_CHANNEL_IN_MONO;
+ break;
case 2:
- return AUDIO_CHANNEL_IN_STEREO;
+ bits = AUDIO_CHANNEL_IN_STEREO;
+ break;
default:
- return 0;
+ return AUDIO_CHANNEL_INVALID;
}
+ return audio_channel_mask_from_representation_and_bits(
+ AUDIO_CHANNEL_REPRESENTATION_POSITION, bits);
+}
+
+/* Derive a channel mask for index assignment from a channel count.
+ * Returns the matching channel mask,
+ * or AUDIO_CHANNEL_NONE if the channel count is zero,
+ * or AUDIO_CHANNEL_INVALID if the channel count exceeds AUDIO_CHANNEL_COUNT_MAX.
+ */
+static inline audio_channel_mask_t audio_channel_mask_for_index_assignment_from_count(
+ uint32_t channel_count)
+{
+ if (channel_count == 0) {
+ return AUDIO_CHANNEL_NONE;
+ }
+ if (channel_count > AUDIO_CHANNEL_COUNT_MAX) {
+ return AUDIO_CHANNEL_INVALID;
+ }
+ uint32_t bits = (1 << channel_count) - 1;
+ return audio_channel_mask_from_representation_and_bits(
+ AUDIO_CHANNEL_REPRESENTATION_INDEX, bits);
}
static inline bool audio_is_valid_format(audio_format_t format)
diff --git a/include/system/audio_policy.h b/include/system/audio_policy.h
index 3085830..a6554de 100644
--- a/include/system/audio_policy.h
+++ b/include/system/audio_policy.h
@@ -44,9 +44,6 @@
AUDIO_POLICY_FORCE_DIGITAL_DOCK,
AUDIO_POLICY_FORCE_NO_BT_A2DP, /* A2DP sink is not preferred to speaker or wired HS */
AUDIO_POLICY_FORCE_SYSTEM_ENFORCED,
- AUDIO_POLICY_FORCE_SYSTEM_AUDIO_HDMI_ARC,
- AUDIO_POLICY_FORCE_SYSTEM_AUDIO_SPDIF,
- AUDIO_POLICY_FORCE_SYSTEM_AUDIO_LINE,
AUDIO_POLICY_FORCE_CFG_CNT,
AUDIO_POLICY_FORCE_CFG_MAX = AUDIO_POLICY_FORCE_CFG_CNT - 1,
diff --git a/init/builtins.c b/init/builtins.c
index f7bd8a9..6032184 100644
--- a/init/builtins.c
+++ b/init/builtins.c
@@ -48,7 +48,7 @@
#include <private/android_filesystem_config.h>
-void add_environment(const char *name, const char *value);
+int add_environment(const char *name, const char *value);
extern int init_module(void *, unsigned long, const char *);
@@ -261,8 +261,7 @@
int do_export(int nargs, char **args)
{
- add_environment(args[1], args[2]);
- return 0;
+ return add_environment(args[1], args[2]);
}
int do_hostname(int nargs, char **args)
diff --git a/init/init.c b/init/init.c
index e4ac1cf..74c0308 100644
--- a/init/init.c
+++ b/init/init.c
@@ -96,11 +96,24 @@
/* add_environment - add "key=value" to the current environment */
int add_environment(const char *key, const char *val)
{
- int n;
+ size_t n;
+ size_t key_len = strlen(key);
- for (n = 0; n < 31; n++) {
- if (!ENV[n]) {
- size_t len = strlen(key) + strlen(val) + 2;
+ /* The last environment entry is reserved to terminate the list */
+ for (n = 0; n < (ARRAY_SIZE(ENV) - 1); n++) {
+
+ /* Delete any existing entry for this key */
+ if (ENV[n] != NULL) {
+ size_t entry_key_len = strcspn(ENV[n], "=");
+ if ((entry_key_len == key_len) && (strncmp(ENV[n], key, entry_key_len) == 0)) {
+ free((char*)ENV[n]);
+ ENV[n] = NULL;
+ }
+ }
+
+ /* Add entry if a free slot is available */
+ if (ENV[n] == NULL) {
+ size_t len = key_len + strlen(val) + 2;
char *entry = malloc(len);
snprintf(entry, len, "%s=%s", key, val);
ENV[n] = entry;
@@ -108,7 +121,9 @@
}
}
- return 1;
+ ERROR("No env. room to store: '%s':'%s'\n", key, val);
+
+ return -1;
}
static void zap_stdio(void)
diff --git a/libcutils/sched_policy.c b/libcutils/sched_policy.c
index fa0792f..f8ffb1d 100644
--- a/libcutils/sched_policy.c
+++ b/libcutils/sched_policy.c
@@ -39,17 +39,9 @@
#if defined(HAVE_ANDROID_OS) && defined(HAVE_SCHED_H) && defined(HAVE_PTHREADS)
-#include <linux/prctl.h>
-#include <sched.h>
#include <pthread.h>
-
-#ifndef SCHED_NORMAL
- #define SCHED_NORMAL 0
-#endif
-
-#ifndef SCHED_BATCH
- #define SCHED_BATCH 3
-#endif
+#include <sched.h>
+#include <sys/prctl.h>
#define POLICY_DEBUG 0
diff --git a/libprocessgroup/Android.mk b/libprocessgroup/Android.mk
new file mode 100644
index 0000000..501321f
--- /dev/null
+++ b/libprocessgroup/Android.mk
@@ -0,0 +1,21 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := processgroup.cpp
+LOCAL_MODULE := libprocessgroup
+LOCAL_SHARED_LIBRARIES := liblog
+LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
+LOCAL_CFLAGS := -Wall -Werror
+LOCAL_REQUIRED_MODULE := processgroup_cleanup
+include external/libcxx/libcxx.mk
+include $(BUILD_SHARED_LIBRARY)
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := cleanup.cpp
+LOCAL_MODULE := processgroup_cleanup
+LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
+LOCAL_CFLAGS := -Wall -Werror
+LOCAL_FORCE_STATIC_EXECUTABLE := true
+LOCAL_STATIC_LIBRARIES := libc libcutils
+include $(BUILD_EXECUTABLE)
diff --git a/libprocessgroup/cleanup.cpp b/libprocessgroup/cleanup.cpp
new file mode 100644
index 0000000..cca8dc4
--- /dev/null
+++ b/libprocessgroup/cleanup.cpp
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2014 Google, Inc
+ *
+ * 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 <string.h>
+#include <unistd.h>
+#include <sys/syslimits.h>
+
+#include "processgroup_priv.h"
+
+int main(int argc, char **argv)
+{
+ char buf[PATH_MAX];
+ if (argc != 2)
+ return -1;
+
+ memcpy(buf, PROCESSGROUP_CGROUP_PATH, sizeof(PROCESSGROUP_CGROUP_PATH));
+ strlcat(buf, argv[1], sizeof(buf));
+ return rmdir(buf);
+}
diff --git a/libprocessgroup/include/processgroup/processgroup.h b/libprocessgroup/include/processgroup/processgroup.h
new file mode 100644
index 0000000..11bd8cc
--- /dev/null
+++ b/libprocessgroup/include/processgroup/processgroup.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2014 Google, Inc
+ *
+ * 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 _PROCESSGROUP_H_
+#define _PROCESSGROUP_H_
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+__BEGIN_DECLS
+
+int killProcessGroup(uid_t uid, int initialPid, int signal);
+
+int createProcessGroup(uid_t uid, int initialPid);
+
+void removeAllProcessGroups(void);
+
+__END_DECLS
+
+#endif
diff --git a/libprocessgroup/processgroup.cpp b/libprocessgroup/processgroup.cpp
new file mode 100644
index 0000000..c32e741
--- /dev/null
+++ b/libprocessgroup/processgroup.cpp
@@ -0,0 +1,316 @@
+/*
+ * Copyright 2014 Google, Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "libprocessgroup"
+
+#include <assert.h>
+#include <dirent.h>
+#include <fcntl.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <log/log.h>
+#include <private/android_filesystem_config.h>
+
+#include <processgroup/processgroup.h>
+#include "processgroup_priv.h"
+
+struct ctx {
+ bool initialized;
+ int fd;
+ char buf[128];
+ char *buf_ptr;
+ size_t buf_len;
+};
+
+static int convertUidToPath(char *path, size_t size, uid_t uid)
+{
+ return snprintf(path, size, "%s/%s%d",
+ PROCESSGROUP_CGROUP_PATH,
+ PROCESSGROUP_UID_PREFIX,
+ uid);
+}
+
+static int convertUidPidToPath(char *path, size_t size, uid_t uid, int pid)
+{
+ return snprintf(path, size, "%s/%s%d/%s%d",
+ PROCESSGROUP_CGROUP_PATH,
+ PROCESSGROUP_UID_PREFIX,
+ uid,
+ PROCESSGROUP_PID_PREFIX,
+ pid);
+}
+
+static int initCtx(uid_t uid, int pid, struct ctx *ctx)
+{
+ int ret;
+ char path[PROCESSGROUP_MAX_PATH_LEN] = {0};
+ convertUidPidToPath(path, sizeof(path), uid, pid);
+ strlcat(path, PROCESSGROUP_CGROUP_PROCS_FILE, sizeof(path));
+
+ int fd = open(path, O_RDONLY);
+ if (fd < 0) {
+ ret = -errno;
+ SLOGV("failed to open %s: %s", path, strerror(errno));
+ return ret;
+ }
+
+ ctx->fd = fd;
+ ctx->buf_ptr = ctx->buf;
+ ctx->buf_len = 0;
+ ctx->initialized = true;
+
+ return 0;
+}
+
+static int refillBuffer(struct ctx *ctx)
+{
+ memmove(ctx->buf, ctx->buf_ptr, ctx->buf_len);
+ ctx->buf_ptr = ctx->buf;
+
+ ssize_t ret = read(ctx->fd, ctx->buf_ptr + ctx->buf_len,
+ sizeof(ctx->buf) - ctx->buf_len);
+ if (ret < 0) {
+ return -errno;
+ } else if (ret == 0) {
+ return 0;
+ }
+
+ ctx->buf_len += ret;
+ assert(ctx->buf_len <= sizeof(ctx->buf));
+
+ return ret;
+}
+
+static pid_t getOneAppProcess(uid_t uid, int appProcessPid, struct ctx *ctx)
+{
+ if (!ctx->initialized) {
+ int ret = initCtx(uid, appProcessPid, ctx);
+ if (ret < 0) {
+ return ret;
+ }
+ }
+
+ char *eptr;
+ while ((eptr = (char *)memchr(ctx->buf_ptr, '\n', ctx->buf_len)) == NULL) {
+ int ret = refillBuffer(ctx);
+ if (ret == 0) {
+ return -ERANGE;
+ }
+ if (ret < 0) {
+ return ret;
+ }
+ }
+
+ *eptr = '\0';
+ char *pid_eptr = NULL;
+ errno = 0;
+ long pid = strtol(ctx->buf_ptr, &pid_eptr, 10);
+ if (errno != 0) {
+ return -errno;
+ }
+ if (pid_eptr != eptr) {
+ return -EINVAL;
+ }
+
+ ctx->buf_ptr = eptr + 1;
+
+ return (pid_t)pid;
+}
+
+static int removeProcessGroup(uid_t uid, int pid)
+{
+ int ret;
+ char path[PROCESSGROUP_MAX_PATH_LEN] = {0};
+
+ convertUidPidToPath(path, sizeof(path), uid, pid);
+ ret = rmdir(path);
+
+ convertUidToPath(path, sizeof(path), uid);
+ rmdir(path);
+
+ return ret;
+}
+
+static void removeUidProcessGroups(const char *uid_path)
+{
+ DIR *uid = opendir(uid_path);
+ if (uid != NULL) {
+ struct dirent cur;
+ struct dirent *dir;
+ while ((readdir_r(uid, &cur, &dir) == 0) && dir) {
+ char path[PROCESSGROUP_MAX_PATH_LEN];
+
+ if (dir->d_type != DT_DIR) {
+ continue;
+ }
+
+ if (strncmp(dir->d_name, PROCESSGROUP_PID_PREFIX, strlen(PROCESSGROUP_PID_PREFIX))) {
+ continue;
+ }
+
+ snprintf(path, sizeof(path), "%s/%s", uid_path, dir->d_name);
+ SLOGV("removing %s\n", path);
+ rmdir(path);
+ }
+ }
+}
+
+void removeAllProcessGroups()
+{
+ SLOGV("removeAllProcessGroups()");
+ DIR *root = opendir(PROCESSGROUP_CGROUP_PATH);
+ if (root == NULL) {
+ SLOGE("failed to open %s: %s", PROCESSGROUP_CGROUP_PATH, strerror(errno));
+ }
+ if (root != NULL) {
+ struct dirent cur;
+ struct dirent *dir;
+ while ((readdir_r(root, &cur, &dir) == 0) && dir) {
+ char path[PROCESSGROUP_MAX_PATH_LEN];
+
+ if (dir->d_type != DT_DIR) {
+ continue;
+ }
+ if (strncmp(dir->d_name, PROCESSGROUP_UID_PREFIX, strlen(PROCESSGROUP_UID_PREFIX))) {
+ continue;
+ }
+
+ snprintf(path, sizeof(path), "%s/%s", PROCESSGROUP_CGROUP_PATH, dir->d_name);
+ removeUidProcessGroups(path);
+ SLOGV("removing %s\n", path);
+ rmdir(path);
+ }
+ }
+}
+
+static int killProcessGroupOnce(uid_t uid, int initialPid, int signal)
+{
+ int processes = 0;
+ struct ctx ctx;
+ pid_t pid;
+
+ ctx.initialized = false;
+
+ while ((pid = getOneAppProcess(uid, initialPid, &ctx)) >= 0) {
+ processes++;
+ SLOGV("sending processgroup kill to pid %d\n", pid);
+ int ret = kill(pid, signal);
+ if (ret == -1) {
+ SLOGV("failed to kill pid %d: %s", pid, strerror(errno));
+ }
+ }
+
+ if (ctx.initialized) {
+ close(ctx.fd);
+ }
+
+ return processes;
+}
+
+int killProcessGroup(uid_t uid, int initialPid, int signal)
+{
+ int processes;
+ int sleep_us = 100;
+
+ while ((processes = killProcessGroupOnce(uid, initialPid, signal)) > 0) {
+ SLOGV("killed %d processes for processgroup %d\n", processes, initialPid);
+ if (sleep_us < 128000) {
+ usleep(sleep_us);
+ sleep_us *= 2;
+ } else {
+ SLOGE("failed to kill %d processes for processgroup %d\n",
+ processes, initialPid);
+ break;
+ }
+ }
+
+ if (processes == 0) {
+ return removeProcessGroup(uid, initialPid);
+ } else {
+ return -1;
+ }
+}
+
+static int mkdirAndChown(const char *path, mode_t mode, uid_t uid, gid_t gid)
+{
+ int ret;
+
+ ret = mkdir(path, 0750);
+ if (ret < 0 && errno != EEXIST) {
+ return -errno;
+ }
+
+ ret = chown(path, AID_SYSTEM, AID_SYSTEM);
+ if (ret < 0) {
+ ret = -errno;
+ rmdir(path);
+ return ret;
+ }
+
+ return 0;
+}
+
+int createProcessGroup(uid_t uid, int initialPid)
+{
+ char path[PROCESSGROUP_MAX_PATH_LEN] = {0};
+ int ret;
+
+ convertUidToPath(path, sizeof(path), uid);
+
+ ret = mkdirAndChown(path, 0750, AID_SYSTEM, AID_SYSTEM);
+ if (ret < 0) {
+ SLOGE("failed to make and chown %s: %s", path, strerror(-ret));
+ return ret;
+ }
+
+ convertUidPidToPath(path, sizeof(path), uid, initialPid);
+
+ ret = mkdirAndChown(path, 0750, AID_SYSTEM, AID_SYSTEM);
+ if (ret < 0) {
+ SLOGE("failed to make and chown %s: %s", path, strerror(-ret));
+ return ret;
+ }
+
+ strlcat(path, PROCESSGROUP_CGROUP_PROCS_FILE, sizeof(path));
+
+ int fd = open(path, O_WRONLY);
+ if (fd < 0) {
+ ret = -errno;
+ SLOGE("failed to open %s: %s", path, strerror(errno));
+ return ret;
+ }
+
+ char pid[PROCESSGROUP_MAX_PID_LEN + 1] = {0};
+ int len = snprintf(pid, sizeof(pid), "%d", initialPid);
+
+ ret = write(fd, pid, len);
+ if (ret < 0) {
+ ret = -errno;
+ SLOGE("failed to write '%s' to %s: %s", pid, path, strerror(errno));
+ } else {
+ ret = 0;
+ }
+
+ close(fd);
+ return ret;
+}
+
diff --git a/libprocessgroup/processgroup_priv.h b/libprocessgroup/processgroup_priv.h
new file mode 100644
index 0000000..1895bf9
--- /dev/null
+++ b/libprocessgroup/processgroup_priv.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2014 Google, Inc
+ *
+ * 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 _PROCESSGROUP_PRIV_H_
+#define _PROCESSGROUP_PRIV_H_
+
+#define PROCESSGROUP_CGROUP_PATH "/acct"
+#define PROCESSGROUP_UID_PREFIX "uid_"
+#define PROCESSGROUP_PID_PREFIX "pid_"
+#define PROCESSGROUP_CGROUP_PROCS_FILE "/cgroup.procs"
+#define PROCESSGROUP_MAX_UID_LEN 11
+#define PROCESSGROUP_MAX_PID_LEN 11
+#define PROCESSGROUP_MAX_PATH_LEN \
+ (sizeof(PROCESSGROUP_CGROUP_PATH) + \
+ sizeof(PROCESSGROUP_UID_PREFIX) + 1 + \
+ PROCESSGROUP_MAX_UID_LEN + \
+ sizeof(PROCESSGROUP_PID_PREFIX) + 1 + \
+ PROCESSGROUP_MAX_PID_LEN + \
+ sizeof(PROCESSGROUP_CGROUP_PROCS_FILE) + \
+ 1)
+
+#endif
diff --git a/lmkd/Android.mk b/lmkd/Android.mk
index 2dd8af2..043a085 100644
--- a/lmkd/Android.mk
+++ b/lmkd/Android.mk
@@ -2,7 +2,7 @@
include $(CLEAR_VARS)
LOCAL_SRC_FILES := lmkd.c
-LOCAL_SHARED_LIBRARIES := libcutils liblog libm libc
+LOCAL_SHARED_LIBRARIES := libcutils liblog libm libc libprocessgroup
LOCAL_CFLAGS := -Werror
LOCAL_MODULE := lmkd
diff --git a/lmkd/lmkd.c b/lmkd/lmkd.c
index 369b5ad..1aeb182 100644
--- a/lmkd/lmkd.c
+++ b/lmkd/lmkd.c
@@ -32,6 +32,7 @@
#include <cutils/sockets.h>
#include <log/log.h>
+#include <processgroup/processgroup.h>
#ifndef __unused
#define __unused __attribute__((__unused__))
@@ -591,6 +592,7 @@
other_file * page_k, minfree * page_k, min_score_adj,
other_free * page_k, other_free >= 0 ? "above" : "below");
r = kill(pid, SIGKILL);
+ killProcessGroup(uid, pid, SIGKILL);
pid_remove(pid);
if (r) {
diff --git a/logd/tests/logd_test.cpp b/logd/tests/logd_test.cpp
index 957fdb5..4bea4be 100644
--- a/logd/tests/logd_test.cpp
+++ b/logd/tests/logd_test.cpp
@@ -503,13 +503,11 @@
(user_logger_content) ? yes : no,
(kernel_logger_available) ? yes : no,
(kernel_logger_content) ? yes : no,
- (user_logger_available && kernel_logger_available) ? "WARNING" : "ok",
+ (user_logger_available && kernel_logger_available) ? "ERROR" : "ok",
(user_logger_content && kernel_logger_content) ? "ERROR" : "ok");
- if (user_logger_available && kernel_logger_available) {
- printf("WARNING: kernel & user logger; both consuming resources!!!\n");
- }
-
+ EXPECT_EQ(0, user_logger_available && kernel_logger_available);
+ EXPECT_EQ(0, !user_logger_available && !kernel_logger_available);
EXPECT_EQ(0, user_logger_content && kernel_logger_content);
EXPECT_EQ(0, !user_logger_content && !kernel_logger_content);
}
diff --git a/toolbox/bsd-compatibility.h b/toolbox/bsd-compatibility.h
index a304631..abc3064 100644
--- a/toolbox/bsd-compatibility.h
+++ b/toolbox/bsd-compatibility.h
@@ -31,6 +31,9 @@
/* We want chown to support user.group as well as user:group. */
#define SUPPORT_DOT
+/* We don't localize /system/bin! */
+#define WITHOUT_NLS
+
__BEGIN_DECLS
extern int uid_from_user(const char* name, uid_t* uid);
diff --git a/toolbox/grep/grep.c b/toolbox/grep/grep.c
index 7b2c487..7314e13 100644
--- a/toolbox/grep/grep.c
+++ b/toolbox/grep/grep.c
@@ -159,7 +159,6 @@
{
fprintf(stderr, getstr(4), __progname);
fprintf(stderr, "%s", getstr(5));
- fprintf(stderr, "%s", getstr(5));
fprintf(stderr, "%s", getstr(6));
fprintf(stderr, "%s", getstr(7));
exit(2);
@@ -403,7 +402,7 @@
Aflag = 0;
else if (Aflag > LLONG_MAX / 10) {
errno = ERANGE;
- err(2, "%llu", Aflag);
+ err(2, NULL);
}
Aflag = Bflag = (Aflag * 10) + (c - '0');
break;
@@ -420,10 +419,10 @@
l = strtoull(optarg, &ep, 10);
if (((errno == ERANGE) && (l == ULLONG_MAX)) ||
((errno == EINVAL) && (l == 0)))
- err(2, "strtoull");
+ err(2, NULL);
else if (ep[0] != '\0') {
errno = EINVAL;
- err(2, "empty");
+ err(2, NULL);
}
if (c == 'A')
Aflag = l;
@@ -509,10 +508,10 @@
mcount = strtoull(optarg, &ep, 10);
if (((errno == ERANGE) && (mcount == ULLONG_MAX)) ||
((errno == EINVAL) && (mcount == 0)))
- err(2, "strtoull");
+ err(2, NULL);
else if (ep[0] != '\0') {
errno = EINVAL;
- err(2, "empty");
+ err(2, NULL);
}
break;
case 'n':
diff --git a/toolbox/grep/grep.h b/toolbox/grep/grep.h
index 6454f93..eafb00e 100644
--- a/toolbox/grep/grep.h
+++ b/toolbox/grep/grep.h
@@ -29,10 +29,6 @@
* SUCH DAMAGE.
*/
-#ifdef ANDROID
-#define WITHOUT_NLS
-#endif
-
#ifndef ANDROID
#include <bzlib.h>
#endif
diff --git a/toolbox/grep/util.c b/toolbox/grep/util.c
index 5712fee..ecd948d 100644
--- a/toolbox/grep/util.c
+++ b/toolbox/grep/util.c
@@ -1,4 +1,4 @@
-/* $NetBSD: util.c,v 1.16 2012/05/06 22:32:05 joerg Exp $ */
+/* $NetBSD: util.c,v 1.17 2013/01/21 03:24:43 msaitoh Exp $ */
/* $FreeBSD: head/usr.bin/grep/util.c 211496 2010-08-19 09:28:59Z des $ */
/* $OpenBSD: util.c,v 1.39 2010/07/02 22:18:03 tedu Exp $ */
@@ -34,7 +34,7 @@
#endif
#include <sys/cdefs.h>
-__RCSID("$NetBSD: util.c,v 1.16 2012/05/06 22:32:05 joerg Exp $");
+__RCSID("$NetBSD: util.c,v 1.17 2013/01/21 03:24:43 msaitoh Exp $");
#include <sys/stat.h>
#include <sys/types.h>
@@ -74,9 +74,10 @@
for (i = 0; i < fpatterns; ++i) {
if (fnmatch(fpattern[i].pat, fname, 0) == 0 ||
fnmatch(fpattern[i].pat, fname_base, 0) == 0) {
- if (fpattern[i].mode == EXCL_PAT)
+ if (fpattern[i].mode == EXCL_PAT) {
+ free(fname_copy);
return (false);
- else
+ } else
ret = true;
}
}
@@ -128,7 +129,7 @@
break;
default:
fts_flags = FTS_LOGICAL;
-
+
}
fts_flags |= FTS_NOSTAT | FTS_NOCHDIR;
@@ -273,7 +274,7 @@
return (c);
}
-#define iswword(x) (iswalnum((wint_t)(x)) || (x) == L'_')
+#define iswword(x) (iswalnum((x)) || (x) == L'_')
/*
* Processes a line comparing it with the specified patterns. Each pattern
@@ -474,13 +475,13 @@
if (!oflag)
fwrite(line->dat + a, matches[i].rm_so - a, 1,
stdout);
- if (color)
+ if (color)
fprintf(stdout, "\33[%sm\33[K", color);
- fwrite(line->dat + matches[i].rm_so,
+ fwrite(line->dat + matches[i].rm_so,
matches[i].rm_eo - matches[i].rm_so, 1,
stdout);
- if (color)
+ if (color)
fprintf(stdout, "\33[m\33[K");
a = matches[i].rm_eo;
if (oflag)