summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--adb/Android.mk2
-rw-r--r--adb/adb.c64
-rw-r--r--adb/adb.h1
-rw-r--r--adb/adb_auth.h4
-rw-r--r--adb/adb_auth_client.c55
-rw-r--r--adb/commandline.c5
-rw-r--r--adb/transport.c7
-rw-r--r--charger/charger.c2
-rw-r--r--debuggerd/arm/machine.c37
-rw-r--r--debuggerd/backtrace.c18
-rw-r--r--debuggerd/backtrace.h2
-rw-r--r--debuggerd/debuggerd.c13
-rw-r--r--debuggerd/mips/machine.c39
-rw-r--r--debuggerd/tombstone.c136
-rw-r--r--debuggerd/utility.c44
-rw-r--r--debuggerd/utility.h24
-rw-r--r--debuggerd/x86/machine.c12
-rw-r--r--fastboot/Android.mk1
-rw-r--r--fastboot/bootimg.c19
-rw-r--r--fastboot/fastboot.c112
-rw-r--r--fastboot/fastboot_protocol.txt173
-rw-r--r--fs_mgr/fs_mgr.c315
-rw-r--r--fs_mgr/fs_mgr_main.c9
-rw-r--r--fs_mgr/fs_mgr_priv.h24
-rw-r--r--fs_mgr/include/fs_mgr.h45
-rw-r--r--include/cutils/aref.h62
-rw-r--r--include/cutils/bitops.h69
-rw-r--r--include/cutils/trace.h254
-rw-r--r--include/cutils/zygote.h1
-rw-r--r--include/netutils/dhcp.h11
-rw-r--r--include/private/android_filesystem_config.h2
-rw-r--r--include/sync/sw_sync.h37
-rw-r--r--include/sync/sync.h8
-rw-r--r--include/system/audio.h1
-rw-r--r--include/system/graphics.h48
-rw-r--r--include/system/window.h1
-rw-r--r--init/builtins.c5
-rwxr-xr-xinit/init.c1
-rw-r--r--init/init_parser.c7
-rw-r--r--init/keychords.c8
-rwxr-xr-xinit/property_service.c6
-rw-r--r--libcutils/Android.mk1
-rw-r--r--libcutils/fs.c1
-rw-r--r--libcutils/trace.c168
-rw-r--r--libcutils/zygote.c38
-rw-r--r--libnetutils/dhcp_utils.c48
-rw-r--r--libpixelflinger/Android.mk11
-rw-r--r--libpixelflinger/codeflinger/ARMAssembler.cpp6
-rw-r--r--libpixelflinger/codeflinger/ARMAssembler.h5
-rw-r--r--libpixelflinger/codeflinger/ARMAssemblerInterface.cpp2
-rw-r--r--libpixelflinger/codeflinger/ARMAssemblerProxy.cpp2
-rw-r--r--libpixelflinger/codeflinger/ARMAssemblerProxy.h2
-rw-r--r--libpixelflinger/codeflinger/CodeCache.cpp2
-rw-r--r--libpixelflinger/codeflinger/CodeCache.h2
-rw-r--r--libpixelflinger/codeflinger/GGLAssembler.cpp2
-rw-r--r--libpixelflinger/codeflinger/GGLAssembler.h2
-rw-r--r--libpixelflinger/codeflinger/MIPSAssembler.cpp6
-rw-r--r--libpixelflinger/codeflinger/MIPSAssembler.h10
-rw-r--r--libpixelflinger/codeflinger/blending.cpp2
-rw-r--r--libpixelflinger/codeflinger/load_store.cpp2
-rw-r--r--libpixelflinger/codeflinger/texturing.cpp2
-rw-r--r--libpixelflinger/codeflinger/tinyutils/Errors.h (renamed from libpixelflinger/tinyutils/Errors.h)30
-rw-r--r--libpixelflinger/codeflinger/tinyutils/KeyedVector.h (renamed from libpixelflinger/tinyutils/KeyedVector.h)30
-rw-r--r--libpixelflinger/codeflinger/tinyutils/SharedBuffer.cpp (renamed from libpixelflinger/tinyutils/SharedBuffer.cpp)21
-rw-r--r--libpixelflinger/codeflinger/tinyutils/SharedBuffer.h (renamed from libpixelflinger/tinyutils/SharedBuffer.h)24
-rw-r--r--libpixelflinger/codeflinger/tinyutils/SortedVector.h (renamed from libpixelflinger/tinyutils/SortedVector.h)18
-rw-r--r--libpixelflinger/codeflinger/tinyutils/TypeHelpers.h (renamed from libpixelflinger/tinyutils/TypeHelpers.h)25
-rw-r--r--libpixelflinger/codeflinger/tinyutils/Vector.h (renamed from libpixelflinger/tinyutils/Vector.h)30
-rw-r--r--libpixelflinger/codeflinger/tinyutils/VectorImpl.cpp (renamed from libpixelflinger/tinyutils/VectorImpl.cpp)31
-rw-r--r--libpixelflinger/codeflinger/tinyutils/VectorImpl.h (renamed from libpixelflinger/tinyutils/VectorImpl.h)24
-rw-r--r--libpixelflinger/codeflinger/tinyutils/smartpointer.h (renamed from libpixelflinger/tinyutils/smartpointer.h)24
-rw-r--r--libusbhost/usbhost.c83
-rw-r--r--logwrapper/Android.mk29
-rw-r--r--logwrapper/include/logwrap/logwrap.h60
-rw-r--r--logwrapper/logwrap.c261
-rw-r--r--logwrapper/logwrapper.c139
-rw-r--r--rootdir/Android.mk33
-rw-r--r--rootdir/etc/init.goldfish.rc83
-rwxr-xr-xrootdir/etc/init.goldfish.sh68
-rw-r--r--rootdir/etc/ueventd.goldfish.rc5
-rw-r--r--rootdir/etc/vold.fstab24
-rw-r--r--rootdir/init.rc16
-rw-r--r--rootdir/init.usb.rc1
-rw-r--r--sdcard/sdcard.c9
-rw-r--r--toolbox/Android.mk1
-rw-r--r--toolbox/clear.c41
-rw-r--r--toolbox/du.c4
-rw-r--r--toolbox/renice.c64
88 files changed, 2272 insertions, 904 deletions
diff --git a/adb/Android.mk b/adb/Android.mk
index 32dd95a46..a80397875 100644
--- a/adb/Android.mk
+++ b/adb/Android.mk
@@ -17,6 +17,7 @@ ifeq ($(HOST_OS),linux)
USB_SRCS := usb_linux.c
EXTRA_SRCS := get_my_path_linux.c
LOCAL_LDLIBS += -lrt -ldl -lpthread
+ LOCAL_CFLAGS += -DWORKAROUND_BUG6558362
endif
ifeq ($(HOST_OS),darwin)
@@ -77,6 +78,7 @@ endif
LOCAL_CFLAGS += -O2 -g -DADB_HOST=1 -Wall -Wno-unused-parameter
LOCAL_CFLAGS += -D_XOPEN_SOURCE -D_GNU_SOURCE
LOCAL_MODULE := adb
+LOCAL_MODULE_TAGS := debug
LOCAL_STATIC_LIBRARIES := libzipfile libunz libcrypto_static $(EXTRA_STATIC_LIBS)
ifeq ($(USE_SYSDEPS_WIN32),)
diff --git a/adb/adb.c b/adb/adb.c
index 71b7a8bc0..d2a2d27eb 100644
--- a/adb/adb.c
+++ b/adb/adb.c
@@ -326,7 +326,7 @@ static void send_connect(atransport *t)
send_packet(cp, t);
}
-static void send_auth_request(atransport *t)
+void send_auth_request(atransport *t)
{
D("Calling send_auth_request\n");
apacket *p;
@@ -403,6 +403,8 @@ static char *connection_state_name(atransport *t)
return "device";
case CS_OFFLINE:
return "offline";
+ case CS_UNAUTHORIZED:
+ return "unauthorized";
default:
return "unknown";
}
@@ -532,6 +534,7 @@ void handle_packet(apacket *p, atransport *t)
case A_AUTH:
if (p->msg.arg0 == ADB_AUTH_TOKEN) {
+ t->connection_state = CS_UNAUTHORIZED;
t->key = adb_auth_nextkey(t->key);
if (t->key) {
send_auth_response(p->data, p->msg.data_length, t);
@@ -984,6 +987,33 @@ void start_device_log(void)
#endif
#if ADB_HOST
+
+#ifdef WORKAROUND_BUG6558362
+#include <sched.h>
+#define AFFINITY_ENVVAR "ADB_CPU_AFFINITY_BUG6558362"
+void adb_set_affinity(void)
+{
+ cpu_set_t cpu_set;
+ const char* cpunum_str = getenv(AFFINITY_ENVVAR);
+ char* strtol_res;
+ int cpu_num;
+
+ if (!cpunum_str || !*cpunum_str)
+ return;
+ cpu_num = strtol(cpunum_str, &strtol_res, 0);
+ if (*strtol_res != '\0')
+ fatal("bad number (%s) in env var %s. Expecting 0..n.\n", cpunum_str, AFFINITY_ENVVAR);
+
+ sched_getaffinity(0, sizeof(cpu_set), &cpu_set);
+ D("orig cpu_set[0]=0x%08lx\n", cpu_set.__bits[0]);
+ CPU_ZERO(&cpu_set);
+ CPU_SET(cpu_num, &cpu_set);
+ sched_setaffinity(0, sizeof(cpu_set), &cpu_set);
+ sched_getaffinity(0, sizeof(cpu_set), &cpu_set);
+ D("new cpu_set[0]=0x%08lx\n", cpu_set.__bits[0]);
+}
+#endif
+
int launch_server(int server_port)
{
#ifdef HAVE_WIN32_PROC
@@ -1154,6 +1184,32 @@ void build_local_name(char* target_str, size_t target_size, int server_port)
}
#if !ADB_HOST
+
+static void drop_capabilities_bounding_set_if_needed() {
+#ifdef ALLOW_ADBD_ROOT
+ char value[PROPERTY_VALUE_MAX];
+ property_get("ro.debuggable", value, "");
+ if (strcmp(value, "1") == 0) {
+ return;
+ }
+#endif
+ int i;
+ for (i = 0; prctl(PR_CAPBSET_READ, i, 0, 0, 0) >= 0; i++) {
+ if ((i == CAP_SETUID) || (i == CAP_SETGID)) {
+ // CAP_SETUID CAP_SETGID needed by /system/bin/run-as
+ continue;
+ }
+ int err = prctl(PR_CAPBSET_DROP, i, 0, 0, 0);
+
+ // Some kernels don't have file capabilities compiled in, and
+ // prctl(PR_CAPBSET_DROP) returns EINVAL. Don't automatically
+ // die when we see such misconfigured kernels.
+ if ((err < 0) && (errno != EINVAL)) {
+ exit(1);
+ }
+ }
+}
+
static int should_drop_privileges() {
#ifndef ALLOW_ADBD_ROOT
return 1;
@@ -1208,6 +1264,10 @@ int adb_main(int is_daemon, int server_port)
#if ADB_HOST
HOST = 1;
+
+#ifdef WORKAROUND_BUG6558362
+ if(is_daemon) adb_set_affinity();
+#endif
usb_vendors_init();
usb_init();
local_init(DEFAULT_ADB_LOCAL_TRANSPORT_PORT);
@@ -1244,6 +1304,8 @@ int adb_main(int is_daemon, int server_port)
exit(1);
}
+ drop_capabilities_bounding_set_if_needed();
+
/* add extra groups:
** AID_ADB to access the USB driver
** AID_LOG to read system logs (adb logcat)
diff --git a/adb/adb.h b/adb/adb.h
index 9da8af8bf..a01d460e4 100644
--- a/adb/adb.h
+++ b/adb/adb.h
@@ -468,6 +468,7 @@ int connection_state(atransport *t);
#define CS_RECOVERY 4
#define CS_NOPERM 5 /* Insufficient permissions to communicate with the device */
#define CS_SIDELOAD 6
+#define CS_UNAUTHORIZED 7
extern int HOST;
extern int SHELL_EXIT_NOTIFY_FD;
diff --git a/adb/adb_auth.h b/adb/adb_auth.h
index 1fffa4976..b24c67413 100644
--- a/adb/adb_auth.h
+++ b/adb/adb_auth.h
@@ -20,6 +20,8 @@
void adb_auth_init(void);
void adb_auth_verified(atransport *t);
+void send_auth_request(atransport *t);
+
/* AUTH packets first argument */
/* Request */
#define ADB_AUTH_TOKEN 1
@@ -36,7 +38,6 @@ int adb_auth_get_userkey(unsigned char *data, size_t len);
static inline int adb_auth_generate_token(void *token, size_t token_size) { return 0; }
static inline int adb_auth_verify(void *token, void *sig, int siglen) { return 0; }
static inline void adb_auth_confirm_key(unsigned char *data, size_t len, atransport *t) { }
-static inline void adb_auth_reload_keys(void) { }
#else // !ADB_HOST
@@ -47,7 +48,6 @@ static inline int adb_auth_get_userkey(unsigned char *data, size_t len) { return
int adb_auth_generate_token(void *token, size_t token_size);
int adb_auth_verify(void *token, void *sig, int siglen);
void adb_auth_confirm_key(unsigned char *data, size_t len, atransport *t);
-void adb_auth_reload_keys(void);
#endif // ADB_HOST
diff --git a/adb/adb_auth_client.c b/adb/adb_auth_client.c
index 0b4913ef4..763b448d7 100644
--- a/adb/adb_auth_client.c
+++ b/adb/adb_auth_client.c
@@ -34,8 +34,6 @@ struct adb_public_key {
RSAPublicKey key;
};
-static struct listnode key_list;
-
static char *key_paths[] = {
"/adb_keys",
"/data/misc/adb/adb_keys",
@@ -45,6 +43,10 @@ static char *key_paths[] = {
static fdevent listener_fde;
static int framework_fd = -1;
+static void usb_disconnected(void* unused, atransport* t);
+static struct adisconnect usb_disconnect = { usb_disconnected, 0, 0, 0 };
+static atransport* usb_transport;
+static bool needs_retry = false;
static void read_keys(const char *file, struct listnode *list)
{
@@ -102,18 +104,18 @@ static void free_keys(struct listnode *list)
}
}
-void adb_auth_reload_keys(void)
+static void load_keys(struct listnode *list)
{
char *path;
char **paths = key_paths;
struct stat buf;
- free_keys(&key_list);
+ list_init(list);
while ((path = *paths++)) {
if (!stat(path, &buf)) {
D("Loading keys from '%s'\n", path);
- read_keys(path, &key_list);
+ read_keys(path, list);
}
}
}
@@ -137,37 +139,50 @@ int adb_auth_verify(void *token, void *sig, int siglen)
{
struct listnode *item;
struct adb_public_key *key;
- int ret;
+ struct listnode key_list;
+ int ret = 0;
if (siglen != RSANUMBYTES)
return 0;
+ load_keys(&key_list);
+
list_for_each(item, &key_list) {
key = node_to_item(item, struct adb_public_key, node);
ret = RSA_verify(&key->key, sig, siglen, token);
if (ret)
- return 1;
+ break;
}
- return 0;
+ free_keys(&key_list);
+
+ return ret;
+}
+
+static void usb_disconnected(void* unused, atransport* t)
+{
+ D("USB disconnect\n");
+ remove_transport_disconnect(usb_transport, &usb_disconnect);
+ usb_transport = NULL;
+ needs_retry = false;
}
static void adb_auth_event(int fd, unsigned events, void *data)
{
- atransport *t = data;
char response[2];
int ret;
if (events & FDE_READ) {
ret = unix_read(fd, response, sizeof(response));
if (ret < 0) {
- D("Disconnect");
- fdevent_remove(&t->auth_fde);
+ D("Framework disconnect\n");
+ if (usb_transport)
+ fdevent_remove(&usb_transport->auth_fde);
framework_fd = -1;
}
else if (ret == 2 && response[0] == 'O' && response[1] == 'K') {
- adb_auth_reload_keys();
- adb_auth_verified(t);
+ if (usb_transport)
+ adb_auth_verified(usb_transport);
}
}
}
@@ -177,8 +192,14 @@ void adb_auth_confirm_key(unsigned char *key, size_t len, atransport *t)
char msg[MAX_PAYLOAD];
int ret;
+ if (!usb_transport) {
+ usb_transport = t;
+ add_transport_disconnect(t, &usb_disconnect);
+ }
+
if (framework_fd < 0) {
D("Client not connected\n");
+ needs_retry = true;
return;
}
@@ -219,15 +240,17 @@ static void adb_auth_listener(int fd, unsigned events, void *data)
}
framework_fd = s;
+
+ if (needs_retry) {
+ needs_retry = false;
+ send_auth_request(usb_transport);
+ }
}
void adb_auth_init(void)
{
int fd, ret;
- list_init(&key_list);
- adb_auth_reload_keys();
-
fd = android_get_control_socket("adbd");
if (fd < 0) {
D("Failed to get adbd socket\n");
diff --git a/adb/commandline.c b/adb/commandline.c
index a927423b4..27a175498 100644
--- a/adb/commandline.c
+++ b/adb/commandline.c
@@ -144,12 +144,15 @@ void help()
" adb bugreport - return all information from the device\n"
" that should be included in a bug report.\n"
"\n"
- " adb backup [-f <file>] [-apk|-noapk] [-shared|-noshared] [-all] [-system|-nosystem] [<packages...>]\n"
+ " adb backup [-f <file>] [-apk|-noapk] [-obb|-noobb] [-shared|-noshared] [-all] [-system|-nosystem] [<packages...>]\n"
" - write an archive of the device's data to <file>.\n"
" If no -f option is supplied then the data is written\n"
" to \"backup.ab\" in the current directory.\n"
" (-apk|-noapk enable/disable backup of the .apks themselves\n"
" in the archive; the default is noapk.)\n"
+ " (-obb|-noobb enable/disable backup of any installed apk expansion\n"
+ " (aka .obb) files associated with each application; the default\n"
+ " is noobb.)\n"
" (-shared|-noshared enable/disable backup of the device's\n"
" shared storage / SD card contents; the default is noshared.)\n"
" (-all means to back up all installed applications)\n"
diff --git a/adb/transport.c b/adb/transport.c
index 9fd6cc2e6..b4abb66ec 100644
--- a/adb/transport.c
+++ b/adb/transport.c
@@ -851,6 +851,12 @@ retry:
adb_mutex_unlock(&transport_lock);
if (result) {
+ if (result->connection_state == CS_UNAUTHORIZED) {
+ if (error_out)
+ *error_out = "device unauthorized. Please check the confirmation dialog on your device.";
+ result = NULL;
+ }
+
/* offline devices are ignored -- they are either being born or dying */
if (result && result->connection_state == CS_OFFLINE) {
if (error_out)
@@ -888,6 +894,7 @@ static const char *statename(atransport *t)
case CS_RECOVERY: return "recovery";
case CS_SIDELOAD: return "sideload";
case CS_NOPERM: return "no permissions";
+ case CS_UNAUTHORIZED: return "unauthorized";
default: return "unknown";
}
}
diff --git a/charger/charger.c b/charger/charger.c
index 353bdf086..66ddeaf9c 100644
--- a/charger/charger.c
+++ b/charger/charger.c
@@ -610,7 +610,7 @@ static int draw_text(const char *str, int x, int y)
x = (gr_fb_width() - str_len_px) / 2;
if (y < 0)
y = (gr_fb_height() - char_height) / 2;
- gr_text(x, y, str);
+ gr_text(x, y, str, 0);
return y + char_height;
}
diff --git a/debuggerd/arm/machine.c b/debuggerd/arm/machine.c
index 160db7b1e..67e3028f5 100644
--- a/debuggerd/arm/machine.c
+++ b/debuggerd/arm/machine.c
@@ -42,7 +42,7 @@
#endif
#endif
-static void dump_memory(log_t* log, pid_t tid, uintptr_t addr, bool at_fault) {
+static void dump_memory(log_t* log, pid_t tid, uintptr_t addr, int scopeFlags) {
char code_buffer[64]; /* actual 8+1+((8+1)*4) + 1 == 45 */
char ascii_buffer[32]; /* actual 16 + 1 == 17 */
uintptr_t p, end;
@@ -102,7 +102,7 @@ static void dump_memory(log_t* log, pid_t tid, uintptr_t addr, bool at_fault) {
p += 4;
}
*asc_out = '\0';
- _LOG(log, !at_fault, " %s %s\n", code_buffer, ascii_buffer);
+ _LOG(log, scopeFlags, " %s %s\n", code_buffer, ascii_buffer);
}
}
@@ -117,6 +117,8 @@ void dump_memory_and_code(const ptrace_context_t* context __attribute((unused)),
return;
}
+ int scopeFlags = at_fault ? SCOPE_AT_FAULT : 0;
+
if (at_fault && DUMP_MEMORY_FOR_ALL_REGISTERS) {
static const char REG_NAMES[] = "r0r1r2r3r4r5r6r7r8r9slfpipsp";
@@ -132,17 +134,18 @@ void dump_memory_and_code(const ptrace_context_t* context __attribute((unused)),
continue;
}
- _LOG(log, false, "\nmemory near %.2s:\n", &REG_NAMES[reg * 2]);
- dump_memory(log, tid, addr, at_fault);
+ _LOG(log, scopeFlags | SCOPE_SENSITIVE, "\nmemory near %.2s:\n", &REG_NAMES[reg * 2]);
+ dump_memory(log, tid, addr, scopeFlags | SCOPE_SENSITIVE);
}
}
- _LOG(log, !at_fault, "\ncode around pc:\n");
- dump_memory(log, tid, (uintptr_t)regs.ARM_pc, at_fault);
+ /* explicitly allow upload of code dump logging */
+ _LOG(log, scopeFlags, "\ncode around pc:\n");
+ dump_memory(log, tid, (uintptr_t)regs.ARM_pc, scopeFlags);
if (regs.ARM_pc != regs.ARM_lr) {
- _LOG(log, !at_fault, "\ncode around lr:\n");
- dump_memory(log, tid, (uintptr_t)regs.ARM_lr, at_fault);
+ _LOG(log, scopeFlags, "\ncode around lr:\n");
+ dump_memory(log, tid, (uintptr_t)regs.ARM_lr, scopeFlags);
}
}
@@ -150,20 +153,20 @@ void dump_registers(const ptrace_context_t* context __attribute((unused)),
log_t* log, pid_t tid, bool at_fault)
{
struct pt_regs r;
- bool only_in_tombstone = !at_fault;
+ int scopeFlags = at_fault ? SCOPE_AT_FAULT : 0;
if(ptrace(PTRACE_GETREGS, tid, 0, &r)) {
- _LOG(log, only_in_tombstone, "cannot get registers: %s\n", strerror(errno));
+ _LOG(log, scopeFlags, "cannot get registers: %s\n", strerror(errno));
return;
}
- _LOG(log, only_in_tombstone, " r0 %08x r1 %08x r2 %08x r3 %08x\n",
+ _LOG(log, scopeFlags, " r0 %08x r1 %08x r2 %08x r3 %08x\n",
(uint32_t)r.ARM_r0, (uint32_t)r.ARM_r1, (uint32_t)r.ARM_r2, (uint32_t)r.ARM_r3);
- _LOG(log, only_in_tombstone, " r4 %08x r5 %08x r6 %08x r7 %08x\n",
+ _LOG(log, scopeFlags, " r4 %08x r5 %08x r6 %08x r7 %08x\n",
(uint32_t)r.ARM_r4, (uint32_t)r.ARM_r5, (uint32_t)r.ARM_r6, (uint32_t)r.ARM_r7);
- _LOG(log, only_in_tombstone, " r8 %08x r9 %08x sl %08x fp %08x\n",
+ _LOG(log, scopeFlags, " r8 %08x r9 %08x sl %08x fp %08x\n",
(uint32_t)r.ARM_r8, (uint32_t)r.ARM_r9, (uint32_t)r.ARM_r10, (uint32_t)r.ARM_fp);
- _LOG(log, only_in_tombstone, " ip %08x sp %08x lr %08x pc %08x cpsr %08x\n",
+ _LOG(log, scopeFlags, " ip %08x sp %08x lr %08x pc %08x cpsr %08x\n",
(uint32_t)r.ARM_ip, (uint32_t)r.ARM_sp, (uint32_t)r.ARM_lr,
(uint32_t)r.ARM_pc, (uint32_t)r.ARM_cpsr);
@@ -172,14 +175,14 @@ void dump_registers(const ptrace_context_t* context __attribute((unused)),
int i;
if(ptrace(PTRACE_GETVFPREGS, tid, 0, &vfp_regs)) {
- _LOG(log, only_in_tombstone, "cannot get registers: %s\n", strerror(errno));
+ _LOG(log, scopeFlags, "cannot get registers: %s\n", strerror(errno));
return;
}
for (i = 0; i < NUM_VFP_REGS; i += 2) {
- _LOG(log, only_in_tombstone, " d%-2d %016llx d%-2d %016llx\n",
+ _LOG(log, scopeFlags, " d%-2d %016llx d%-2d %016llx\n",
i, vfp_regs.fpregs[i], i+1, vfp_regs.fpregs[i+1]);
}
- _LOG(log, only_in_tombstone, " scr %08lx\n", vfp_regs.fpscr);
+ _LOG(log, scopeFlags, " scr %08lx\n", vfp_regs.fpscr);
#endif
}
diff --git a/debuggerd/backtrace.c b/debuggerd/backtrace.c
index ba76e7dc3..f42f24c42 100644
--- a/debuggerd/backtrace.c
+++ b/debuggerd/backtrace.c
@@ -51,15 +51,15 @@ static void dump_process_header(log_t* log, pid_t pid) {
localtime_r(&t, &tm);
char timestr[64];
strftime(timestr, sizeof(timestr), "%F %T", &tm);
- _LOG(log, false, "\n\n----- pid %d at %s -----\n", pid, timestr);
+ _LOG(log, SCOPE_AT_FAULT, "\n\n----- pid %d at %s -----\n", pid, timestr);
if (procname) {
- _LOG(log, false, "Cmd line: %s\n", procname);
+ _LOG(log, SCOPE_AT_FAULT, "Cmd line: %s\n", procname);
}
}
static void dump_process_footer(log_t* log, pid_t pid) {
- _LOG(log, false, "\n----- end %d -----\n", pid);
+ _LOG(log, SCOPE_AT_FAULT, "\n----- end %d -----\n", pid);
}
static void dump_thread(log_t* log, pid_t tid, ptrace_context_t* context, bool attached,
@@ -81,10 +81,11 @@ static void dump_thread(log_t* log, pid_t tid, ptrace_context_t* context, bool a
}
}
- _LOG(log, false, "\n\"%s\" sysTid=%d\n", threadname ? threadname : "<unknown>", tid);
+ _LOG(log, SCOPE_AT_FAULT, "\n\"%s\" sysTid=%d\n",
+ threadname ? threadname : "<unknown>", tid);
if (!attached && ptrace(PTRACE_ATTACH, tid, 0, 0) < 0) {
- _LOG(log, false, "Could not attach to thread: %s\n", strerror(errno));
+ _LOG(log, SCOPE_AT_FAULT, "Could not attach to thread: %s\n", strerror(errno));
return;
}
@@ -93,7 +94,7 @@ static void dump_thread(log_t* log, pid_t tid, ptrace_context_t* context, bool a
backtrace_frame_t backtrace[STACK_DEPTH];
ssize_t frames = unwind_backtrace_ptrace(tid, context, backtrace, 0, STACK_DEPTH);
if (frames <= 0) {
- _LOG(log, false, "Could not obtain stack trace for thread.\n");
+ _LOG(log, SCOPE_AT_FAULT, "Could not obtain stack trace for thread.\n");
} else {
backtrace_symbol_t backtrace_symbols[STACK_DEPTH];
get_backtrace_symbols_ptrace(context, backtrace, frames, backtrace_symbols);
@@ -101,7 +102,7 @@ static void dump_thread(log_t* log, pid_t tid, ptrace_context_t* context, bool a
char line[MAX_BACKTRACE_LINE_LENGTH];
format_backtrace_line(i, &backtrace[i], &backtrace_symbols[i],
line, MAX_BACKTRACE_LINE_LENGTH);
- _LOG(log, false, " %s\n", line);
+ _LOG(log, SCOPE_AT_FAULT, " %s\n", line);
}
free_backtrace_symbols(backtrace_symbols, frames);
}
@@ -112,10 +113,11 @@ static void dump_thread(log_t* log, pid_t tid, ptrace_context_t* context, bool a
}
}
-void dump_backtrace(int fd, pid_t pid, pid_t tid, bool* detach_failed,
+void dump_backtrace(int fd, int amfd, pid_t pid, pid_t tid, bool* detach_failed,
int* total_sleep_time_usec) {
log_t log;
log.tfd = fd;
+ log.amfd = amfd;
log.quiet = true;
ptrace_context_t* context = load_ptrace_context(tid);
diff --git a/debuggerd/backtrace.h b/debuggerd/backtrace.h
index ec7d20ff4..c5c786a01 100644
--- a/debuggerd/backtrace.h
+++ b/debuggerd/backtrace.h
@@ -25,7 +25,7 @@
/* Dumps a backtrace using a format similar to what Dalvik uses so that the result
* can be intermixed in a bug report. */
-void dump_backtrace(int fd, pid_t pid, pid_t tid, bool* detach_failed,
+void dump_backtrace(int fd, int amfd, pid_t pid, pid_t tid, bool* detach_failed,
int* total_sleep_time_usec);
#endif // _DEBUGGERD_BACKTRACE_H
diff --git a/debuggerd/debuggerd.c b/debuggerd/debuggerd.c
index 99e6f13c3..da2e9b0e1 100644
--- a/debuggerd/debuggerd.c
+++ b/debuggerd/debuggerd.c
@@ -203,7 +203,7 @@ static int read_request(int fd, debugger_request_t* out_request) {
pollfds[0].revents = 0;
status = TEMP_FAILURE_RETRY(poll(pollfds, 1, 3000));
if (status != 1) {
- LOG("timed out reading tid\n");
+ LOG("timed out reading tid (from pid=%d uid=%d)\n", cr.pid, cr.uid);
return -1;
}
@@ -211,13 +211,15 @@ static int read_request(int fd, debugger_request_t* out_request) {
memset(&msg, 0, sizeof(msg));
status = TEMP_FAILURE_RETRY(read(fd, &msg, sizeof(msg)));
if (status < 0) {
- LOG("read failure? %s\n", strerror(errno));
+ LOG("read failure? %s (pid=%d uid=%d)\n",
+ strerror(errno), cr.pid, cr.uid);
return -1;
}
if (status == sizeof(debugger_msg_t)) {
XLOG("crash request of size %d abort_msg_address=%#08x\n", status, msg.abort_msg_address);
} else {
- LOG("invalid crash request of size %d\n", status);
+ LOG("invalid crash request of size %d (from pid=%d uid=%d)\n",
+ status, cr.pid, cr.uid);
return -1;
}
@@ -250,7 +252,7 @@ static int read_request(int fd, debugger_request_t* out_request) {
return -1;
}
} else {
- /* No one else is not allowed to dump arbitrary processes. */
+ /* No one else is allowed to dump arbitrary processes. */
return -1;
}
return 0;
@@ -318,7 +320,8 @@ static void handle_request(int fd) {
&total_sleep_time_usec);
} else if (request.action == DEBUGGER_ACTION_DUMP_BACKTRACE) {
XLOG("stopped -- dumping to fd\n");
- dump_backtrace(fd, request.pid, request.tid, &detach_failed,
+ dump_backtrace(fd, -1,
+ request.pid, request.tid, &detach_failed,
&total_sleep_time_usec);
} else {
XLOG("stopped -- continuing\n");
diff --git a/debuggerd/mips/machine.c b/debuggerd/mips/machine.c
index dba1711ec..65fdf02f8 100644
--- a/debuggerd/mips/machine.c
+++ b/debuggerd/mips/machine.c
@@ -36,7 +36,7 @@
#define R(x) ((unsigned int)(x))
-static void dump_memory(log_t* log, pid_t tid, uintptr_t addr, bool at_fault) {
+static void dump_memory(log_t* log, pid_t tid, uintptr_t addr, int scopeFlags) {
char code_buffer[64]; /* actual 8+1+((8+1)*4) + 1 == 45 */
char ascii_buffer[32]; /* actual 16 + 1 == 17 */
uintptr_t p, end;
@@ -92,7 +92,7 @@ static void dump_memory(log_t* log, pid_t tid, uintptr_t addr, bool at_fault) {
p += 4;
}
*asc_out = '\0';
- _LOG(log, !at_fault, " %s %s\n", code_buffer, ascii_buffer);
+ _LOG(log, scopeFlags, " %s %s\n", code_buffer, ascii_buffer);
}
}
@@ -107,6 +107,7 @@ void dump_memory_and_code(const ptrace_context_t* context __attribute((unused)),
return;
}
+ int scopeFlags = at_fault ? SCOPE_AT_FAULT : 0;
if (at_fault && DUMP_MEMORY_FOR_ALL_REGISTERS) {
static const char REG_NAMES[] = "$0atv0v1a0a1a2a3t0t1t2t3t4t5t6t7s0s1s2s3s4s5s6s7t8t9k0k1gpsps8ra";
@@ -129,20 +130,20 @@ void dump_memory_and_code(const ptrace_context_t* context __attribute((unused)),
continue;
}
- _LOG(log, false, "\nmemory near %.2s:\n", &REG_NAMES[reg * 2]);
- dump_memory(log, tid, addr, at_fault);
+ _LOG(log, scopeFlags | SCOPE_SENSITIVE, "\nmemory near %.2s:\n", &REG_NAMES[reg * 2]);
+ dump_memory(log, tid, addr, scopeFlags | SCOPE_SENSITIVE);
}
}
unsigned int pc = R(r.cp0_epc);
unsigned int ra = R(r.regs[31]);
- _LOG(log, !at_fault, "\ncode around pc:\n");
- dump_memory(log, tid, (uintptr_t)pc, at_fault);
+ _LOG(log, scopeFlags, "\ncode around pc:\n");
+ dump_memory(log, tid, (uintptr_t)pc, scopeFlags);
if (pc != ra) {
- _LOG(log, !at_fault, "\ncode around ra:\n");
- dump_memory(log, tid, (uintptr_t)ra, at_fault);
+ _LOG(log, scopeFlags, "\ncode around ra:\n");
+ dump_memory(log, tid, (uintptr_t)ra, scopeFlags);
}
}
@@ -150,29 +151,29 @@ void dump_registers(const ptrace_context_t* context __attribute((unused)),
log_t* log, pid_t tid, bool at_fault)
{
pt_regs_mips_t r;
- bool only_in_tombstone = !at_fault;
+ int scopeFlags = at_fault ? SCOPE_AT_FAULT : 0;
if(ptrace(PTRACE_GETREGS, tid, 0, &r)) {
- _LOG(log, only_in_tombstone, "cannot get registers: %s\n", strerror(errno));
+ _LOG(log, scopeFlags, "cannot get registers: %s\n", strerror(errno));
return;
}
- _LOG(log, only_in_tombstone, " zr %08x at %08x v0 %08x v1 %08x\n",
+ _LOG(log, scopeFlags, " zr %08x at %08x v0 %08x v1 %08x\n",
R(r.regs[0]), R(r.regs[1]), R(r.regs[2]), R(r.regs[3]));
- _LOG(log, only_in_tombstone, " a0 %08x a1 %08x a2 %08x a3 %08x\n",
+ _LOG(log, scopeFlags, " a0 %08x a1 %08x a2 %08x a3 %08x\n",
R(r.regs[4]), R(r.regs[5]), R(r.regs[6]), R(r.regs[7]));
- _LOG(log, only_in_tombstone, " t0 %08x t1 %08x t2 %08x t3 %08x\n",
+ _LOG(log, scopeFlags, " t0 %08x t1 %08x t2 %08x t3 %08x\n",
R(r.regs[8]), R(r.regs[9]), R(r.regs[10]), R(r.regs[11]));
- _LOG(log, only_in_tombstone, " t4 %08x t5 %08x t6 %08x t7 %08x\n",
+ _LOG(log, scopeFlags, " t4 %08x t5 %08x t6 %08x t7 %08x\n",
R(r.regs[12]), R(r.regs[13]), R(r.regs[14]), R(r.regs[15]));
- _LOG(log, only_in_tombstone, " s0 %08x s1 %08x s2 %08x s3 %08x\n",
+ _LOG(log, scopeFlags, " s0 %08x s1 %08x s2 %08x s3 %08x\n",
R(r.regs[16]), R(r.regs[17]), R(r.regs[18]), R(r.regs[19]));
- _LOG(log, only_in_tombstone, " s4 %08x s5 %08x s6 %08x s7 %08x\n",
+ _LOG(log, scopeFlags, " s4 %08x s5 %08x s6 %08x s7 %08x\n",
R(r.regs[20]), R(r.regs[21]), R(r.regs[22]), R(r.regs[23]));
- _LOG(log, only_in_tombstone, " t8 %08x t9 %08x k0 %08x k1 %08x\n",
+ _LOG(log, scopeFlags, " t8 %08x t9 %08x k0 %08x k1 %08x\n",
R(r.regs[24]), R(r.regs[25]), R(r.regs[26]), R(r.regs[27]));
- _LOG(log, only_in_tombstone, " gp %08x sp %08x s8 %08x ra %08x\n",
+ _LOG(log, scopeFlags, " gp %08x sp %08x s8 %08x ra %08x\n",
R(r.regs[28]), R(r.regs[29]), R(r.regs[30]), R(r.regs[31]));
- _LOG(log, only_in_tombstone, " hi %08x lo %08x bva %08x epc %08x\n",
+ _LOG(log, scopeFlags, " hi %08x lo %08x bva %08x epc %08x\n",
R(r.hi), R(r.lo), R(r.cp0_badvaddr), R(r.cp0_epc));
}
diff --git a/debuggerd/tombstone.c b/debuggerd/tombstone.c
index da5f03c99..714612053 100644
--- a/debuggerd/tombstone.c
+++ b/debuggerd/tombstone.c
@@ -35,6 +35,9 @@
#include <corkscrew/demangle.h>
#include <corkscrew/backtrace.h>
+#include <sys/socket.h>
+#include <linux/un.h>
+
#include <selinux/android.h>
#include "machine.h"
@@ -47,6 +50,9 @@
#define MAX_TOMBSTONES 10
#define TOMBSTONE_DIR "/data/tombstones"
+/* Must match the path defined in NativeCrashListener.java */
+#define NCRASH_SOCKET_PATH "/data/system/ndebugsocket"
+
#define typecheck(x,y) { \
typeof(x) __dummy1; \
typeof(y) __dummy2; \
@@ -157,7 +163,7 @@ static void dump_revision_info(log_t* log)
property_get("ro.revision", revision, "unknown");
- _LOG(log, false, "Revision: '%s'\n", revision);
+ _LOG(log, SCOPE_AT_FAULT, "Revision: '%s'\n", revision);
}
static void dump_build_info(log_t* log)
@@ -166,7 +172,7 @@ static void dump_build_info(log_t* log)
property_get("ro.build.fingerprint", fingerprint, "unknown");
- _LOG(log, false, "Build fingerprint: '%s'\n", fingerprint);
+ _LOG(log, SCOPE_AT_FAULT, "Build fingerprint: '%s'\n", fingerprint);
}
static void dump_fault_addr(log_t* log, pid_t tid, int sig)
@@ -174,15 +180,15 @@ static void dump_fault_addr(log_t* log, pid_t tid, int sig)
siginfo_t si;
memset(&si, 0, sizeof(si));
- if (ptrace(PTRACE_GETSIGINFO, tid, 0, &si)){
- _LOG(log, false, "cannot get siginfo: %s\n", strerror(errno));
+ if(ptrace(PTRACE_GETSIGINFO, tid, 0, &si)){
+ _LOG(log, SCOPE_AT_FAULT, "cannot get siginfo: %s\n", strerror(errno));
} else if (signal_has_address(sig)) {
- _LOG(log, false, "signal %d (%s), code %d (%s), fault addr %08x\n",
+ _LOG(log, SCOPE_AT_FAULT, "signal %d (%s), code %d (%s), fault addr %08x\n",
sig, get_signame(sig),
si.si_code, get_sigcode(sig, si.si_code),
(uintptr_t) si.si_addr);
} else {
- _LOG(log, false, "signal %d (%s), code %d (%s), fault addr --------\n",
+ _LOG(log, SCOPE_AT_FAULT, "signal %d (%s), code %d (%s), fault addr --------\n",
sig, get_signame(sig), si.si_code, get_sigcode(sig, si.si_code));
}
}
@@ -215,19 +221,20 @@ static void dump_thread_info(log_t* log, pid_t pid, pid_t tid, bool at_fault) {
fclose(fp);
}
- _LOG(log, false, "pid: %d, tid: %d, name: %s >>> %s <<<\n", pid, tid,
+ _LOG(log, SCOPE_AT_FAULT, "pid: %d, tid: %d, name: %s >>> %s <<<\n", pid, tid,
threadname ? threadname : "UNKNOWN",
procname ? procname : "UNKNOWN");
} else {
- _LOG(log, true, "pid: %d, tid: %d, name: %s\n", pid, tid,
- threadname ? threadname : "UNKNOWN");
+ _LOG(log, 0, "pid: %d, tid: %d, name: %s\n",
+ pid, tid, threadname ? threadname : "UNKNOWN");
}
}
static void dump_backtrace(const ptrace_context_t* context __attribute((unused)),
log_t* log, pid_t tid __attribute((unused)), bool at_fault,
const backtrace_frame_t* backtrace, size_t frames) {
- _LOG(log, !at_fault, "\nbacktrace:\n");
+ int scopeFlags = at_fault ? SCOPE_AT_FAULT : 0;
+ _LOG(log, scopeFlags, "\nbacktrace:\n");
backtrace_symbol_t backtrace_symbols[STACK_DEPTH];
get_backtrace_symbols_ptrace(context, backtrace, frames, backtrace_symbols);
@@ -235,13 +242,13 @@ static void dump_backtrace(const ptrace_context_t* context __attribute((unused))
char line[MAX_BACKTRACE_LINE_LENGTH];
format_backtrace_line(i, &backtrace[i], &backtrace_symbols[i],
line, MAX_BACKTRACE_LINE_LENGTH);
- _LOG(log, !at_fault, " %s\n", line);
+ _LOG(log, scopeFlags, " %s\n", line);
}
free_backtrace_symbols(backtrace_symbols, frames);
}
static void dump_stack_segment(const ptrace_context_t* context, log_t* log, pid_t tid,
- bool only_in_tombstone, uintptr_t* sp, size_t words, int label) {
+ int scopeFlags, uintptr_t* sp, size_t words, int label) {
for (size_t i = 0; i < words; i++) {
uint32_t stack_content;
if (!try_get_word_ptrace(tid, *sp, &stack_content)) {
@@ -258,28 +265,28 @@ static void dump_stack_segment(const ptrace_context_t* context, log_t* log, pid_
uint32_t offset = stack_content - (mi->start + symbol->start);
if (!i && label >= 0) {
if (offset) {
- _LOG(log, only_in_tombstone, " #%02d %08x %08x %s (%s+%u)\n",
+ _LOG(log, scopeFlags, " #%02d %08x %08x %s (%s+%u)\n",
label, *sp, stack_content, mi ? mi->name : "", symbol_name, offset);
} else {
- _LOG(log, only_in_tombstone, " #%02d %08x %08x %s (%s)\n",
+ _LOG(log, scopeFlags, " #%02d %08x %08x %s (%s)\n",
label, *sp, stack_content, mi ? mi->name : "", symbol_name);
}
} else {
if (offset) {
- _LOG(log, only_in_tombstone, " %08x %08x %s (%s+%u)\n",
+ _LOG(log, scopeFlags, " %08x %08x %s (%s+%u)\n",
*sp, stack_content, mi ? mi->name : "", symbol_name, offset);
} else {
- _LOG(log, only_in_tombstone, " %08x %08x %s (%s)\n",
+ _LOG(log, scopeFlags, " %08x %08x %s (%s)\n",
*sp, stack_content, mi ? mi->name : "", symbol_name);
}
}
free(demangled_name);
} else {
if (!i && label >= 0) {
- _LOG(log, only_in_tombstone, " #%02d %08x %08x %s\n",
+ _LOG(log, scopeFlags, " #%02d %08x %08x %s\n",
label, *sp, stack_content, mi ? mi->name : "");
} else {
- _LOG(log, only_in_tombstone, " %08x %08x %s\n",
+ _LOG(log, scopeFlags, " %08x %08x %s\n",
*sp, stack_content, mi ? mi->name : "");
}
}
@@ -305,28 +312,28 @@ static void dump_stack(const ptrace_context_t* context, log_t* log, pid_t tid, b
return;
}
- _LOG(log, !at_fault, "\nstack:\n");
+ int scopeFlags = SCOPE_SENSITIVE | (at_fault ? SCOPE_AT_FAULT : 0);
+ _LOG(log, scopeFlags, "\nstack:\n");
// Dump a few words before the first frame.
- bool only_in_tombstone = !at_fault;
uintptr_t sp = backtrace[first].stack_top - STACK_WORDS * sizeof(uint32_t);
- dump_stack_segment(context, log, tid, only_in_tombstone, &sp, STACK_WORDS, -1);
+ dump_stack_segment(context, log, tid, scopeFlags, &sp, STACK_WORDS, -1);
// Dump a few words from all successive frames.
// Only log the first 3 frames, put the rest in the tombstone.
for (size_t i = first; i <= last; i++) {
const backtrace_frame_t* frame = &backtrace[i];
if (sp != frame->stack_top) {
- _LOG(log, only_in_tombstone, " ........ ........\n");
+ _LOG(log, scopeFlags, " ........ ........\n");
sp = frame->stack_top;
}
if (i - first == 3) {
- only_in_tombstone = true;
+ scopeFlags &= (~SCOPE_AT_FAULT);
}
if (i == last) {
- dump_stack_segment(context, log, tid, only_in_tombstone, &sp, STACK_WORDS, i);
+ dump_stack_segment(context, log, tid, scopeFlags, &sp, STACK_WORDS, i);
if (sp < frame->stack_top + frame->stack_size) {
- _LOG(log, only_in_tombstone, " ........ ........\n");
+ _LOG(log, scopeFlags, " ........ ........\n");
}
} else {
size_t words = frame->stack_size / sizeof(uint32_t);
@@ -335,7 +342,7 @@ static void dump_stack(const ptrace_context_t* context, log_t* log, pid_t tid, b
} else if (words > STACK_WORDS) {
words = STACK_WORDS;
}
- dump_stack_segment(context, log, tid, only_in_tombstone, &sp, words, i);
+ dump_stack_segment(context, log, tid, scopeFlags, &sp, words, i);
}
}
}
@@ -352,13 +359,13 @@ static void dump_backtrace_and_stack(const ptrace_context_t* context, log_t* log
static void dump_map(log_t* log, map_info_t* m, const char* what) {
if (m != NULL) {
- _LOG(log, false, " %08x-%08x %c%c%c %s\n", m->start, m->end,
+ _LOG(log, SCOPE_SENSITIVE, " %08x-%08x %c%c%c %s\n", m->start, m->end,
m->is_readable ? 'r' : '-',
m->is_writable ? 'w' : '-',
m->is_executable ? 'x' : '-',
m->name);
} else {
- _LOG(log, false, " (no %s)\n", what);
+ _LOG(log, SCOPE_SENSITIVE, " (no %s)\n", what);
}
}
@@ -366,7 +373,7 @@ static void dump_nearby_maps(const ptrace_context_t* context, log_t* log, pid_t
siginfo_t si;
memset(&si, 0, sizeof(si));
if (ptrace(PTRACE_GETSIGINFO, tid, 0, &si)) {
- _LOG(log, false, "cannot get siginfo for %d: %s\n",
+ _LOG(log, SCOPE_SENSITIVE, "cannot get siginfo for %d: %s\n",
tid, strerror(errno));
return;
}
@@ -380,7 +387,7 @@ static void dump_nearby_maps(const ptrace_context_t* context, log_t* log, pid_t
return;
}
- _LOG(log, false, "\nmemory map around fault addr %08x:\n", (int)si.si_addr);
+ _LOG(log, SCOPE_SENSITIVE, "\nmemory map around fault addr %08x:\n", (int)si.si_addr);
/*
* Search for a match, or for a hole where the match would be. The list
@@ -458,7 +465,7 @@ static bool dump_sibling_thread_report(const ptrace_context_t* context,
continue;
}
- _LOG(log, true, "--- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---\n");
+ _LOG(log, 0, "--- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---\n");
dump_thread_info(log, pid, new_tid, false);
dump_thread(context, log, new_tid, false, total_sleep_time_usec);
@@ -511,12 +518,12 @@ static void dump_log_file(log_t* log, pid_t pid, const char* filename,
/* non-blocking EOF; we're done */
break;
} else {
- _LOG(log, true, "Error while reading log: %s\n",
+ _LOG(log, 0, "Error while reading log: %s\n",
strerror(errno));
break;
}
} else if (actual == 0) {
- _LOG(log, true, "Got zero bytes while reading log: %s\n",
+ _LOG(log, 0, "Got zero bytes while reading log: %s\n",
strerror(errno));
break;
}
@@ -536,7 +543,7 @@ static void dump_log_file(log_t* log, pid_t pid, const char* filename,
}
if (first) {
- _LOG(log, true, "--------- %slog %s\n",
+ _LOG(log, 0, "--------- %slog %s\n",
tailOnly ? "tail end of " : "", filename);
first = false;
}
@@ -578,7 +585,7 @@ static void dump_log_file(log_t* log, pid_t pid, const char* filename,
shortLogNext = (shortLogNext + 1) % kShortLogMaxLines;
shortLogCount++;
} else {
- _LOG(log, true, "%s.%03d %5d %5d %c %-8s: %s\n",
+ _LOG(log, 0, "%s.%03d %5d %5d %c %-8s: %s\n",
timeBuf, entry->nsec / 1000000, entry->pid, entry->tid,
prioChar, tag, msg);
}
@@ -598,7 +605,7 @@ static void dump_log_file(log_t* log, pid_t pid, const char* filename,
}
for (i = 0; i < shortLogCount; i++) {
- _LOG(log, true, "%s\n", shortLog[shortLogNext]);
+ _LOG(log, 0, "%s\n", shortLog[shortLogNext]);
shortLogNext = (shortLogNext + 1) % kShortLogMaxLines;
}
}
@@ -648,7 +655,7 @@ static void dump_abort_message(log_t* log, pid_t tid, uintptr_t address) {
}
msg[sizeof(msg) - 1] = '\0';
- _LOG(log, false, "Abort message: '%s'\n", msg);
+ _LOG(log, SCOPE_AT_FAULT, "Abort message: '%s'\n", msg);
}
/*
@@ -662,7 +669,19 @@ static bool dump_crash(log_t* log, pid_t pid, pid_t tid, int signal, uintptr_t a
property_get("ro.debuggable", value, "0");
bool want_logs = (value[0] == '1');
- _LOG(log, false,
+ if (log->amfd >= 0) {
+ /*
+ * Activity Manager protocol: binary 32-bit network-byte-order ints for the
+ * pid and signal number, followed by the raw text of the dump, culminating
+ * in a zero byte that marks end-of-data.
+ */
+ uint32_t datum = htonl(pid);
+ TEMP_FAILURE_RETRY( write(log->amfd, &datum, 4) );
+ datum = htonl(signal);
+ TEMP_FAILURE_RETRY( write(log->amfd, &datum, 4) );
+ }
+
+ _LOG(log, SCOPE_AT_FAULT,
"*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***\n");
dump_build_info(log);
dump_revision_info(log);
@@ -689,6 +708,16 @@ static bool dump_crash(log_t* log, pid_t pid, pid_t tid, int signal, uintptr_t a
if (want_logs) {
dump_logs(log, pid, false);
}
+
+ /* send EOD to the Activity Manager, then wait for its ack to avoid racing ahead
+ * and killing the target out from under it */
+ if (log->amfd >= 0) {
+ uint8_t eodMarker = 0;
+ TEMP_FAILURE_RETRY( write(log->amfd, &eodMarker, 1) );
+ /* 3 sec timeout reading the ack; we're fine if that happens */
+ TEMP_FAILURE_RETRY( read(log->amfd, &eodMarker, 1) );
+ }
+
return detach_failed;
}
@@ -748,6 +777,35 @@ static char* find_and_open_tombstone(int* fd)
return strdup(path);
}
+static int activity_manager_connect() {
+ int amfd = socket(PF_UNIX, SOCK_STREAM, 0);
+ if (amfd >= 0) {
+ struct sockaddr_un address;
+ int err;
+
+ memset(&address, 0, sizeof(address));
+ address.sun_family = AF_UNIX;
+ strncpy(address.sun_path, NCRASH_SOCKET_PATH, sizeof(address.sun_path));
+ err = TEMP_FAILURE_RETRY( connect(amfd, (struct sockaddr*) &address, sizeof(address)) );
+ if (!err) {
+ struct timeval tv;
+ memset(&tv, 0, sizeof(tv));
+ tv.tv_sec = 1; // tight leash
+ err = setsockopt(amfd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));
+ if (!err) {
+ tv.tv_sec = 3; // 3 seconds on handshake read
+ err = setsockopt(amfd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
+ }
+ }
+ if (err) {
+ close(amfd);
+ amfd = -1;
+ }
+ }
+
+ return amfd;
+}
+
char* engrave_tombstone(pid_t pid, pid_t tid, int signal, uintptr_t abort_msg_address,
bool dump_sibling_threads, bool quiet, bool* detach_failed,
int* total_sleep_time_usec) {
@@ -768,10 +826,12 @@ char* engrave_tombstone(pid_t pid, pid_t tid, int signal, uintptr_t abort_msg_ad
log_t log;
log.tfd = fd;
+ log.amfd = activity_manager_connect();
log.quiet = quiet;
*detach_failed = dump_crash(&log, pid, tid, signal, abort_msg_address, dump_sibling_threads,
total_sleep_time_usec);
+ close(log.amfd);
close(fd);
return path;
}
diff --git a/debuggerd/utility.c b/debuggerd/utility.c
index aabaf7468..9bf3c18dd 100644
--- a/debuggerd/utility.c
+++ b/debuggerd/utility.c
@@ -25,27 +25,63 @@
#include <cutils/logd.h>
#include <sys/ptrace.h>
#include <sys/wait.h>
+#include <arpa/inet.h>
+#include <assert.h>
#include "utility.h"
const int sleep_time_usec = 50000; /* 0.05 seconds */
const int max_total_sleep_usec = 10000000; /* 10 seconds */
-void _LOG(log_t* log, bool in_tombstone_only, const char *fmt, ...) {
+static int write_to_am(int fd, const char* buf, int len) {
+ int to_write = len;
+ while (to_write > 0) {
+ int written = TEMP_FAILURE_RETRY( write(fd, buf + len - to_write, to_write) );
+ if (written < 0) {
+ /* hard failure */
+ LOG("AM write failure (%d / %s)\n", errno, strerror(errno));
+ return -1;
+ }
+ to_write -= written;
+ }
+ return len;
+}
+
+void _LOG(log_t* log, int scopeFlags, const char *fmt, ...) {
char buf[512];
+ bool want_tfd_write;
+ bool want_log_write;
+ bool want_amfd_write;
+ int len = 0;
va_list ap;
va_start(ap, fmt);
- if (log && log->tfd >= 0) {
- int len;
+ // where is the information going to go?
+ want_tfd_write = log && log->tfd >= 0;
+ want_log_write = IS_AT_FAULT(scopeFlags) && (!log || !log->quiet);
+ want_amfd_write = IS_AT_FAULT(scopeFlags) && !IS_SENSITIVE(scopeFlags) && log && log->amfd >= 0;
+
+ // if we're going to need the literal string, generate it once here
+ if (want_tfd_write || want_amfd_write) {
vsnprintf(buf, sizeof(buf), fmt, ap);
len = strlen(buf);
+ }
+
+ if (want_tfd_write) {
write(log->tfd, buf, len);
}
- if (!in_tombstone_only && (!log || !log->quiet)) {
+ if (want_log_write) {
+ // whatever goes to logcat also goes to the Activity Manager
__android_log_vprint(ANDROID_LOG_INFO, "DEBUG", fmt, ap);
+ if (want_amfd_write && len > 0) {
+ int written = write_to_am(log->amfd, buf, len);
+ if (written <= 0) {
+ // timeout or other failure on write; stop informing the activity manager
+ log->amfd = -1;
+ }
+ }
}
va_end(ap);
}
diff --git a/debuggerd/utility.h b/debuggerd/utility.h
index 136f46d8d..1f006ed5d 100644
--- a/debuggerd/utility.h
+++ b/debuggerd/utility.h
@@ -24,26 +24,38 @@
typedef struct {
/* tombstone file descriptor */
int tfd;
- /* if true, does not log anything to the Android logcat */
+ /* Activity Manager socket file descriptor */
+ int amfd;
+ /* if true, does not log anything to the Android logcat or Activity Manager */
bool quiet;
} log_t;
-/* Log information onto the tombstone. */
-void _LOG(log_t* log, bool in_tombstone_only, const char *fmt, ...)
+/* Log information onto the tombstone. scopeFlags is a bitmask of the flags defined
+ * here. */
+void _LOG(log_t* log, int scopeFlags, const char *fmt, ...)
__attribute__ ((format(printf, 3, 4)));
-#define LOG(fmt...) _LOG(NULL, 0, fmt)
+/* The message pertains specifically to the faulting thread / process */
+#define SCOPE_AT_FAULT (1 << 0)
+/* The message contains sensitive information such as RAM contents */
+#define SCOPE_SENSITIVE (1 << 1)
+
+#define IS_AT_FAULT(x) (((x) & SCOPE_AT_FAULT) != 0)
+#define IS_SENSITIVE(x) (((x) & SCOPE_SENSITIVE) != 0)
+
+/* Further helpful macros */
+#define LOG(fmt...) _LOG(NULL, SCOPE_AT_FAULT, fmt)
/* Set to 1 for normal debug traces */
#if 0
-#define XLOG(fmt...) _LOG(NULL, 0, fmt)
+#define XLOG(fmt...) _LOG(NULL, SCOPE_AT_FAULT, fmt)
#else
#define XLOG(fmt...) do {} while(0)
#endif
/* Set to 1 for chatty debug traces. Includes all resolved dynamic symbols */
#if 0
-#define XLOG2(fmt...) _LOG(NULL, 0, fmt)
+#define XLOG2(fmt...) _LOG(NULL, SCOPE_AT_FAULT, fmt)
#else
#define XLOG2(fmt...) do {} while(0)
#endif
diff --git a/debuggerd/x86/machine.c b/debuggerd/x86/machine.c
index 01da5fef0..af79092c7 100644
--- a/debuggerd/x86/machine.c
+++ b/debuggerd/x86/machine.c
@@ -38,21 +38,21 @@ void dump_memory_and_code(const ptrace_context_t* context __attribute((unused)),
void dump_registers(const ptrace_context_t* context __attribute((unused)),
log_t* log, pid_t tid, bool at_fault) {
struct pt_regs_x86 r;
- bool only_in_tombstone = !at_fault;
+ int scopeFlags = (at_fault ? SCOPE_AT_FAULT : 0);
if(ptrace(PTRACE_GETREGS, tid, 0, &r)) {
- _LOG(log, only_in_tombstone, "cannot get registers: %s\n", strerror(errno));
+ _LOG(log, scopeFlags, "cannot get registers: %s\n", strerror(errno));
return;
}
//if there is no stack, no print just like arm
if(!r.ebp)
return;
- _LOG(log, only_in_tombstone, " eax %08x ebx %08x ecx %08x edx %08x\n",
+ _LOG(log, scopeFlags, " eax %08x ebx %08x ecx %08x edx %08x\n",
r.eax, r.ebx, r.ecx, r.edx);
- _LOG(log, only_in_tombstone, " esi %08x edi %08x\n",
+ _LOG(log, scopeFlags, " esi %08x edi %08x\n",
r.esi, r.edi);
- _LOG(log, only_in_tombstone, " xcs %08x xds %08x xes %08x xfs %08x xss %08x\n",
+ _LOG(log, scopeFlags, " xcs %08x xds %08x xes %08x xfs %08x xss %08x\n",
r.xcs, r.xds, r.xes, r.xfs, r.xss);
- _LOG(log, only_in_tombstone, " eip %08x ebp %08x esp %08x flags %08x\n",
+ _LOG(log, scopeFlags, " eip %08x ebp %08x esp %08x flags %08x\n",
r.eip, r.ebp, r.esp, r.eflags);
}
diff --git a/fastboot/Android.mk b/fastboot/Android.mk
index 5025dae73..1189e1f4c 100644
--- a/fastboot/Android.mk
+++ b/fastboot/Android.mk
@@ -20,6 +20,7 @@ LOCAL_C_INCLUDES := $(LOCAL_PATH)/../mkbootimg \
$(LOCAL_PATH)/../../extras/ext4_utils
LOCAL_SRC_FILES := protocol.c engine.c bootimg.c fastboot.c
LOCAL_MODULE := fastboot
+LOCAL_MODULE_TAGS := debug
ifeq ($(HOST_OS),linux)
LOCAL_SRC_FILES += usb_linux.c util_linux.c
diff --git a/fastboot/bootimg.c b/fastboot/bootimg.c
index 9e0e45c7b..240784fb0 100644
--- a/fastboot/bootimg.c
+++ b/fastboot/bootimg.c
@@ -37,10 +37,10 @@ void bootimg_set_cmdline(boot_img_hdr *h, const char *cmdline)
strcpy((char*) h->cmdline, cmdline);
}
-boot_img_hdr *mkbootimg(void *kernel, unsigned kernel_size,
- void *ramdisk, unsigned ramdisk_size,
- void *second, unsigned second_size,
- unsigned page_size, unsigned base,
+boot_img_hdr *mkbootimg(void *kernel, unsigned kernel_size, unsigned kernel_offset,
+ void *ramdisk, unsigned ramdisk_size, unsigned ramdisk_offset,
+ void *second, unsigned second_size, unsigned second_offset,
+ unsigned page_size, unsigned base, unsigned tags_offset,
unsigned *bootimg_size)
{
unsigned kernel_actual;
@@ -68,12 +68,15 @@ boot_img_hdr *mkbootimg(void *kernel, unsigned kernel_size,
hdr->kernel_size = kernel_size;
hdr->ramdisk_size = ramdisk_size;
hdr->second_size = second_size;
- hdr->kernel_addr = base + 0x00008000;
- hdr->ramdisk_addr = base + 0x01000000;
- hdr->second_addr = base + 0x00F00000;
- hdr->tags_addr = base + 0x00000100;
+
+ hdr->kernel_addr = base + kernel_offset;
+ hdr->ramdisk_addr = base + ramdisk_offset;
+ hdr->second_addr = base + second_offset;
+ hdr->tags_addr = base + tags_offset;
+
hdr->page_size = page_size;
+
memcpy(hdr->magic + page_size,
kernel, kernel_size);
memcpy(hdr->magic + page_size + kernel_actual,
diff --git a/fastboot/fastboot.c b/fastboot/fastboot.c
index 3de6d7df9..447b2572b 100644
--- a/fastboot/fastboot.c
+++ b/fastboot/fastboot.c
@@ -58,10 +58,10 @@ char cur_product[FB_RESPONSE_SZ + 1];
void bootimg_set_cmdline(boot_img_hdr *h, const char *cmdline);
-boot_img_hdr *mkbootimg(void *kernel, unsigned kernel_size,
- void *ramdisk, unsigned ramdisk_size,
- void *second, unsigned second_size,
- unsigned page_size, unsigned base,
+boot_img_hdr *mkbootimg(void *kernel, unsigned kernel_size, unsigned kernel_offset,
+ void *ramdisk, unsigned ramdisk_size, unsigned ramdisk_offset,
+ void *second, unsigned second_size, unsigned second_offset,
+ unsigned page_size, unsigned base, unsigned tags_offset,
unsigned *bootimg_size);
static usb_handle *usb = 0;
@@ -74,7 +74,13 @@ static int long_listing = 0;
static int64_t sparse_limit = -1;
static int64_t target_sparse_limit = -1;
-static unsigned base_addr = 0x10000000;
+unsigned page_size = 2048;
+unsigned base_addr = 0x10000000;
+unsigned kernel_offset = 0x00008000;
+unsigned ramdisk_offset = 0x01000000;
+unsigned second_offset = 0x00f00000;
+unsigned tags_offset = 0x00000100;
+
void die(const char *fmt, ...)
{
@@ -186,11 +192,6 @@ oops:
}
#endif
-int match_fastboot(usb_ifc_info *info)
-{
- return match_fastboot_with_serial(info, serial);
-}
-
int match_fastboot_with_serial(usb_ifc_info *info, const char *local_serial)
{
if(!(vendor_id && (info->dev_vendor == vendor_id)) &&
@@ -217,6 +218,11 @@ int match_fastboot_with_serial(usb_ifc_info *info, const char *local_serial)
return 0;
}
+int match_fastboot(usb_ifc_info *info)
+{
+ return match_fastboot_with_serial(info, serial);
+}
+
int list_devices_callback(usb_ifc_info *info)
{
if (match_fastboot_with_serial(info, NULL) == 0) {
@@ -297,14 +303,14 @@ void usage(void)
" -p <product> specify product name\n"
" -c <cmdline> override kernel commandline\n"
" -i <vendor id> specify a custom USB vendor id\n"
- " -b <base_addr> specify a custom kernel base address\n"
+ " -b <base_addr> specify a custom kernel base address. default: 0x10000000\n"
" -n <page size> specify the nand page size. default: 2048\n"
" -S <size>[K|M|G] automatically sparse files greater than\n"
" size. 0 to disable\n"
);
}
-void *load_bootable_image(unsigned page_size, const char *kernel, const char *ramdisk,
+void *load_bootable_image(const char *kernel, const char *ramdisk,
unsigned *sz, const char *cmdline)
{
void *kdata = 0, *rdata = 0;
@@ -345,7 +351,10 @@ void *load_bootable_image(unsigned page_size, const char *kernel, const char *ra
}
fprintf(stderr,"creating boot image...\n");
- bdata = mkbootimg(kdata, ksize, rdata, rsize, 0, 0, page_size, base_addr, &bsize);
+ bdata = mkbootimg(kdata, ksize, kernel_offset,
+ rdata, rsize, ramdisk_offset,
+ 0, 0, second_offset,
+ page_size, base_addr, tags_offset, &bsize);
if(bdata == 0) {
fprintf(stderr,"failed to create boot.img\n");
return 0;
@@ -806,35 +815,64 @@ int main(int argc, char **argv)
int erase_first = 1;
void *data;
unsigned sz;
- unsigned page_size = 2048;
int status;
int c;
int r;
- const struct option longopts = { 0, 0, 0, 0 };
+ const struct option longopts[] = {
+ {"base", required_argument, 0, 'b'},
+ {"kernel_offset", required_argument, 0, 'k'},
+ {"page_size", required_argument, 0, 'n'},
+ {"ramdisk_offset", required_argument, 0, 'r'},
+ {"help", 0, 0, 'h'},
+ {0, 0, 0, 0}
+ };
serial = getenv("ANDROID_SERIAL");
while (1) {
- c = getopt_long(argc, argv, "wub:n:s:S:lp:c:i:m:h", &longopts, NULL);
+ int option_index = 0;
+ c = getopt_long(argc, argv, "wub:k:n:r:s:S:lp:c:i:m:h", longopts, NULL);
if (c < 0) {
break;
}
-
+ /* Alphabetical cases */
switch (c) {
- case 'w':
- wants_wipe = 1;
- break;
- case 'u':
- erase_first = 0;
- break;
case 'b':
base_addr = strtoul(optarg, 0, 16);
break;
+ case 'c':
+ cmdline = optarg;
+ break;
+ case 'h':
+ usage();
+ return 1;
+ case 'i': {
+ char *endptr = NULL;
+ unsigned long val;
+
+ val = strtoul(optarg, &endptr, 0);
+ if (!endptr || *endptr != '\0' || (val & ~0xffff))
+ die("invalid vendor id '%s'", optarg);
+ vendor_id = (unsigned short)val;
+ break;
+ }
+ case 'k':
+ kernel_offset = strtoul(optarg, 0, 16);
+ break;
+ case 'l':
+ long_listing = 1;
+ break;
case 'n':
page_size = (unsigned)strtoul(optarg, NULL, 0);
if (!page_size) die("invalid page size");
break;
+ case 'p':
+ product = optarg;
+ break;
+ case 'r':
+ ramdisk_offset = strtoul(optarg, 0, 16);
+ break;
case 's':
serial = optarg;
break;
@@ -844,28 +882,12 @@ int main(int argc, char **argv)
die("invalid sparse limit");
}
break;
- case 'l':
- long_listing = 1;
- break;
- case 'p':
- product = optarg;
+ case 'u':
+ erase_first = 0;
break;
- case 'c':
- cmdline = optarg;
+ case 'w':
+ wants_wipe = 1;
break;
- case 'i': {
- char *endptr = NULL;
- unsigned long val;
-
- val = strtoul(optarg, &endptr, 0);
- if (!endptr || *endptr != '\0' || (val & ~0xffff))
- die("invalid vendor id '%s'", optarg);
- vendor_id = (unsigned short)val;
- break;
- }
- case 'h':
- usage();
- return 1;
case '?':
return 1;
default:
@@ -944,7 +966,7 @@ int main(int argc, char **argv)
rname = argv[0];
skip(1);
}
- data = load_bootable_image(page_size, kname, rname, &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");
@@ -975,7 +997,7 @@ int main(int argc, char **argv)
} else {
skip(3);
}
- data = load_bootable_image(page_size, kname, rname, &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/fastboot/fastboot_protocol.txt b/fastboot/fastboot_protocol.txt
new file mode 100644
index 000000000..2248992d2
--- /dev/null
+++ b/fastboot/fastboot_protocol.txt
@@ -0,0 +1,173 @@
+
+FastBoot Version 0.4
+----------------------
+
+The fastboot protocol is a mechanism for communicating with bootloaders
+over USB. It is designed to be very straightforward to implement, to
+allow it to be used across a wide range of devices and from hosts running
+Linux, Windows, or OSX.
+
+
+Basic Requirements
+------------------
+
+* Two bulk endpoints (in, out) are required
+* Max packet size must be 64 bytes for full-speed and 512 bytes for
+ high-speed USB
+* The protocol is entirely host-driven and synchronous (unlike the
+ multi-channel, bi-directional, asynchronous ADB protocol)
+
+
+Transport and Framing
+---------------------
+
+1. Host sends a command, which is an ascii string in a single
+ packet no greater than 64 bytes.
+
+2. Client response with a single packet no greater than 64 bytes.
+ The first four bytes of the response are "OKAY", "FAIL", "DATA",
+ or "INFO". Additional bytes may contain an (ascii) informative
+ message.
+
+ a. INFO -> the remaining 60 bytes are an informative message
+ (providing progress or diagnostic messages). They should
+ be displayed and then step #2 repeats
+
+ b. FAIL -> the requested command failed. The remaining 60 bytes
+ of the response (if present) provide a textual failure message
+ to present to the user. Stop.
+
+ c. OKAY -> the requested command completed successfully. Go to #5
+
+ d. DATA -> the requested command is ready for the data phase.
+ A DATA response packet will be 12 bytes long, in the form of
+ DATA00000000 where the 8 digit hexidecimal number represents
+ the total data size to transfer.
+
+3. Data phase. Depending on the command, the host or client will
+ send the indicated amount of data. Short packets are always
+ acceptable and zero-length packets are ignored. This phase continues
+ until the client has sent or received the number of bytes indicated
+ in the "DATA" response above.
+
+4. Client responds with a single packet no greater than 64 bytes.
+ The first four bytes of the response are "OKAY", "FAIL", or "INFO".
+ Similar to #2:
+
+ a. INFO -> display the remaining 60 bytes and return to #4
+
+ b. FAIL -> display the remaining 60 bytes (if present) as a failure
+ reason and consider the command failed. Stop.
+
+ c. OKAY -> success. Go to #5
+
+5. Success. Stop.
+
+
+Example Session
+---------------
+
+Host: "getvar:version" request version variable
+
+Client: "OKAY0.4" return version "0.4"
+
+Host: "getvar:nonexistant" request some undefined variable
+
+Client: "OKAY" return value ""
+
+Host: "download:00001234" request to send 0x1234 bytes of data
+
+Client: "DATA00001234" ready to accept data
+
+Host: < 0x1234 bytes > send data
+
+Client: "OKAY" success
+
+Host: "flash:bootloader" request to flash the data to the bootloader
+
+Client: "INFOerasing flash" indicate status / progress
+ "INFOwriting flash"
+ "OKAY" indicate success
+
+Host: "powerdown" send a command
+
+Client: "FAILunknown command" indicate failure
+
+
+Command Reference
+-----------------
+
+* Command parameters are indicated by printf-style escape sequences.
+
+* Commands are ascii strings and sent without the quotes (which are
+ for illustration only here) and without a trailing 0 byte.
+
+* Commands that begin with a lowercase letter are reserved for this
+ specification. OEM-specific commands should not begin with a
+ lowercase letter, to prevent incompatibilities with future specs.
+
+ "getvar:%s" Read a config/version variable from the bootloader.
+ The variable contents will be returned after the
+ OKAY response.
+
+ "download:%08x" Write data to memory which will be later used
+ by "boot", "ramdisk", "flash", etc. The client
+ will reply with "DATA%08x" if it has enough
+ space in RAM or "FAIL" if not. The size of
+ the download is remembered.
+
+ "verify:%08x" Send a digital signature to verify the downloaded
+ data. Required if the bootloader is "secure"
+ otherwise "flash" and "boot" will be ignored.
+
+ "flash:%s" Write the previously downloaded image to the
+ named partition (if possible).
+
+ "erase:%s" Erase the indicated partition (clear to 0xFFs)
+
+ "boot" The previously downloaded data is a boot.img
+ and should be booted according to the normal
+ procedure for a boot.img
+
+ "continue" Continue booting as normal (if possible)
+
+ "reboot" Reboot the device.
+
+ "reboot-bootloader" Reboot back into the bootloader.
+ Useful for upgrade processes that require upgrading
+ the bootloader and then upgrading other partitions
+ using the new bootloader.
+
+ "powerdown" Power off the device.
+
+
+
+Client Variables
+----------------
+
+The "getvar:%s" command is used to read client variables which
+represent various information about the device and the software
+on it.
+
+The various currently defined names are:
+
+ version Version of FastBoot protocol supported.
+ It should be "0.3" for this document.
+
+ version-bootloader Version string for the Bootloader.
+
+ version-baseband Version string of the Baseband Software
+
+ product Name of the product
+
+ serialno Product serial number
+
+ secure If the value is "yes", this is a secure
+ bootloader requiring a signature before
+ it will install or boot images.
+
+Names starting with a lowercase character are reserved by this
+specification. OEM-specific names should not start with lowercase
+characters.
+
+
diff --git a/fs_mgr/fs_mgr.c b/fs_mgr/fs_mgr.c
index e51c9cff0..8f647578b 100644
--- a/fs_mgr/fs_mgr.c
+++ b/fs_mgr/fs_mgr.c
@@ -72,6 +72,10 @@ static struct flag_list fs_mgr_flags[] = {
{ "wait", MF_WAIT },
{ "check", MF_CHECK },
{ "encryptable=",MF_CRYPT },
+ { "nonremovable",MF_NONREMOVABLE },
+ { "voldmanaged=",MF_VOLDMANAGED},
+ { "length=", MF_LENGTH },
+ { "recoveryonly",MF_RECOVERYONLY },
{ "defaults", 0 },
{ 0, 0 },
};
@@ -106,7 +110,8 @@ static int wait_for_file(const char *filename, int timeout)
return ret;
}
-static int parse_flags(char *flags, struct flag_list *fl, char **key_loc,
+static int parse_flags(char *flags, struct flag_list *fl,
+ char **key_loc, long long *part_length, char **label, int *partnum,
char *fs_options, int fs_options_len)
{
int f = 0;
@@ -119,6 +124,18 @@ static int parse_flags(char *flags, struct flag_list *fl, char **key_loc,
if (key_loc) {
*key_loc = NULL;
}
+ /* initialize part_length to 0, if we find an MF_LENGTH flag,
+ * then we'll set part_length to the proper value */
+ if (part_length) {
+ *part_length = 0;
+ }
+ if (partnum) {
+ *partnum = -1;
+ }
+ if (label) {
+ *label = NULL;
+ }
+
/* initialize fs_options to the null string */
if (fs_options && (fs_options_len > 0)) {
fs_options[0] = '\0';
@@ -137,6 +154,36 @@ static int parse_flags(char *flags, struct flag_list *fl, char **key_loc,
* location of the keys. Get it and return it.
*/
*key_loc = strdup(strchr(p, '=') + 1);
+ } else if ((fl[i].flag == MF_LENGTH) && part_length) {
+ /* The length flag is followed by an = and the
+ * size of the partition. Get it and return it.
+ */
+ *part_length = strtoll(strchr(p, '=') + 1, NULL, 0);
+ } else if ((fl[i].flag == MF_VOLDMANAGED) && label && partnum) {
+ /* The voldmanaged flag is followed by an = and the
+ * label, a colon and the partition number or the
+ * word "auto", e.g.
+ * voldmanaged=sdcard:3
+ * Get and return them.
+ */
+ char *label_start;
+ char *label_end;
+ char *part_start;
+
+ label_start = strchr(p, '=') + 1;
+ label_end = strchr(p, ':');
+ if (label_end) {
+ *label = strndup(label_start,
+ (int) (label_end - label_start));
+ part_start = strchr(p, ':') + 1;
+ if (!strcmp(part_start, "auto")) {
+ *partnum = -1;
+ } else {
+ *partnum = strtol(part_start, NULL, 0);
+ }
+ } else {
+ ERROR("Warning: voldmanaged= flag malformed\n");
+ }
}
break;
}
@@ -227,7 +274,7 @@ static char *fs_getline(char *buf, int size, FILE *file)
}
}
-static struct fstab_rec *read_fstab(char *fstab_path)
+struct fstab *fs_mgr_read_fstab(const char *fstab_path)
{
FILE *fstab_file;
int cnt, entries;
@@ -235,8 +282,12 @@ static struct fstab_rec *read_fstab(char *fstab_path)
char line[256];
const char *delim = " \t";
char *save_ptr, *p;
- struct fstab_rec *fstab;
+ struct fstab *fstab;
+ struct fstab_rec *recs;
char *key_loc;
+ long long part_length;
+ char *label;
+ int partnum;
#define FS_OPTIONS_LEN 1024
char tmp_fs_options[FS_OPTIONS_LEN];
@@ -269,7 +320,11 @@ static struct fstab_rec *read_fstab(char *fstab_path)
return 0;
}
- fstab = calloc(entries + 1, sizeof(struct fstab_rec));
+ /* Allocate and init the fstab structure */
+ fstab = calloc(1, sizeof(struct fstab));
+ fstab->num_entries = entries;
+ fstab->fstab_filename = strdup(fstab_path);
+ fstab->recs = calloc(fstab->num_entries, sizeof(struct fstab_rec));
fseek(fstab_file, 0, SEEK_SET);
@@ -303,41 +358,48 @@ static struct fstab_rec *read_fstab(char *fstab_path)
ERROR("Error parsing mount source\n");
return 0;
}
- fstab[cnt].blk_dev = strdup(p);
+ fstab->recs[cnt].blk_device = strdup(p);
if (!(p = strtok_r(NULL, delim, &save_ptr))) {
- ERROR("Error parsing mnt_point\n");
+ ERROR("Error parsing mount_point\n");
return 0;
}
- fstab[cnt].mnt_point = strdup(p);
+ fstab->recs[cnt].mount_point = strdup(p);
if (!(p = strtok_r(NULL, delim, &save_ptr))) {
ERROR("Error parsing fs_type\n");
return 0;
}
- fstab[cnt].type = strdup(p);
+ fstab->recs[cnt].fs_type = strdup(p);
if (!(p = strtok_r(NULL, delim, &save_ptr))) {
ERROR("Error parsing mount_flags\n");
return 0;
}
tmp_fs_options[0] = '\0';
- fstab[cnt].flags = parse_flags(p, mount_flags, 0, tmp_fs_options, FS_OPTIONS_LEN);
+ fstab->recs[cnt].flags = parse_flags(p, mount_flags,
+ NULL, NULL, NULL, NULL,
+ tmp_fs_options, FS_OPTIONS_LEN);
/* fs_options are optional */
if (tmp_fs_options[0]) {
- fstab[cnt].fs_options = strdup(tmp_fs_options);
+ fstab->recs[cnt].fs_options = strdup(tmp_fs_options);
} else {
- fstab[cnt].fs_options = NULL;
+ fstab->recs[cnt].fs_options = NULL;
}
if (!(p = strtok_r(NULL, delim, &save_ptr))) {
ERROR("Error parsing fs_mgr_options\n");
return 0;
}
- fstab[cnt].fs_mgr_flags = parse_flags(p, fs_mgr_flags, &key_loc, 0, 0);
- fstab[cnt].key_loc = key_loc;
-
+ fstab->recs[cnt].fs_mgr_flags = parse_flags(p, fs_mgr_flags,
+ &key_loc, &part_length,
+ &label, &partnum,
+ NULL, 0);
+ fstab->recs[cnt].key_loc = key_loc;
+ fstab->recs[cnt].length = part_length;
+ fstab->recs[cnt].label = label;
+ fstab->recs[cnt].partnum = partnum;
cnt++;
}
fclose(fstab_file);
@@ -345,26 +407,32 @@ static struct fstab_rec *read_fstab(char *fstab_path)
return fstab;
}
-static void free_fstab(struct fstab_rec *fstab)
+void fs_mgr_free_fstab(struct fstab *fstab)
{
- int i = 0;
+ int i;
- while (fstab[i].blk_dev) {
+ for (i = 0; i < fstab->num_entries; i++) {
/* Free the pointers return by strdup(3) */
- free(fstab[i].blk_dev);
- free(fstab[i].mnt_point);
- free(fstab[i].type);
- free(fstab[i].fs_options);
- free(fstab[i].key_loc);
-
+ free(fstab->recs[i].blk_device);
+ free(fstab->recs[i].mount_point);
+ free(fstab->recs[i].fs_type);
+ free(fstab->recs[i].fs_options);
+ free(fstab->recs[i].key_loc);
+ free(fstab->recs[i].label);
i++;
}
- /* Free the actual fstab array created by calloc(3) */
+ /* Free the fstab_recs array created by calloc(3) */
+ free(fstab->recs);
+
+ /* Free the fstab filename */
+ free(fstab->fstab_filename);
+
+ /* Free fstab */
free(fstab);
}
-static void check_fs(char *blk_dev, char *type, char *target)
+static void check_fs(char *blk_device, char *fs_type, char *target)
{
pid_t pid;
int status;
@@ -373,7 +441,7 @@ static void check_fs(char *blk_dev, char *type, char *target)
char *tmpmnt_opts = "nomblk_io_submit,errors=remount-ro";
/* Check for the types of filesystems we know how to check */
- if (!strcmp(type, "ext2") || !strcmp(type, "ext3") || !strcmp(type, "ext4")) {
+ if (!strcmp(fs_type, "ext2") || !strcmp(fs_type, "ext3") || !strcmp(fs_type, "ext4")) {
/*
* First try to mount and unmount the filesystem. We do this because
* the kernel is more efficient than e2fsck in running the journal and
@@ -387,19 +455,19 @@ static void check_fs(char *blk_dev, char *type, char *target)
* filesytsem due to an error, e2fsck is still run to do a full check
* fix the filesystem.
*/
- ret = mount(blk_dev, target, type, tmpmnt_flags, tmpmnt_opts);
- if (! ret) {
+ ret = mount(blk_device, target, fs_type, tmpmnt_flags, tmpmnt_opts);
+ if (!ret) {
umount(target);
}
- INFO("Running %s on %s\n", E2FSCK_BIN, blk_dev);
+ INFO("Running %s on %s\n", E2FSCK_BIN, blk_device);
pid = fork();
if (pid > 0) {
/* Parent, wait for the child to return */
waitpid(pid, &status, 0);
} else if (pid == 0) {
/* child, run checker */
- execlp(E2FSCK_BIN, E2FSCK_BIN, "-y", blk_dev, (char *)NULL);
+ execlp(E2FSCK_BIN, E2FSCK_BIN, "-y", blk_device, (char *)NULL);
/* Only gets here on error */
ERROR("Cannot run fs_mgr binary %s\n", E2FSCK_BIN);
@@ -443,49 +511,62 @@ static int fs_match(char *in1, char *in2)
return ret;
}
-int fs_mgr_mount_all(char *fstab_file)
+int fs_mgr_mount_all(struct fstab *fstab)
{
int i = 0;
int encrypted = 0;
int ret = -1;
int mret;
- struct fstab_rec *fstab = 0;
- if (!(fstab = read_fstab(fstab_file))) {
+ if (!fstab) {
return ret;
}
- for (i = 0; fstab[i].blk_dev; i++) {
- if (fstab[i].fs_mgr_flags & MF_WAIT) {
- wait_for_file(fstab[i].blk_dev, WAIT_TIMEOUT);
+ for (i = 0; i < fstab->num_entries; i++) {
+ /* Don't mount entries that are managed by vold */
+ if (fstab->recs[i].fs_mgr_flags & (MF_VOLDMANAGED | MF_RECOVERYONLY)) {
+ continue;
}
- if (fstab[i].fs_mgr_flags & MF_CHECK) {
- check_fs(fstab[i].blk_dev, fstab[i].type, fstab[i].mnt_point);
+ /* Skip raw partition entries such as boot, recovery, etc */
+ if (!strcmp(fstab->recs[i].fs_type, "emmc") ||
+ !strcmp(fstab->recs[i].fs_type, "mtd")) {
+ continue;
}
- mret = mount(fstab[i].blk_dev, fstab[i].mnt_point, fstab[i].type,
- fstab[i].flags, fstab[i].fs_options);
+ if (fstab->recs[i].fs_mgr_flags & MF_WAIT) {
+ wait_for_file(fstab->recs[i].blk_device, WAIT_TIMEOUT);
+ }
+
+ if (fstab->recs[i].fs_mgr_flags & MF_CHECK) {
+ check_fs(fstab->recs[i].blk_device, fstab->recs[i].fs_type,
+ fstab->recs[i].mount_point);
+ }
+
+ mret = mount(fstab->recs[i].blk_device, fstab->recs[i].mount_point,
+ fstab->recs[i].fs_type, fstab->recs[i].flags,
+ fstab->recs[i].fs_options);
if (!mret) {
/* Success! Go get the next one */
continue;
}
/* mount(2) returned an error, check if it's encrypted and deal with it */
- if ((fstab[i].fs_mgr_flags & MF_CRYPT) && !partition_wiped(fstab[i].blk_dev)) {
+ if ((fstab->recs[i].fs_mgr_flags & MF_CRYPT) &&
+ !partition_wiped(fstab->recs[i].blk_device)) {
/* Need to mount a tmpfs at this mountpoint for now, and set
* properties that vold will query later for decrypting
*/
- if (mount("tmpfs", fstab[i].mnt_point, "tmpfs",
+ if (mount("tmpfs", fstab->recs[i].mount_point, "tmpfs",
MS_NOATIME | MS_NOSUID | MS_NODEV, CRYPTO_TMPFS_OPTIONS) < 0) {
ERROR("Cannot mount tmpfs filesystem for encrypted fs at %s\n",
- fstab[i].mnt_point);
+ fstab->recs[i].mount_point);
goto out;
}
encrypted = 1;
} else {
ERROR("Cannot mount filesystem on %s at %s\n",
- fstab[i].blk_dev, fstab[i].mnt_point);
+ fstab->recs[i].blk_device, fstab->recs[i].mount_point);
goto out;
}
}
@@ -497,49 +578,57 @@ int fs_mgr_mount_all(char *fstab_file)
}
out:
- free_fstab(fstab);
return ret;
}
-/* If tmp_mnt_point is non-null, mount the filesystem there. This is for the
+/* If tmp_mount_point is non-null, mount the filesystem there. This is for the
* tmp mount we do to check the user password
*/
-int fs_mgr_do_mount(char *fstab_file, char *n_name, char *n_blk_dev, char *tmp_mnt_point)
+int fs_mgr_do_mount(struct fstab *fstab, char *n_name, char *n_blk_device,
+ char *tmp_mount_point)
{
int i = 0;
int ret = -1;
- struct fstab_rec *fstab = 0;
char *m;
- if (!(fstab = read_fstab(fstab_file))) {
+ if (!fstab) {
return ret;
}
- for (i = 0; fstab[i].blk_dev; i++) {
- if (!fs_match(fstab[i].mnt_point, n_name)) {
+ for (i = 0; i < fstab->num_entries; i++) {
+ if (!fs_match(fstab->recs[i].mount_point, n_name)) {
continue;
}
/* We found our match */
+ /* If this is a raw partition, report an error */
+ if (!strcmp(fstab->recs[i].fs_type, "emmc") ||
+ !strcmp(fstab->recs[i].fs_type, "mtd")) {
+ ERROR("Cannot mount filesystem of type %s on %s\n",
+ fstab->recs[i].fs_type, n_blk_device);
+ goto out;
+ }
+
/* First check the filesystem if requested */
- if (fstab[i].fs_mgr_flags & MF_WAIT) {
- wait_for_file(n_blk_dev, WAIT_TIMEOUT);
+ if (fstab->recs[i].fs_mgr_flags & MF_WAIT) {
+ wait_for_file(n_blk_device, WAIT_TIMEOUT);
}
- if (fstab[i].fs_mgr_flags & MF_CHECK) {
- check_fs(n_blk_dev, fstab[i].type, fstab[i].mnt_point);
+ if (fstab->recs[i].fs_mgr_flags & MF_CHECK) {
+ check_fs(n_blk_device, fstab->recs[i].fs_type,
+ fstab->recs[i].mount_point);
}
/* Now mount it where requested */
- if (tmp_mnt_point) {
- m = tmp_mnt_point;
+ if (tmp_mount_point) {
+ m = tmp_mount_point;
} else {
- m = fstab[i].mnt_point;
+ m = fstab->recs[i].mount_point;
}
- if (mount(n_blk_dev, m, fstab[i].type,
- fstab[i].flags, fstab[i].fs_options)) {
+ if (mount(n_blk_device, m, fstab->recs[i].fs_type,
+ fstab->recs[i].flags, fstab->recs[i].fs_options)) {
ERROR("Cannot mount filesystem on %s at %s\n",
- n_blk_dev, m);
+ n_blk_device, m);
goto out;
} else {
ret = 0;
@@ -548,10 +637,9 @@ int fs_mgr_do_mount(char *fstab_file, char *n_name, char *n_blk_dev, char *tmp_m
}
/* We didn't find a match, say so and return an error */
- ERROR("Cannot find mount point %s in fstab\n", fstab[i].mnt_point);
+ ERROR("Cannot find mount point %s in fstab\n", fstab->recs[i].mount_point);
out:
- free_fstab(fstab);
return ret;
}
@@ -574,65 +662,128 @@ int fs_mgr_do_tmpfs_mount(char *n_name)
return 0;
}
-int fs_mgr_unmount_all(char *fstab_file)
+int fs_mgr_unmount_all(struct fstab *fstab)
{
int i = 0;
int ret = 0;
- struct fstab_rec *fstab = 0;
- if (!(fstab = read_fstab(fstab_file))) {
+ if (!fstab) {
return -1;
}
- while (fstab[i].blk_dev) {
- if (umount(fstab[i].mnt_point)) {
- ERROR("Cannot unmount filesystem at %s\n", fstab[i].mnt_point);
+ while (fstab->recs[i].blk_device) {
+ if (umount(fstab->recs[i].mount_point)) {
+ ERROR("Cannot unmount filesystem at %s\n", fstab->recs[i].mount_point);
ret = -1;
}
i++;
}
- free_fstab(fstab);
return ret;
}
/*
* key_loc must be at least PROPERTY_VALUE_MAX bytes long
*
- * real_blk_dev must be at least PROPERTY_VALUE_MAX bytes long
+ * real_blk_device must be at least PROPERTY_VALUE_MAX bytes long
*/
-int fs_mgr_get_crypt_info(char *fstab_file, char *key_loc, char *real_blk_dev, int size)
+int fs_mgr_get_crypt_info(struct fstab *fstab, char *key_loc, char *real_blk_device, int size)
{
int i = 0;
- struct fstab_rec *fstab = 0;
- if (!(fstab = read_fstab(fstab_file))) {
+ if (!fstab) {
return -1;
}
/* Initialize return values to null strings */
if (key_loc) {
*key_loc = '\0';
}
- if (real_blk_dev) {
- *real_blk_dev = '\0';
+ if (real_blk_device) {
+ *real_blk_device = '\0';
}
/* Look for the encryptable partition to find the data */
- for (i = 0; fstab[i].blk_dev; i++) {
- if (!(fstab[i].fs_mgr_flags & MF_CRYPT)) {
+ for (i = 0; i < fstab->num_entries; i++) {
+ /* Don't deal with vold managed enryptable partitions here */
+ if (fstab->recs[i].fs_mgr_flags & MF_VOLDMANAGED) {
+ continue;
+ }
+ if (!(fstab->recs[i].fs_mgr_flags & MF_CRYPT)) {
continue;
}
/* We found a match */
if (key_loc) {
- strlcpy(key_loc, fstab[i].key_loc, size);
+ strlcpy(key_loc, fstab->recs[i].key_loc, size);
}
- if (real_blk_dev) {
- strlcpy(real_blk_dev, fstab[i].blk_dev, size);
+ if (real_blk_device) {
+ strlcpy(real_blk_device, fstab->recs[i].blk_device, size);
}
break;
}
- free_fstab(fstab);
return 0;
}
+/* Add an entry to the fstab, and return 0 on success or -1 on error */
+int fs_mgr_add_entry(struct fstab *fstab,
+ const char *mount_point, const char *fs_type,
+ const char *blk_device, long long length)
+{
+ struct fstab_rec *new_fstab_recs;
+ int n = fstab->num_entries;
+
+ new_fstab_recs = (struct fstab_rec *)
+ realloc(fstab->recs, sizeof(struct fstab_rec) * (n + 1));
+
+ if (!new_fstab_recs) {
+ return -1;
+ }
+
+ /* A new entry was added, so initialize it */
+ memset(&new_fstab_recs[n], 0, sizeof(struct fstab_rec));
+ new_fstab_recs[n].mount_point = strdup(mount_point);
+ new_fstab_recs[n].fs_type = strdup(fs_type);
+ new_fstab_recs[n].blk_device = strdup(blk_device);
+ new_fstab_recs[n].length = 0;
+
+ /* Update the fstab struct */
+ fstab->recs = new_fstab_recs;
+ fstab->num_entries++;
+
+ return 0;
+}
+
+struct fstab_rec *fs_mgr_get_entry_for_mount_point(struct fstab *fstab, const char *path)
+{
+ int i;
+
+ if (!fstab) {
+ return NULL;
+ }
+
+ for (i = 0; i < fstab->num_entries; i++) {
+ int len = strlen(fstab->recs[i].mount_point);
+ if (strncmp(path, fstab->recs[i].mount_point, len) == 0 &&
+ (path[len] == '\0' || path[len] == '/')) {
+ return &fstab->recs[i];
+ }
+ }
+
+ return NULL;
+}
+
+int fs_mgr_is_voldmanaged(struct fstab_rec *fstab)
+{
+ return fstab->fs_mgr_flags & MF_VOLDMANAGED;
+}
+
+int fs_mgr_is_nonremovable(struct fstab_rec *fstab)
+{
+ return fstab->fs_mgr_flags & MF_NONREMOVABLE;
+}
+
+int fs_mgr_is_encryptable(struct fstab_rec *fstab)
+{
+ return fstab->fs_mgr_flags & MF_CRYPT;
+}
+
diff --git a/fs_mgr/fs_mgr_main.c b/fs_mgr/fs_mgr_main.c
index 81febf124..4bde4a1da 100644
--- a/fs_mgr/fs_mgr_main.c
+++ b/fs_mgr/fs_mgr_main.c
@@ -82,7 +82,8 @@ int main(int argc, char *argv[])
int n_flag=0;
char *n_name;
char *n_blk_dev;
- char *fstab;
+ char *fstab_file;
+ struct fstab *fstab;
klog_init();
klog_set_level(6);
@@ -90,7 +91,9 @@ int main(int argc, char *argv[])
parse_options(argc, argv, &a_flag, &u_flag, &n_flag, &n_name, &n_blk_dev);
/* The name of the fstab file is last, after the option */
- fstab = argv[argc - 1];
+ fstab_file = argv[argc - 1];
+
+ fstab = fs_mgr_read_fstab(fstab_file);
if (a_flag) {
return fs_mgr_mount_all(fstab);
@@ -103,6 +106,8 @@ int main(int argc, char *argv[])
exit(1);
}
+ fs_mgr_free_fstab(fstab);
+
/* Should not get here */
exit(1);
}
diff --git a/fs_mgr/fs_mgr_priv.h b/fs_mgr/fs_mgr_priv.h
index 175fdabd2..75dad498d 100644
--- a/fs_mgr/fs_mgr_priv.h
+++ b/fs_mgr/fs_mgr_priv.h
@@ -25,16 +25,6 @@
#define CRYPTO_TMPFS_OPTIONS "size=128m,mode=0771,uid=1000,gid=1000"
-struct fstab_rec {
- char *blk_dev;
- char *mnt_point;
- char *type;
- unsigned long flags;
- char *fs_options;
- int fs_mgr_flags;
- char *key_loc;
-};
-
#define WAIT_TIMEOUT 5
/* fstab has the following format:
@@ -59,8 +49,8 @@ struct fstab_rec {
* run an fscheck program on the <source> before mounting the filesystem.
* If check is specifed on a read-only filesystem, it is ignored.
* Also, "encryptable" means that filesystem can be encrypted.
- * The "encryptable" flag _MUST_ be followed by a : and a string which
- * is the location of the encryption keys. I can either be a path
+ * The "encryptable" flag _MUST_ be followed by a = and a string which
+ * is the location of the encryption keys. It can either be a path
* to a file or partition which contains the keys, or the word "footer"
* which means the keys are in the last 16 Kbytes of the partition
* containing the filesystem.
@@ -72,9 +62,13 @@ struct fstab_rec {
*
*/
-#define MF_WAIT 0x1
-#define MF_CHECK 0x2
-#define MF_CRYPT 0x4
+#define MF_WAIT 0x1
+#define MF_CHECK 0x2
+#define MF_CRYPT 0x4
+#define MF_NONREMOVABLE 0x8
+#define MF_VOLDMANAGED 0x10
+#define MF_LENGTH 0x20
+#define MF_RECOVERYONLY 0x40
#endif /* __CORE_FS_MGR_PRIV_H */
diff --git a/fs_mgr/include/fs_mgr.h b/fs_mgr/include/fs_mgr.h
index 76abb8332..05bcc1bdf 100644
--- a/fs_mgr/include/fs_mgr.h
+++ b/fs_mgr/include/fs_mgr.h
@@ -17,11 +17,48 @@
#ifndef __CORE_FS_MGR_H
#define __CORE_FS_MGR_H
-int fs_mgr_mount_all(char *fstab_file);
-int fs_mgr_do_mount(char *fstab_file, char *n_name, char *n_blk_dev, char *tmp_mnt_point);
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct fstab {
+ int num_entries;
+ struct fstab_rec *recs;
+ char *fstab_filename;
+};
+
+struct fstab_rec {
+ char *blk_device;
+ char *mount_point;
+ char *fs_type;
+ unsigned long flags;
+ char *fs_options;
+ int fs_mgr_flags;
+ char *key_loc;
+ long long length;
+ char *label;
+ int partnum;
+};
+
+struct fstab *fs_mgr_read_fstab(const char *fstab_path);
+void fs_mgr_free_fstab(struct fstab *fstab);
+int fs_mgr_mount_all(struct fstab *fstab);
+int fs_mgr_do_mount(struct fstab *fstab, char *n_name, char *n_blk_device,
+ char *tmp_mount_point);
int fs_mgr_do_tmpfs_mount(char *n_name);
-int fs_mgr_unmount_all(char *fstab_file);
-int fs_mgr_get_crypt_info(char *fstab_file, char *key_loc, char *real_blk_dev, int size);
+int fs_mgr_unmount_all(struct fstab *fstab);
+int fs_mgr_get_crypt_info(struct fstab *fstab, char *key_loc,
+ char *real_blk_device, int size);
+int fs_mgr_add_entry(struct fstab *fstab,
+ const char *mount_point, const char *fs_type,
+ const char *blk_device, long long length);
+struct fstab_rec *fs_mgr_get_entry_for_mount_point(struct fstab *fstab, const char *path);
+int fs_mgr_is_voldmanaged(struct fstab_rec *fstab);
+int fs_mgr_is_nonremovable(struct fstab_rec *fstab);
+int fs_mgr_is_encryptable(struct fstab_rec *fstab);
+#ifdef __cplusplus
+}
+#endif
#endif /* __CORE_FS_MGR_H */
diff --git a/include/cutils/aref.h b/include/cutils/aref.h
new file mode 100644
index 000000000..460ac020b
--- /dev/null
+++ b/include/cutils/aref.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _CUTILS_AREF_H_
+#define _CUTILS_AREF_H_
+
+#include <stddef.h>
+#include <sys/cdefs.h>
+
+#ifdef ANDROID_SMP
+#include <cutils/atomic-inline.h>
+#else
+#include <cutils/atomic.h>
+#endif
+
+__BEGIN_DECLS
+
+#define AREF_TO_ITEM(aref, container, member) \
+ (container *) (((char*) (aref)) - offsetof(container, member))
+
+struct aref
+{
+ volatile int32_t count;
+};
+
+static inline void aref_init(struct aref *r)
+{
+ r->count = 1;
+}
+
+static inline int32_t aref_count(struct aref *r)
+{
+ return r->count;
+}
+
+static inline void aref_get(struct aref *r)
+{
+ android_atomic_inc(&r->count);
+}
+
+static inline void aref_put(struct aref *r, void (*release)(struct aref *))
+{
+ if (android_atomic_dec(&r->count) == 1)
+ release(r);
+}
+
+__END_DECLS
+
+#endif // _CUTILS_AREF_H_
diff --git a/include/cutils/bitops.h b/include/cutils/bitops.h
index 1b3b762e6..eb44236f5 100644
--- a/include/cutils/bitops.h
+++ b/include/cutils/bitops.h
@@ -17,10 +17,79 @@
#ifndef __CUTILS_BITOPS_H
#define __CUTILS_BITOPS_H
+#include <stdbool.h>
+#include <string.h>
+#include <strings.h>
#include <sys/cdefs.h>
__BEGIN_DECLS
+/*
+ * Bitmask Operations
+ *
+ * Note this doesn't provide any locking/exclusion, and isn't atomic.
+ * Additionally no bounds checking is done on the bitmask array.
+ *
+ * Example:
+ *
+ * int num_resources;
+ * unsigned int resource_bits[BITS_TO_WORDS(num_resources)];
+ * bitmask_init(resource_bits, num_resources);
+ * ...
+ * int bit = bitmask_ffz(resource_bits, num_resources);
+ * bitmask_set(resource_bits, bit);
+ * ...
+ * if (bitmask_test(resource_bits, bit)) { ... }
+ * ...
+ * bitmask_clear(resource_bits, bit);
+ *
+ */
+
+#define BITS_PER_WORD (sizeof(unsigned int) * 8)
+#define BITS_TO_WORDS(x) (((x) + BITS_PER_WORD - 1) / BITS_PER_WORD)
+#define BIT_IN_WORD(x) ((x) % BITS_PER_WORD)
+#define BIT_WORD(x) ((x) / BITS_PER_WORD)
+#define BIT_MASK(x) (1 << BIT_IN_WORD(x))
+
+static inline void bitmask_init(unsigned int *bitmask, int num_bits)
+{
+ memset(bitmask, 0, BITS_TO_WORDS(num_bits)*sizeof(unsigned int));
+}
+
+static inline int bitmask_ffz(unsigned int *bitmask, int num_bits)
+{
+ int bit, result;
+ unsigned int i;
+
+ for (i = 0; i < BITS_TO_WORDS(num_bits); i++) {
+ bit = ffs(~bitmask[i]);
+ if (bit) {
+ // ffs is 1-indexed, return 0-indexed result
+ bit--;
+ result = BITS_PER_WORD * i + bit;
+ if (result >= num_bits)
+ return -1;
+ return result;
+ }
+ }
+ return -1;
+}
+
+static inline void bitmask_set(unsigned int *bitmask, int bit)
+{
+ bitmask[BIT_WORD(bit)] |= BIT_MASK(bit);
+}
+
+static inline void bitmask_clear(unsigned int *bitmask, int bit)
+{
+ bitmask[BIT_WORD(bit)] &= ~BIT_MASK(bit);
+}
+
+static inline bool bitmask_test(unsigned int *bitmask, int bit)
+{
+ return bitmask[BIT_WORD(bit)] & BIT_MASK(bit);
+}
+
static inline int popcount(unsigned int x)
{
return __builtin_popcount(x);
diff --git a/include/cutils/trace.h b/include/cutils/trace.h
new file mode 100644
index 000000000..55aabdde7
--- /dev/null
+++ b/include/cutils/trace.h
@@ -0,0 +1,254 @@
+/*
+ * Copyright (C) 2012 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 _LIBS_CUTILS_TRACE_H
+#define _LIBS_CUTILS_TRACE_H
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <unistd.h>
+#include <cutils/compiler.h>
+
+#ifdef ANDROID_SMP
+#include <cutils/atomic-inline.h>
+#else
+#include <cutils/atomic.h>
+#endif
+
+__BEGIN_DECLS
+
+/**
+ * The ATRACE_TAG macro can be defined before including this header to trace
+ * using one of the tags defined below. It must be defined to one of the
+ * following ATRACE_TAG_* macros. The trace tag is used to filter tracing in
+ * userland to avoid some of the runtime cost of tracing when it is not desired.
+ *
+ * Defining ATRACE_TAG to be ATRACE_TAG_ALWAYS will result in the tracing always
+ * being enabled - this should ONLY be done for debug code, as userland tracing
+ * has a performance cost even when the trace is not being recorded. Defining
+ * ATRACE_TAG to be ATRACE_TAG_NEVER or leaving ATRACE_TAG undefined will result
+ * in the tracing always being disabled.
+ *
+ * ATRACE_TAG_HAL should be bitwise ORed with the relevant tags for tracing
+ * within a hardware module. For example a camera hardware module would set:
+ * #define ATRACE_TAG (ATRACE_TAG_CAMERA | ATRACE_TAG_HAL)
+ *
+ * Keep these in sync with frameworks/base/core/java/android/os/Trace.java.
+ */
+#define ATRACE_TAG_NEVER 0 // This tag is never enabled.
+#define ATRACE_TAG_ALWAYS (1<<0) // This tag is always enabled.
+#define ATRACE_TAG_GRAPHICS (1<<1)
+#define ATRACE_TAG_INPUT (1<<2)
+#define ATRACE_TAG_VIEW (1<<3)
+#define ATRACE_TAG_WEBVIEW (1<<4)
+#define ATRACE_TAG_WINDOW_MANAGER (1<<5)
+#define ATRACE_TAG_ACTIVITY_MANAGER (1<<6)
+#define ATRACE_TAG_SYNC_MANAGER (1<<7)
+#define ATRACE_TAG_AUDIO (1<<8)
+#define ATRACE_TAG_VIDEO (1<<9)
+#define ATRACE_TAG_CAMERA (1<<10)
+#define ATRACE_TAG_HAL (1<<11)
+#define ATRACE_TAG_APP (1<<12)
+#define ATRACE_TAG_LAST ATRACE_TAG_APP
+
+// Reserved for initialization.
+#define ATRACE_TAG_NOT_READY (1LL<<63)
+
+#define ATRACE_TAG_VALID_MASK ((ATRACE_TAG_LAST - 1) | ATRACE_TAG_LAST)
+
+#ifndef ATRACE_TAG
+#define ATRACE_TAG ATRACE_TAG_NEVER
+#elif ATRACE_TAG > ATRACE_TAG_VALID_MASK
+#error ATRACE_TAG must be defined to be one of the tags defined in cutils/trace.h
+#endif
+
+/**
+ * Maximum size of a message that can be logged to the trace buffer.
+ * Note this message includes a tag, the pid, and the string given as the name.
+ * Names should be kept short to get the most use of the trace buffer.
+ */
+#define ATRACE_MESSAGE_LENGTH 1024
+
+/**
+ * Opens the trace file for writing and reads the property for initial tags.
+ * The atrace.tags.enableflags property sets the tags to trace.
+ * This function should not be explicitly called, the first call to any normal
+ * trace function will cause it to be run safely.
+ */
+void atrace_setup();
+
+/**
+ * If tracing is ready, set atrace_enabled_tags to the system property
+ * debug.atrace.tags.enableflags. Can be used as a sysprop change callback.
+ */
+void atrace_update_tags();
+
+/**
+ * Set whether the process is debuggable. By default the process is not
+ * considered debuggable. If the process is not debuggable then application-
+ * level tracing is not allowed unless the ro.debuggable system property is
+ * set to '1'.
+ */
+void atrace_set_debuggable(bool debuggable);
+
+/**
+ * Flag indicating whether setup has been completed, initialized to 0.
+ * Nonzero indicates setup has completed.
+ * Note: This does NOT indicate whether or not setup was successful.
+ */
+extern int32_t atrace_is_ready;
+
+/**
+ * Set of ATRACE_TAG flags to trace for, initialized to ATRACE_TAG_NOT_READY.
+ * A value of zero indicates setup has failed.
+ * Any other nonzero value indicates setup has succeeded, and tracing is on.
+ */
+extern uint64_t atrace_enabled_tags;
+
+/**
+ * Handle to the kernel's trace buffer, initialized to -1.
+ * Any other value indicates setup has succeeded, and is a valid fd for tracing.
+ */
+extern int atrace_marker_fd;
+
+/**
+ * atrace_init readies the process for tracing by opening the trace_marker file.
+ * Calling any trace function causes this to be run, so calling it is optional.
+ * This can be explicitly run to avoid setup delay on first trace function.
+ */
+#define ATRACE_INIT() atrace_init()
+static inline void atrace_init()
+{
+ if (CC_UNLIKELY(!android_atomic_acquire_load(&atrace_is_ready))) {
+ atrace_setup();
+ }
+}
+
+/**
+ * Get the mask of all tags currently enabled.
+ * It can be used as a guard condition around more expensive trace calculations.
+ * Every trace function calls this, which ensures atrace_init is run.
+ */
+#define ATRACE_GET_ENABLED_TAGS() atrace_get_enabled_tags()
+static inline uint64_t atrace_get_enabled_tags()
+{
+ atrace_init();
+ return atrace_enabled_tags;
+}
+
+/**
+ * Test if a given tag is currently enabled.
+ * Returns nonzero if the tag is enabled, otherwise zero.
+ * It can be used as a guard condition around more expensive trace calculations.
+ */
+#define ATRACE_ENABLED() atrace_is_tag_enabled(ATRACE_TAG)
+static inline uint64_t atrace_is_tag_enabled(uint64_t tag)
+{
+ return atrace_get_enabled_tags() & tag;
+}
+
+/**
+ * Trace the beginning of a context. name is used to identify the context.
+ * This is often used to time function execution.
+ */
+#define ATRACE_BEGIN(name) atrace_begin(ATRACE_TAG, name)
+static inline void atrace_begin(uint64_t tag, const char* name)
+{
+ if (CC_UNLIKELY(atrace_is_tag_enabled(tag))) {
+ char buf[ATRACE_MESSAGE_LENGTH];
+ size_t len;
+
+ len = snprintf(buf, ATRACE_MESSAGE_LENGTH, "B|%d|%s", getpid(), name);
+ write(atrace_marker_fd, buf, len);
+ }
+}
+
+/**
+ * Trace the end of a context.
+ * This should match up (and occur after) a corresponding ATRACE_BEGIN.
+ */
+#define ATRACE_END() atrace_end(ATRACE_TAG)
+static inline void atrace_end(uint64_t tag)
+{
+ if (CC_UNLIKELY(atrace_is_tag_enabled(tag))) {
+ char c = 'E';
+ write(atrace_marker_fd, &c, 1);
+ }
+}
+
+/**
+ * Trace the beginning of an asynchronous event. Unlike ATRACE_BEGIN/ATRACE_END
+ * contexts, asynchronous events do not need to be nested. The name describes
+ * the event, and the cookie provides a unique identifier for distinguishing
+ * simultaneous events. The name and cookie used to begin an event must be
+ * used to end it.
+ */
+#define ATRACE_ASYNC_BEGIN(name, cookie) \
+ atrace_async_begin(ATRACE_TAG, name, cookie)
+static inline void atrace_async_begin(uint64_t tag, const char* name,
+ int32_t cookie)
+{
+ if (CC_UNLIKELY(atrace_is_tag_enabled(tag))) {
+ char buf[ATRACE_MESSAGE_LENGTH];
+ size_t len;
+
+ len = snprintf(buf, ATRACE_MESSAGE_LENGTH, "S|%d|%s|%d", getpid(),
+ name, cookie);
+ write(atrace_marker_fd, buf, len);
+ }
+}
+
+/**
+ * Trace the end of an asynchronous event.
+ * This should have a corresponding ATRACE_ASYNC_BEGIN.
+ */
+#define ATRACE_ASYNC_END(name, cookie) atrace_async_end(ATRACE_TAG, name, cookie)
+static inline void atrace_async_end(uint64_t tag, const char* name,
+ int32_t cookie)
+{
+ if (CC_UNLIKELY(atrace_is_tag_enabled(tag))) {
+ char buf[ATRACE_MESSAGE_LENGTH];
+ size_t len;
+
+ len = snprintf(buf, ATRACE_MESSAGE_LENGTH, "F|%d|%s|%d", getpid(),
+ name, cookie);
+ write(atrace_marker_fd, buf, len);
+ }
+}
+
+
+/**
+ * Traces an integer counter value. name is used to identify the counter.
+ * This can be used to track how a value changes over time.
+ */
+#define ATRACE_INT(name, value) atrace_int(ATRACE_TAG, name, value)
+static inline void atrace_int(uint64_t tag, const char* name, int32_t value)
+{
+ if (CC_UNLIKELY(atrace_is_tag_enabled(tag))) {
+ char buf[ATRACE_MESSAGE_LENGTH];
+ size_t len;
+
+ len = snprintf(buf, ATRACE_MESSAGE_LENGTH, "C|%d|%s|%d",
+ getpid(), name, value);
+ write(atrace_marker_fd, buf, len);
+ }
+}
+
+__END_DECLS
+
+#endif // _LIBS_CUTILS_TRACE_H
diff --git a/include/cutils/zygote.h b/include/cutils/zygote.h
index 22721a6bd..a7480d320 100644
--- a/include/cutils/zygote.h
+++ b/include/cutils/zygote.h
@@ -23,7 +23,6 @@ extern "C" {
int zygote_run_oneshot(int sendStdio, int argc, const char **argv);
int zygote_run(int argc, const char **argv);
-int zygote_run_wait(int argc, const char **argv, void (*post_run_func)(int));
#ifdef __cplusplus
}
diff --git a/include/netutils/dhcp.h b/include/netutils/dhcp.h
index d25e58fa6..bd2c9571a 100644
--- a/include/netutils/dhcp.h
+++ b/include/netutils/dhcp.h
@@ -27,11 +27,18 @@ extern int dhcp_do_request(const char *ifname,
char *ipaddr,
char *gateway,
uint32_t *prefixLength,
- char *dns1,
- char *dns2,
+ char *dns[],
char *server,
uint32_t *lease,
char *vendorInfo);
+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);
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_config.h b/include/private/android_filesystem_config.h
index 53bd166b6..540318fd5 100644
--- a/include/private/android_filesystem_config.h
+++ b/include/private/android_filesystem_config.h
@@ -187,6 +187,7 @@ static const struct fs_path_config android_dirs[] = {
{ 00755, AID_ROOT, AID_SHELL, 0, "system/vendor" },
{ 00755, AID_ROOT, AID_SHELL, 0, "system/xbin" },
{ 00755, AID_ROOT, AID_ROOT, 0, "system/etc/ppp" },
+ { 00755, AID_ROOT, AID_SHELL, 0, "vendor" },
{ 00777, AID_ROOT, AID_ROOT, 0, "sdcard" },
{ 00755, AID_ROOT, AID_ROOT, 0, 0 },
};
@@ -234,6 +235,7 @@ static const struct fs_path_config android_files[] = {
{ 00755, AID_ROOT, AID_ROOT, 0, "system/lib/valgrind/*" },
{ 00755, AID_ROOT, AID_SHELL, 0, "system/xbin/*" },
{ 00755, AID_ROOT, AID_SHELL, 0, "system/vendor/bin/*" },
+ { 00755, AID_ROOT, AID_SHELL, 0, "vendor/bin/*" },
{ 00750, AID_ROOT, AID_SHELL, 0, "sbin/*" },
{ 00755, AID_ROOT, AID_ROOT, 0, "bin/*" },
{ 00750, AID_ROOT, AID_SHELL, 0, "init*" },
diff --git a/include/sync/sw_sync.h b/include/sync/sw_sync.h
new file mode 100644
index 000000000..3bf4110e2
--- /dev/null
+++ b/include/sync/sw_sync.h
@@ -0,0 +1,37 @@
+/*
+ * sw_sync.h
+ *
+ * Copyright 2013 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 __SYS_CORE_SW_SYNC_H
+#define __SYS_CORE_SW_SYNC_H
+
+#include "sync.h"
+
+__BEGIN_DECLS
+
+/*
+ * sw_sync is mainly intended for testing and should not be compiled into
+ * production kernels
+ */
+
+int sw_sync_timeline_create(void);
+int sw_sync_timeline_inc(int fd, unsigned count);
+int sw_sync_fence_create(int fd, const char *name, unsigned value);
+
+__END_DECLS
+
+#endif /* __SYS_CORE_SW_SYNC_H */
diff --git a/include/sync/sync.h b/include/sync/sync.h
index 918acf652..2e5d82f15 100644
--- a/include/sync/sync.h
+++ b/include/sync/sync.h
@@ -49,14 +49,6 @@ struct sync_pt_info *sync_pt_info(struct sync_fence_info_data *info,
struct sync_pt_info *itr);
void sync_fence_info_free(struct sync_fence_info_data *info);
-/* sw_sync is mainly inteded for testing and should not be complied into
- * production kernels
- */
-
-int sw_sync_timeline_create(void);
-int sw_sync_timeline_inc(int fd, unsigned count);
-int sw_sync_fence_create(int fd, const char *name, unsigned value);
-
__END_DECLS
#endif /* __SYS_CORE_SYNC_H */
diff --git a/include/system/audio.h b/include/system/audio.h
index d246070a2..da235dd1b 100644
--- a/include/system/audio.h
+++ b/include/system/audio.h
@@ -239,6 +239,7 @@ enum {
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),
AUDIO_CHANNEL_IN_ALL = (AUDIO_CHANNEL_IN_LEFT |
AUDIO_CHANNEL_IN_RIGHT |
AUDIO_CHANNEL_IN_FRONT |
diff --git a/include/system/graphics.h b/include/system/graphics.h
index 82b5fcc87..ab064db62 100644
--- a/include/system/graphics.h
+++ b/include/system/graphics.h
@@ -87,6 +87,54 @@ enum {
*/
HAL_PIXEL_FORMAT_YV12 = 0x32315659, // YCrCb 4:2:0 Planar
+
+ /*
+ * Android Y8 format:
+ *
+ * This format is exposed outside of the HAL to the framework.
+ * The expected gralloc usage flags are SW_* and HW_CAMERA_*,
+ * and no other HW_ flags will be used.
+ *
+ * Y8 is a YUV planar format comprised of a WxH Y plane,
+ * with each pixel being represented by 8 bits.
+ *
+ * It is equivalent to just the Y plane from YV12.
+ *
+ * This format assumes
+ * - an even width
+ * - an even height
+ * - a horizontal stride multiple of 16 pixels
+ * - a vertical stride equal to the height
+ *
+ * size = stride * height
+ *
+ */
+ HAL_PIXEL_FORMAT_Y8 = 0x20203859,
+
+ /*
+ * Android Y16 format:
+ *
+ * This format is exposed outside of the HAL to the framework.
+ * The expected gralloc usage flags are SW_* and HW_CAMERA_*,
+ * and no other HW_ flags will be used.
+ *
+ * Y16 is a YUV planar format comprised of a WxH Y plane,
+ * with each pixel being represented by 16 bits.
+ *
+ * It is just like Y8, but has double the bits per pixel (little endian).
+ *
+ * This format assumes
+ * - an even width
+ * - an even height
+ * - a horizontal stride multiple of 16 pixels
+ * - a vertical stride equal to the height
+ * - strides are specified in pixels, not in bytes
+ *
+ * size = stride * height * 2
+ *
+ */
+ HAL_PIXEL_FORMAT_Y16 = 0x20363159,
+
/*
* Android RAW sensor format:
*
diff --git a/include/system/window.h b/include/system/window.h
index 4698fb394..b8a19c80f 100644
--- a/include/system/window.h
+++ b/include/system/window.h
@@ -321,7 +321,6 @@ enum {
enum {
NATIVE_WINDOW_FRAMEBUFFER = 0, /* FramebufferNativeWindow */
NATIVE_WINDOW_SURFACE = 1, /* Surface */
- NATIVE_WINDOW_SURFACE_TEXTURE_CLIENT = 2, /* SurfaceTextureClient */
};
/* parameter for NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP
diff --git a/init/builtins.c b/init/builtins.c
index dc7900e22..0f9f13136 100644
--- a/init/builtins.c
+++ b/init/builtins.c
@@ -464,6 +464,7 @@ int do_mount_all(int nargs, char **args)
int child_ret = -1;
int status;
const char *prop;
+ struct fstab *fstab;
if (nargs != 2) {
return -1;
@@ -487,7 +488,9 @@ int do_mount_all(int nargs, char **args)
} else if (pid == 0) {
/* child, call fs_mgr_mount_all() */
klog_set_level(6); /* So we can see what fs_mgr_mount_all() does */
- child_ret = fs_mgr_mount_all(args[1]);
+ fstab = fs_mgr_read_fstab(args[1]);
+ child_ret = fs_mgr_mount_all(fstab);
+ fs_mgr_free_fstab(fstab);
if (child_ret == -1) {
ERROR("fs_mgr_mount_all returned an error\n");
}
diff --git a/init/init.c b/init/init.c
index 39df0ffae..f8b21e64a 100755
--- a/init/init.c
+++ b/init/init.c
@@ -879,6 +879,7 @@ int main(int argc, char **argv)
*/
restorecon("/dev");
restorecon("/dev/socket");
+ restorecon("/dev/__properties__");
is_charger = !strcmp(bootmode, "charger");
diff --git a/init/init_parser.c b/init/init_parser.c
index beb9188fc..686640ed4 100644
--- a/init/init_parser.c
+++ b/init/init_parser.c
@@ -571,6 +571,7 @@ void queue_builtin_action(int (*func)(int nargs, char **args), char *name)
act = calloc(1, sizeof(*act));
act->name = name;
list_init(&act->commands);
+ list_init(&act->qlist);
cmd = calloc(1, sizeof(*cmd));
cmd->func = func;
@@ -583,7 +584,9 @@ void queue_builtin_action(int (*func)(int nargs, char **args), char *name)
void action_add_queue_tail(struct action *act)
{
- list_add_tail(&action_queue, &act->qlist);
+ if (list_empty(&act->qlist)) {
+ list_add_tail(&action_queue, &act->qlist);
+ }
}
struct action *action_remove_queue_head(void)
@@ -594,6 +597,7 @@ struct action *action_remove_queue_head(void)
struct listnode *node = list_head(&action_queue);
struct action *act = node_to_item(node, struct action, qlist);
list_remove(node);
+ list_init(node);
return act;
}
}
@@ -825,6 +829,7 @@ static void *parse_action(struct parse_state *state, int nargs, char **args)
act = calloc(1, sizeof(*act));
act->name = args[1];
list_init(&act->commands);
+ list_init(&act->qlist);
list_add_tail(&action_list, &act->alist);
/* XXX add to hash */
return act;
diff --git a/init/keychords.c b/init/keychords.c
index aab08195e..061d15701 100644
--- a/init/keychords.c
+++ b/init/keychords.c
@@ -100,10 +100,7 @@ void handle_keychord()
int ret;
__u16 id;
- // only handle keychords if ro.debuggable is set or adb is enabled.
- // the logic here is that bugreports should be enabled in userdebug or eng builds
- // and on user builds for users that are developers.
- debuggable = property_get("ro.debuggable");
+ // Only handle keychords if adb is enabled.
adb_enabled = property_get("init.svc.adbd");
ret = read(keychord_fd, &id, sizeof(id));
if (ret != sizeof(id)) {
@@ -111,8 +108,7 @@ void handle_keychord()
return;
}
- if ((debuggable && !strcmp(debuggable, "1")) ||
- (adb_enabled && !strcmp(adb_enabled, "running"))) {
+ if ((adb_enabled && !strcmp(adb_enabled, "running"))) {
svc = service_find_by_keychord(id);
if (svc) {
INFO("starting service %s from keychord\n", svc->name);
diff --git a/init/property_service.c b/init/property_service.c
index 61dd86fdc..578000154 100755
--- a/init/property_service.c
+++ b/init/property_service.c
@@ -123,7 +123,7 @@ static int init_workspace(workspace *w, size_t size)
/* dev is a tmpfs that we can use to carve a shared workspace
* out of, so let's do that...
*/
- fd = open("/dev/__properties__", O_RDWR | O_CREAT | O_NOFOLLOW, 0600);
+ fd = open(PROP_FILENAME, O_RDWR | O_CREAT | O_NOFOLLOW, 0644);
if (fd < 0)
return -1;
@@ -136,12 +136,10 @@ static int init_workspace(workspace *w, size_t size)
close(fd);
- fd = open("/dev/__properties__", O_RDONLY | O_NOFOLLOW);
+ fd = open(PROP_FILENAME, O_RDONLY | O_NOFOLLOW);
if (fd < 0)
return -1;
- unlink("/dev/__properties__");
-
w->data = data;
w->size = size;
w->fd = fd;
diff --git a/libcutils/Android.mk b/libcutils/Android.mk
index 17b320f5f..7c661bb8c 100644
--- a/libcutils/Android.mk
+++ b/libcutils/Android.mk
@@ -121,6 +121,7 @@ LOCAL_SRC_FILES := $(commonSources) \
mq.c \
partition_utils.c \
qtaguid.c \
+ trace.c \
uevent.c
ifeq ($(TARGET_ARCH),arm)
diff --git a/libcutils/fs.c b/libcutils/fs.c
index 1226d447e..116526dca 100644
--- a/libcutils/fs.c
+++ b/libcutils/fs.c
@@ -26,6 +26,7 @@
#include <errno.h>
#include <string.h>
#include <limits.h>
+#include <stdlib.h>
#define ALL_PERMS (S_ISUID | S_ISGID | S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO)
#define BUF_SIZE 64
diff --git a/libcutils/trace.c b/libcutils/trace.c
new file mode 100644
index 000000000..047f88941
--- /dev/null
+++ b/libcutils/trace.c
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <pthread.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <cutils/atomic.h>
+#include <cutils/compiler.h>
+#include <cutils/properties.h>
+#include <cutils/trace.h>
+
+#define LOG_TAG "cutils-trace"
+#include <cutils/log.h>
+
+int32_t atrace_is_ready = 0;
+int atrace_marker_fd = -1;
+uint64_t atrace_enabled_tags = ATRACE_TAG_NOT_READY;
+static bool atrace_is_debuggable = false;
+static pthread_once_t atrace_once_control = PTHREAD_ONCE_INIT;
+static pthread_mutex_t atrace_tags_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+// Set whether this process is debuggable, which determines whether
+// application-level tracing is allowed when the ro.debuggable system property
+// is not set to '1'.
+void atrace_set_debuggable(bool debuggable)
+{
+ atrace_is_debuggable = debuggable;
+ atrace_update_tags();
+}
+
+// Check whether the given command line matches one of the comma-separated
+// values listed in the app_cmdlines property.
+static bool atrace_is_cmdline_match(const char* cmdline) {
+ char value[PROPERTY_VALUE_MAX];
+ char* start = value;
+
+ property_get("debug.atrace.app_cmdlines", value, "");
+
+ while (start != NULL) {
+ char* end = strchr(start, ',');
+
+ if (end != NULL) {
+ *end = '\0';
+ end++;
+ }
+
+ if (strcmp(cmdline, start) == 0) {
+ return true;
+ }
+
+ start = end;
+ }
+
+ return false;
+}
+
+// Determine whether application-level tracing is enabled for this process.
+static bool atrace_is_app_tracing_enabled()
+{
+ bool sys_debuggable = false;
+ bool proc_debuggable = false;
+ char value[PROPERTY_VALUE_MAX];
+ bool result = false;
+
+ // Check whether the system is debuggable.
+ property_get("ro.debuggable", value, "0");
+ if (value[0] == '1') {
+ sys_debuggable = true;
+ }
+
+ if (sys_debuggable || atrace_is_debuggable) {
+ // Check whether tracing is enabled for this process.
+ FILE * file = fopen("/proc/self/cmdline", "r");
+ if (file) {
+ char cmdline[4096];
+ if (fgets(cmdline, sizeof(cmdline), file)) {
+ result = atrace_is_cmdline_match(cmdline);
+ } else {
+ ALOGE("Error reading cmdline: %s (%d)", strerror(errno), errno);
+ }
+ fclose(file);
+ } else {
+ ALOGE("Error opening /proc/self/cmdline: %s (%d)", strerror(errno),
+ errno);
+ }
+ }
+
+ return result;
+}
+
+// Read the sysprop and return the value tags should be set to
+static uint64_t atrace_get_property()
+{
+ char value[PROPERTY_VALUE_MAX];
+ char *endptr;
+ uint64_t tags;
+
+ property_get("debug.atrace.tags.enableflags", value, "0");
+ errno = 0;
+ tags = strtoull(value, &endptr, 0);
+ if (value[0] == '\0' || *endptr != '\0') {
+ ALOGE("Error parsing trace property: Not a number: %s", value);
+ return 0;
+ } else if (errno == ERANGE || tags == ULLONG_MAX) {
+ ALOGE("Error parsing trace property: Number too large: %s", value);
+ return 0;
+ }
+
+ // Only set the "app" tag if this process was selected for app-level debug
+ // tracing.
+ if (atrace_is_app_tracing_enabled()) {
+ tags |= ATRACE_TAG_APP;
+ } else {
+ tags &= ~ATRACE_TAG_APP;
+ }
+
+ return (tags | ATRACE_TAG_ALWAYS) & ATRACE_TAG_VALID_MASK;
+}
+
+// Update tags if tracing is ready. Useful as a sysprop change callback.
+void atrace_update_tags()
+{
+ uint64_t tags;
+ if (CC_UNLIKELY(android_atomic_acquire_load(&atrace_is_ready))) {
+ tags = atrace_get_property();
+ pthread_mutex_lock(&atrace_tags_mutex);
+ atrace_enabled_tags = tags;
+ pthread_mutex_unlock(&atrace_tags_mutex);
+ }
+}
+
+static void atrace_init_once()
+{
+ atrace_marker_fd = open("/sys/kernel/debug/tracing/trace_marker", O_WRONLY);
+ if (atrace_marker_fd == -1) {
+ ALOGE("Error opening trace file: %s (%d)", strerror(errno), errno);
+ atrace_enabled_tags = 0;
+ goto done;
+ }
+
+ atrace_enabled_tags = atrace_get_property();
+
+done:
+ android_atomic_release_store(1, &atrace_is_ready);
+}
+
+void atrace_setup()
+{
+ pthread_once(&atrace_once_control, atrace_init_once);
+}
diff --git a/libcutils/zygote.c b/libcutils/zygote.c
index 75ce3ba99..37236e8a6 100644
--- a/libcutils/zygote.c
+++ b/libcutils/zygote.c
@@ -159,44 +159,6 @@ static int send_request(int fd, int sendStdio, int argc, const char **argv)
#endif /* HAVE_ANDROID_OS */
}
-int zygote_run_wait(int argc, const char **argv, void (*post_run_func)(int))
-{
- int fd;
- int pid;
- int err;
- const char *newargv[argc + 1];
-
- fd = socket_local_client(ZYGOTE_SOCKET,
- ANDROID_SOCKET_NAMESPACE_RESERVED, AF_LOCAL);
-
- if (fd < 0) {
- return -1;
- }
-
- // The command socket is passed to the peer as close-on-exec
- // and will close when the peer dies
- newargv[0] = "--peer-wait";
- memcpy(newargv + 1, argv, argc * sizeof(*argv));
-
- pid = send_request(fd, 1, argc + 1, newargv);
-
- if (pid > 0 && post_run_func != NULL) {
- post_run_func(pid);
- }
-
- // Wait for socket to close
- do {
- int dummy;
- err = read(fd, &dummy, sizeof(dummy));
- } while ((err < 0 && errno == EINTR) || err != 0);
-
- do {
- err = close(fd);
- } while (err < 0 && errno == EINTR);
-
- return 0;
-}
-
/**
* Spawns a new dalvik instance via the Zygote process. The non-zygote
* arguments are passed to com.android.internal.os.RuntimeInit(). The
diff --git a/libnetutils/dhcp_utils.c b/libnetutils/dhcp_utils.c
index b4caaf977..bd48eff34 100644
--- a/libnetutils/dhcp_utils.c
+++ b/libnetutils/dhcp_utils.c
@@ -88,16 +88,17 @@ static int fill_ip_info(const char *interface,
char *ipaddr,
char *gateway,
uint32_t *prefixLength,
- char *dns1,
- char *dns2,
+ char *dns[],
char *server,
uint32_t *lease,
- char *vendorInfo)
+ char *vendorInfo,
+ char *domain)
{
char 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];
+ int x;
get_p2p_interface_replacement(interface, p2p_interface);
@@ -111,7 +112,7 @@ static int fill_ip_info(const char *interface,
property_get(prop_name, server, NULL);
//TODO: Handle IPv6 when we change system property usage
- if (strcmp(gateway, "0.0.0.0") == 0) {
+ if (gateway[0] == '\0' || strncmp(gateway, "0.0.0.0", 7) == 0) {
//DHCP server is our best bet as gateway
strncpy(gateway, server, PROPERTY_VALUE_MAX);
}
@@ -138,11 +139,11 @@ static int fill_ip_info(const char *interface,
}
*prefixLength = p;
}
- snprintf(prop_name, sizeof(prop_name), "%s.%s.dns1", DHCP_PROP_NAME_PREFIX, p2p_interface);
- property_get(prop_name, dns1, NULL);
- snprintf(prop_name, sizeof(prop_name), "%s.%s.dns2", DHCP_PROP_NAME_PREFIX, p2p_interface);
- property_get(prop_name, dns2, NULL);
+ for (x=0; dns[x] != NULL; x++) {
+ snprintf(prop_name, sizeof(prop_name), "%s.%s.dns%d", DHCP_PROP_NAME_PREFIX, p2p_interface, x+1);
+ property_get(prop_name, dns[x], NULL);
+ }
snprintf(prop_name, sizeof(prop_name), "%s.%s.leasetime", DHCP_PROP_NAME_PREFIX, p2p_interface);
if (property_get(prop_name, prop_value, NULL)) {
@@ -153,6 +154,10 @@ static int fill_ip_info(const char *interface,
p2p_interface);
property_get(prop_name, vendorInfo, NULL);
+ snprintf(prop_name, sizeof(prop_name), "%s.%s.domain", DHCP_PROP_NAME_PREFIX,
+ p2p_interface);
+ property_get(prop_name, domain, NULL);
+
return 0;
}
@@ -177,11 +182,11 @@ int dhcp_do_request(const char *interface,
char *ipaddr,
char *gateway,
uint32_t *prefixLength,
- char *dns1,
- char *dns2,
+ char *dns[],
char *server,
uint32_t *lease,
- char *vendorInfo)
+ char *vendorInfo,
+ char *domain)
{
char result_prop_name[PROPERTY_KEY_MAX];
char daemon_prop_name[PROPERTY_KEY_MAX];
@@ -232,17 +237,10 @@ int dhcp_do_request(const char *interface,
}
if (strcmp(prop_value, "ok") == 0) {
char dns_prop_name[PROPERTY_KEY_MAX];
- if (fill_ip_info(interface, ipaddr, gateway, prefixLength,
- dns1, dns2, server, lease, vendorInfo) == -1) {
+ if (fill_ip_info(interface, ipaddr, gateway, prefixLength, dns,
+ server, lease, vendorInfo, domain) == -1) {
return -1;
}
-
- /* copy dns data to system properties - TODO - remove this after we have async
- * notification of renewal's */
- snprintf(dns_prop_name, sizeof(dns_prop_name), "net.%s.dns1", interface);
- property_set(dns_prop_name, *dns1 ? ipaddr_to_string(*dns1) : "");
- snprintf(dns_prop_name, sizeof(dns_prop_name), "net.%s.dns2", interface);
- property_set(dns_prop_name, *dns2 ? ipaddr_to_string(*dns2) : "");
return 0;
} else {
snprintf(errmsg, sizeof(errmsg), "DHCP result was %s", prop_value);
@@ -327,11 +325,11 @@ int dhcp_do_request_renew(const char *interface,
char *ipaddr,
char *gateway,
uint32_t *prefixLength,
- char *dns1,
- char *dns2,
+ char *dns[],
char *server,
uint32_t *lease,
- char *vendorInfo)
+ char *vendorInfo,
+ char *domain)
{
char result_prop_name[PROPERTY_KEY_MAX];
char prop_value[PROPERTY_VALUE_MAX] = {'\0'};
@@ -367,8 +365,8 @@ int dhcp_do_request_renew(const char *interface,
return -1;
}
if (strcmp(prop_value, "ok") == 0) {
- fill_ip_info(interface, ipaddr, gateway, prefixLength,
- dns1, dns2, server, lease, vendorInfo);
+ fill_ip_info(interface, ipaddr, gateway, prefixLength, dns,
+ server, lease, vendorInfo, domain);
return 0;
} else {
snprintf(errmsg, sizeof(errmsg), "DHCP Renew result was %s", prop_value);
diff --git a/libpixelflinger/Android.mk b/libpixelflinger/Android.mk
index 488003f2a..85d2c9cf0 100644
--- a/libpixelflinger/Android.mk
+++ b/libpixelflinger/Android.mk
@@ -16,8 +16,8 @@ PIXELFLINGER_SRC_FILES:= \
codeflinger/blending.cpp \
codeflinger/texturing.cpp \
codeflinger/disassem.c \
- tinyutils/SharedBuffer.cpp \
- tinyutils/VectorImpl.cpp \
+ codeflinger/tinyutils/SharedBuffer.cpp \
+ codeflinger/tinyutils/VectorImpl.cpp \
fixed.cpp.arm \
picker.cpp.arm \
pixelflinger.cpp.arm \
@@ -52,13 +52,6 @@ endif
LOCAL_SHARED_LIBRARIES := libcutils
-ifneq ($(TARGET_ARCH),arm)
-# Required to define logging functions on the simulator.
-# TODO: move the simulator logging functions into libcutils with
-# the rest of the basic log stuff.
-LOCAL_SHARED_LIBRARIES += libutils
-endif
-
#
# Shared library
#
diff --git a/libpixelflinger/codeflinger/ARMAssembler.cpp b/libpixelflinger/codeflinger/ARMAssembler.cpp
index c4f42f5bd..607ed3c1f 100644
--- a/libpixelflinger/codeflinger/ARMAssembler.cpp
+++ b/libpixelflinger/codeflinger/ARMAssembler.cpp
@@ -28,9 +28,9 @@
#include <private/pixelflinger/ggl_context.h>
-#include "codeflinger/ARMAssembler.h"
-#include "codeflinger/CodeCache.h"
-#include "codeflinger/disassem.h"
+#include "ARMAssembler.h"
+#include "CodeCache.h"
+#include "disassem.h"
// ----------------------------------------------------------------------------
diff --git a/libpixelflinger/codeflinger/ARMAssembler.h b/libpixelflinger/codeflinger/ARMAssembler.h
index 06c66dd8b..c03dd9a39 100644
--- a/libpixelflinger/codeflinger/ARMAssembler.h
+++ b/libpixelflinger/codeflinger/ARMAssembler.h
@@ -25,9 +25,8 @@
#include "tinyutils/KeyedVector.h"
#include "tinyutils/smartpointer.h"
-#include "tinyutils/smartpointer.h"
-#include "codeflinger/ARMAssemblerInterface.h"
-#include "codeflinger/CodeCache.h"
+#include "ARMAssemblerInterface.h"
+#include "CodeCache.h"
namespace android {
diff --git a/libpixelflinger/codeflinger/ARMAssemblerInterface.cpp b/libpixelflinger/codeflinger/ARMAssemblerInterface.cpp
index 82180eef0..073633cd1 100644
--- a/libpixelflinger/codeflinger/ARMAssemblerInterface.cpp
+++ b/libpixelflinger/codeflinger/ARMAssemblerInterface.cpp
@@ -22,7 +22,7 @@
#include <sys/types.h>
#include <cutils/log.h>
-#include "codeflinger/ARMAssemblerInterface.h"
+#include "ARMAssemblerInterface.h"
namespace android {
diff --git a/libpixelflinger/codeflinger/ARMAssemblerProxy.cpp b/libpixelflinger/codeflinger/ARMAssemblerProxy.cpp
index 7feed622b..1c7bc76e4 100644
--- a/libpixelflinger/codeflinger/ARMAssemblerProxy.cpp
+++ b/libpixelflinger/codeflinger/ARMAssemblerProxy.cpp
@@ -19,7 +19,7 @@
#include <stdint.h>
#include <sys/types.h>
-#include "codeflinger/ARMAssemblerProxy.h"
+#include "ARMAssemblerProxy.h"
namespace android {
diff --git a/libpixelflinger/codeflinger/ARMAssemblerProxy.h b/libpixelflinger/codeflinger/ARMAssemblerProxy.h
index 5e3f763bc..70cb4645d 100644
--- a/libpixelflinger/codeflinger/ARMAssemblerProxy.h
+++ b/libpixelflinger/codeflinger/ARMAssemblerProxy.h
@@ -22,7 +22,7 @@
#include <stdint.h>
#include <sys/types.h>
-#include "codeflinger/ARMAssemblerInterface.h"
+#include "ARMAssemblerInterface.h"
namespace android {
diff --git a/libpixelflinger/codeflinger/CodeCache.cpp b/libpixelflinger/codeflinger/CodeCache.cpp
index f9ae00ac7..58fde7eeb 100644
--- a/libpixelflinger/codeflinger/CodeCache.cpp
+++ b/libpixelflinger/codeflinger/CodeCache.cpp
@@ -28,7 +28,7 @@
#include <cutils/log.h>
-#include "codeflinger/CodeCache.h"
+#include "CodeCache.h"
namespace android {
diff --git a/libpixelflinger/codeflinger/CodeCache.h b/libpixelflinger/codeflinger/CodeCache.h
index 54fd69b04..fa67dd072 100644
--- a/libpixelflinger/codeflinger/CodeCache.h
+++ b/libpixelflinger/codeflinger/CodeCache.h
@@ -28,6 +28,8 @@
namespace android {
+using namespace tinyutils;
+
// ----------------------------------------------------------------------------
class AssemblyKeyBase {
diff --git a/libpixelflinger/codeflinger/GGLAssembler.cpp b/libpixelflinger/codeflinger/GGLAssembler.cpp
index 1ddf93d57..0cb042eb9 100644
--- a/libpixelflinger/codeflinger/GGLAssembler.cpp
+++ b/libpixelflinger/codeflinger/GGLAssembler.cpp
@@ -24,7 +24,7 @@
#include <sys/types.h>
#include <cutils/log.h>
-#include "codeflinger/GGLAssembler.h"
+#include "GGLAssembler.h"
namespace android {
diff --git a/libpixelflinger/codeflinger/GGLAssembler.h b/libpixelflinger/codeflinger/GGLAssembler.h
index dd5f48ee9..d99368404 100644
--- a/libpixelflinger/codeflinger/GGLAssembler.h
+++ b/libpixelflinger/codeflinger/GGLAssembler.h
@@ -24,7 +24,7 @@
#include <private/pixelflinger/ggl_context.h>
-#include "codeflinger/ARMAssemblerProxy.h"
+#include "ARMAssemblerProxy.h"
namespace android {
diff --git a/libpixelflinger/codeflinger/MIPSAssembler.cpp b/libpixelflinger/codeflinger/MIPSAssembler.cpp
index 7888a0e4e..a88d2fe00 100644
--- a/libpixelflinger/codeflinger/MIPSAssembler.cpp
+++ b/libpixelflinger/codeflinger/MIPSAssembler.cpp
@@ -61,9 +61,9 @@
#include <private/pixelflinger/ggl_context.h>
-#include "codeflinger/MIPSAssembler.h"
-#include "codeflinger/CodeCache.h"
-#include "codeflinger/mips_disassem.h"
+#include "MIPSAssembler.h"
+#include "CodeCache.h"
+#include "mips_disassem.h"
// Choose MIPS arch variant following gcc flags
#if defined(__mips__) && __mips==32 && __mips_isa_rev>=2
diff --git a/libpixelflinger/codeflinger/MIPSAssembler.h b/libpixelflinger/codeflinger/MIPSAssembler.h
index d8e8165e9..430ab064c 100644
--- a/libpixelflinger/codeflinger/MIPSAssembler.h
+++ b/libpixelflinger/codeflinger/MIPSAssembler.h
@@ -21,12 +21,12 @@
#include <stdint.h>
#include <sys/types.h>
-#include <utils/Vector.h>
-#include <utils/KeyedVector.h>
-
+#include "tinyutils/KeyedVector.h"
+#include "tinyutils/Vector.h"
#include "tinyutils/smartpointer.h"
-#include "codeflinger/ARMAssemblerInterface.h"
-#include "codeflinger/CodeCache.h"
+
+#include "ARMAssemblerInterface.h"
+#include "CodeCache.h"
namespace android {
diff --git a/libpixelflinger/codeflinger/blending.cpp b/libpixelflinger/codeflinger/blending.cpp
index c90eaa0f5..b20219ced 100644
--- a/libpixelflinger/codeflinger/blending.cpp
+++ b/libpixelflinger/codeflinger/blending.cpp
@@ -23,7 +23,7 @@
#include <cutils/log.h>
-#include "codeflinger/GGLAssembler.h"
+#include "GGLAssembler.h"
namespace android {
diff --git a/libpixelflinger/codeflinger/load_store.cpp b/libpixelflinger/codeflinger/load_store.cpp
index 146fa52ea..0a46eaa3c 100644
--- a/libpixelflinger/codeflinger/load_store.cpp
+++ b/libpixelflinger/codeflinger/load_store.cpp
@@ -18,7 +18,7 @@
#include <assert.h>
#include <stdio.h>
#include <cutils/log.h>
-#include "codeflinger/GGLAssembler.h"
+#include "GGLAssembler.h"
#ifdef __ARM_ARCH__
#include <machine/cpu-features.h>
diff --git a/libpixelflinger/codeflinger/texturing.cpp b/libpixelflinger/codeflinger/texturing.cpp
index 4d5a50f1d..9e3d2172d 100644
--- a/libpixelflinger/codeflinger/texturing.cpp
+++ b/libpixelflinger/codeflinger/texturing.cpp
@@ -23,7 +23,7 @@
#include <cutils/log.h>
-#include "codeflinger/GGLAssembler.h"
+#include "GGLAssembler.h"
#ifdef __ARM_ARCH__
#include <machine/cpu-features.h>
diff --git a/libpixelflinger/tinyutils/Errors.h b/libpixelflinger/codeflinger/tinyutils/Errors.h
index b9fd5f4fc..47ae9d79e 100644
--- a/libpixelflinger/tinyutils/Errors.h
+++ b/libpixelflinger/codeflinger/tinyutils/Errors.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007 The Android Open Source Project
+ * Copyright 2007 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.
@@ -14,13 +14,14 @@
* limitations under the License.
*/
-#ifndef ANDROID_ERRORS_H
-#define ANDROID_ERRORS_H
+#ifndef ANDROID_PIXELFLINGER_ERRORS_H
+#define ANDROID_PIXELFLINGER_ERRORS_H
#include <sys/types.h>
#include <errno.h>
namespace android {
+namespace tinyutils {
// use this type to return error codes
typedef int32_t status_t;
@@ -31,32 +32,17 @@ typedef int32_t status_t;
*/
enum {
- OK = 0, // Everything's swell.
NO_ERROR = 0, // No errors.
-
- UNKNOWN_ERROR = 0x80000000,
-
NO_MEMORY = -ENOMEM,
- INVALID_OPERATION = -ENOSYS,
BAD_VALUE = -EINVAL,
- BAD_TYPE = 0x80000001,
- NAME_NOT_FOUND = -ENOENT,
- PERMISSION_DENIED = -EPERM,
- NO_INIT = -ENODEV,
- ALREADY_EXISTS = -EEXIST,
- DEAD_OBJECT = -EPIPE,
- FAILED_TRANSACTION = 0x80000002,
- JPARKS_BROKE_IT = -EPIPE,
BAD_INDEX = -EOVERFLOW,
- NOT_ENOUGH_DATA = -ENODATA,
- WOULD_BLOCK = -EWOULDBLOCK,
- TIMED_OUT = -ETIME,
- UNKNOWN_TRANSACTION = -EBADMSG,
+ NAME_NOT_FOUND = -ENOENT,
};
-}; // namespace android
+} // namespace tinyutils
+} // namespace android
// ---------------------------------------------------------------------------
-#endif // ANDROID_ERRORS_H
+#endif // ANDROID_PIXELFLINGER_ERRORS_H
diff --git a/libpixelflinger/tinyutils/KeyedVector.h b/libpixelflinger/codeflinger/tinyutils/KeyedVector.h
index 1be2094e9..9d8668b9c 100644
--- a/libpixelflinger/tinyutils/KeyedVector.h
+++ b/libpixelflinger/codeflinger/tinyutils/KeyedVector.h
@@ -1,25 +1,34 @@
/*
- * keyed_vector.h
- * Android
+ * Copyright 2005 The Android Open Source Project
*
- * Created on 11/18/05.
- * Copyright 2005 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_KEYED_VECTOR_H
-#define ANDROID_KEYED_VECTOR_H
+#ifndef ANDROID_PIXELFLINGER_KEYED_VECTOR_H
+#define ANDROID_PIXELFLINGER_KEYED_VECTOR_H
#include <assert.h>
#include <stdint.h>
#include <sys/types.h>
-#include "tinyutils/SortedVector.h"
-#include "tinyutils/TypeHelpers.h"
+#include "Errors.h"
+#include "SortedVector.h"
+#include "TypeHelpers.h"
// ---------------------------------------------------------------------------
namespace android {
+namespace tinyutils {
template <typename KEY, typename VALUE>
class KeyedVector
@@ -186,8 +195,9 @@ const VALUE& DefaultKeyedVector<KEY,VALUE>::valueFor(const KEY& key) const {
return i >= 0 ? KeyedVector<KEY,VALUE>::valueAt(i) : mDefault;
}
-}; // namespace android
+} // namespace tinyutils
+} // namespace android
// ---------------------------------------------------------------------------
-#endif // ANDROID_KEYED_VECTOR_H
+#endif // ANDROID_PIXELFLINGER_KEYED_VECTOR_H
diff --git a/libpixelflinger/tinyutils/SharedBuffer.cpp b/libpixelflinger/codeflinger/tinyutils/SharedBuffer.cpp
index ef781a75c..ef453fa6c 100644
--- a/libpixelflinger/tinyutils/SharedBuffer.cpp
+++ b/libpixelflinger/codeflinger/tinyutils/SharedBuffer.cpp
@@ -1,9 +1,17 @@
/*
- * SharedBuffer.cpp
- * Android
+ * Copyright 2005 The Android Open Source Project
*
- * Copyright 2005 The Android Open Source Project
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
*
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
*/
#include <stdlib.h>
@@ -11,11 +19,12 @@
#include <cutils/atomic.h>
-#include "tinyutils/SharedBuffer.h"
+#include "SharedBuffer.h"
// ---------------------------------------------------------------------------
namespace android {
+namespace tinyutils {
SharedBuffer* SharedBuffer::alloc(size_t size)
{
@@ -102,5 +111,5 @@ int32_t SharedBuffer::release(uint32_t flags) const
return prev;
}
-
-}; // namespace android
+} // namespace tinyutils
+} // namespace android
diff --git a/libpixelflinger/tinyutils/SharedBuffer.h b/libpixelflinger/codeflinger/tinyutils/SharedBuffer.h
index 9f631213a..d69b4179b 100644
--- a/libpixelflinger/tinyutils/SharedBuffer.h
+++ b/libpixelflinger/codeflinger/tinyutils/SharedBuffer.h
@@ -1,13 +1,21 @@
/*
- * SharedBuffer.h
- * Android
+ * Copyright 2005 The Android Open Source Project
*
- * Copyright 2005 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_SHARED_BUFFER_H
-#define ANDROID_SHARED_BUFFER_H
+#ifndef ANDROID_PIXELFLINGER_SHARED_BUFFER_H
+#define ANDROID_PIXELFLINGER_SHARED_BUFFER_H
#include <stdint.h>
#include <sys/types.h>
@@ -15,6 +23,7 @@
// ---------------------------------------------------------------------------
namespace android {
+namespace tinyutils {
class SharedBuffer
{
@@ -131,8 +140,9 @@ bool SharedBuffer::onlyOwner() const {
return (mRefs == 1);
}
-}; // namespace android
+} // namespace tinyutils
+} // namespace android
// ---------------------------------------------------------------------------
-#endif // ANDROID_VECTOR_H
+#endif // ANDROID_PIXELFLINGER_SHARED_BUFFER_H
diff --git a/libpixelflinger/tinyutils/SortedVector.h b/libpixelflinger/codeflinger/tinyutils/SortedVector.h
index 7a6b4435f..a2b700542 100644
--- a/libpixelflinger/tinyutils/SortedVector.h
+++ b/libpixelflinger/codeflinger/tinyutils/SortedVector.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005 The Android Open Source Project
+ * Copyright 2005 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.
@@ -14,20 +14,21 @@
* limitations under the License.
*/
-#ifndef ANDROID_SORTED_VECTOR_H
-#define ANDROID_SORTED_VECTOR_H
+#ifndef ANDROID_PIXELFLINGER_SORTED_VECTOR_H
+#define ANDROID_PIXELFLINGER_SORTED_VECTOR_H
#include <assert.h>
#include <stdint.h>
#include <sys/types.h>
-#include "tinyutils/Vector.h"
-#include "tinyutils/VectorImpl.h"
-#include "tinyutils/TypeHelpers.h"
+#include "Vector.h"
+#include "VectorImpl.h"
+#include "TypeHelpers.h"
// ---------------------------------------------------------------------------
namespace android {
+namespace tinyutils {
template <class TYPE>
class SortedVector : private SortedVectorImpl
@@ -274,9 +275,10 @@ int SortedVector<TYPE>::do_compare(const void* lhs, const void* rhs) const {
return compare_type( *reinterpret_cast<const TYPE*>(lhs), *reinterpret_cast<const TYPE*>(rhs) );
}
-}; // namespace android
+} // namespace tinyutils
+} // namespace android
// ---------------------------------------------------------------------------
-#endif // ANDROID_SORTED_VECTOR_H
+#endif // ANDROID_PIXELFLINGER_SORTED_VECTOR_H
diff --git a/libpixelflinger/tinyutils/TypeHelpers.h b/libpixelflinger/codeflinger/tinyutils/TypeHelpers.h
index 9500c9044..7abff072f 100644
--- a/libpixelflinger/tinyutils/TypeHelpers.h
+++ b/libpixelflinger/codeflinger/tinyutils/TypeHelpers.h
@@ -1,12 +1,21 @@
/*
- * TypeHelpers.h
- *
- * Copyright 2005 The Android Open Source Project
+ * Copyright 2005 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_TYPE_HELPERS_H
-#define ANDROID_TYPE_HELPERS_H
+#ifndef ANDROID_PIXELFLINGER_TYPE_HELPERS_H
+#define ANDROID_PIXELFLINGER_TYPE_HELPERS_H
#include <new>
#include <stdint.h>
@@ -16,6 +25,7 @@
// ---------------------------------------------------------------------------
namespace android {
+namespace tinyutils {
/*
* Types traits
@@ -238,8 +248,9 @@ struct trait_trivial_assign< key_value_pair_t<K, V> >
// ---------------------------------------------------------------------------
-}; // namespace android
+} // namespace tinyutils
+} // namespace android
// ---------------------------------------------------------------------------
-#endif // ANDROID_TYPE_HELPERS_H
+#endif // ANDROID_PIXELFLINGER_TYPE_HELPERS_H
diff --git a/libpixelflinger/tinyutils/Vector.h b/libpixelflinger/codeflinger/tinyutils/Vector.h
index 14cf99a43..c07a17aa5 100644
--- a/libpixelflinger/tinyutils/Vector.h
+++ b/libpixelflinger/codeflinger/tinyutils/Vector.h
@@ -1,13 +1,21 @@
/*
- * vector.h
- * Android
+ * Copyright 2005 The Android Open Source Project
*
- * Copyright 2005 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_VECTOR_H
-#define ANDROID_VECTOR_H
+#ifndef ANDROID_PIXELFLINGER_VECTOR_H
+#define ANDROID_PIXELFLINGER_VECTOR_H
#include <new>
#include <stdint.h>
@@ -15,13 +23,14 @@
#include <cutils/log.h>
-#include "tinyutils/Errors.h"
-#include "tinyutils/VectorImpl.h"
-#include "tinyutils/TypeHelpers.h"
+#include "Errors.h"
+#include "VectorImpl.h"
+#include "TypeHelpers.h"
// ---------------------------------------------------------------------------
namespace android {
+namespace tinyutils {
/*!
* The main templated vector class ensuring type safety
@@ -335,9 +344,10 @@ void Vector<TYPE>::do_move_backward(void* dest, const void* from, size_t num) co
move_backward_type( reinterpret_cast<TYPE*>(dest), reinterpret_cast<const TYPE*>(from), num );
}
-}; // namespace android
+} // namespace tinyutils
+} // namespace android
// ---------------------------------------------------------------------------
-#endif // ANDROID_VECTOR_H
+#endif // ANDROID_PIXELFLINGER_VECTOR_H
diff --git a/libpixelflinger/tinyutils/VectorImpl.cpp b/libpixelflinger/codeflinger/tinyutils/VectorImpl.cpp
index 05c4945b6..689129a65 100644
--- a/libpixelflinger/tinyutils/VectorImpl.cpp
+++ b/libpixelflinger/codeflinger/tinyutils/VectorImpl.cpp
@@ -1,9 +1,17 @@
/*
- * vector_impl.cpp
- * Android
+ * Copyright 2005 The Android Open Source Project
*
- * Copyright 2005 The Android Open Source Project
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
*
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
*/
#define LOG_TAG "Vector"
@@ -15,21 +23,15 @@
#include <cutils/log.h>
-#include "tinyutils/SharedBuffer.h"
-#include "tinyutils/VectorImpl.h"
+#include "Errors.h"
+#include "SharedBuffer.h"
+#include "VectorImpl.h"
/*****************************************************************************/
namespace android {
-
-enum {
- NO_ERROR = 0, // No errors.
- NO_MEMORY = -ENOMEM,
- BAD_VALUE = -EINVAL,
- BAD_INDEX = -EOVERFLOW,
- NAME_NOT_FOUND = -ENOENT,
-};
+namespace tinyutils {
// ----------------------------------------------------------------------------
@@ -548,5 +550,6 @@ void SortedVectorImpl::reservedSortedVectorImpl8() { };
/*****************************************************************************/
-}; // namespace android
+} // namespace tinyutils
+} // namespace android
diff --git a/libpixelflinger/tinyutils/VectorImpl.h b/libpixelflinger/codeflinger/tinyutils/VectorImpl.h
index e868ecaf9..56089b325 100644
--- a/libpixelflinger/tinyutils/VectorImpl.h
+++ b/libpixelflinger/codeflinger/tinyutils/VectorImpl.h
@@ -1,13 +1,21 @@
/*
- * vector_impl.h
- * Android
+ * Copyright 2005 The Android Open Source Project
*
- * Copyright 2005 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_VECTOR_IMPL_H
-#define ANDROID_VECTOR_IMPL_H
+#ifndef ANDROID_PIXELFLINGER_VECTOR_IMPL_H
+#define ANDROID_PIXELFLINGER_VECTOR_IMPL_H
#include <assert.h>
#include <stdint.h>
@@ -18,6 +26,7 @@
// ---------------------------------------------------------------------------
namespace android {
+namespace tinyutils {
/*!
* Implementation of the guts of the vector<> class
@@ -177,9 +186,10 @@ private:
ssize_t replaceAt(const void* item, size_t index);
};
-}; // namespace android
+} // namespace tinyutils
+} // namespace android
// ---------------------------------------------------------------------------
-#endif // ANDROID_VECTOR_IMPL_H
+#endif // ANDROID_PIXELFLINGER_VECTOR_IMPL_H
diff --git a/libpixelflinger/tinyutils/smartpointer.h b/libpixelflinger/codeflinger/tinyutils/smartpointer.h
index 88032d7fb..9d0a16e5c 100644
--- a/libpixelflinger/tinyutils/smartpointer.h
+++ b/libpixelflinger/codeflinger/tinyutils/smartpointer.h
@@ -1,13 +1,21 @@
/*
- * smartpointer.h
- * Android
+ * Copyright 2005 The Android Open Source Project
*
- * Copyright 2005 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_SMART_POINTER_H
-#define ANDROID_SMART_POINTER_H
+#ifndef ANDROID_PIXELFLINGER_SMART_POINTER_H
+#define ANDROID_PIXELFLINGER_SMART_POINTER_H
#include <stdint.h>
#include <sys/types.h>
@@ -15,6 +23,7 @@
// ---------------------------------------------------------------------------
namespace android {
+namespace tinyutils {
// ---------------------------------------------------------------------------
@@ -163,8 +172,9 @@ void sp<T>::clear()
// ---------------------------------------------------------------------------
-}; // namespace android
+} // namespace tinyutils
+} // namespace android
// ---------------------------------------------------------------------------
-#endif // ANDROID_SMART_POINTER_H
+#endif // ANDROID_PIXELFLINGER_SMART_POINTER_H
diff --git a/libusbhost/usbhost.c b/libusbhost/usbhost.c
index 167fa6061..b96734258 100644
--- a/libusbhost/usbhost.c
+++ b/libusbhost/usbhost.c
@@ -223,56 +223,61 @@ int usb_host_read_event(struct usb_host_context *context)
char event_buf[512];
char path[100];
int i, ret, done = 0;
- int j, event_size;
+ int offset = 0;
int wd;
ret = read(context->fd, event_buf, sizeof(event_buf));
if (ret >= (int)sizeof(struct inotify_event)) {
- event = (struct inotify_event *)event_buf;
- wd = event->wd;
- if (wd == context->wdd) {
- if ((event->mask & IN_CREATE) && !strcmp(event->name, "bus")) {
- watch_existing_subdirs(context, context->wds, MAX_USBFS_WD_COUNT);
- done = find_existing_devices(context->cb_added, context->data);
- } else if ((event->mask & IN_DELETE) && !strcmp(event->name, "bus")) {
- for (i = 0; i < MAX_USBFS_WD_COUNT; i++) {
- if (context->wds[i] >= 0) {
+ while (offset < ret) {
+ event = (struct inotify_event*)&event_buf[offset];
+ done = 0;
+ wd = event->wd;
+ if (wd == context->wdd) {
+ if ((event->mask & IN_CREATE) && !strcmp(event->name, "bus")) {
+ watch_existing_subdirs(context, context->wds, MAX_USBFS_WD_COUNT);
+ done = find_existing_devices(context->cb_added, context->data);
+ } else if ((event->mask & IN_DELETE) && !strcmp(event->name, "bus")) {
+ for (i = 0; i < MAX_USBFS_WD_COUNT; i++) {
+ if (context->wds[i] >= 0) {
+ inotify_rm_watch(context->fd, context->wds[i]);
+ context->wds[i] = -1;
+ }
+ }
+ }
+ } else if (wd == context->wds[0]) {
+ i = atoi(event->name);
+ snprintf(path, sizeof(path), USB_FS_DIR "/%s", event->name);
+ D("%s subdirectory %s: index: %d\n", (event->mask & IN_CREATE) ?
+ "new" : "gone", path, i);
+ if (i > 0 && i < MAX_USBFS_WD_COUNT) {
+ if (event->mask & IN_CREATE) {
+ ret = inotify_add_watch(context->fd, path,
+ IN_CREATE | IN_DELETE);
+ if (ret >= 0)
+ context->wds[i] = ret;
+ done = find_existing_devices_bus(path, context->cb_added,
+ context->data);
+ } else if (event->mask & IN_DELETE) {
inotify_rm_watch(context->fd, context->wds[i]);
context->wds[i] = -1;
}
}
- }
- } else if (wd == context->wds[0]) {
- i = atoi(event->name);
- snprintf(path, sizeof(path), USB_FS_DIR "/%s", event->name);
- D("%s subdirectory %s: index: %d\n", (event->mask & IN_CREATE) ?
- "new" : "gone", path, i);
- if (i > 0 && i < MAX_USBFS_WD_COUNT) {
- if (event->mask & IN_CREATE) {
- ret = inotify_add_watch(context->fd, path,
- IN_CREATE | IN_DELETE);
- if (ret >= 0)
- context->wds[i] = ret;
- done = find_existing_devices_bus(path, context->cb_added,
- context->data);
- } else if (event->mask & IN_DELETE) {
- inotify_rm_watch(context->fd, context->wds[i]);
- context->wds[i] = -1;
- }
- }
- } else {
- for (i = 1; (i < MAX_USBFS_WD_COUNT) && !done; i++) {
- if (wd == context->wds[i]) {
- snprintf(path, sizeof(path), USB_FS_DIR "/%03d/%s", i, event->name);
- if (event->mask == IN_CREATE) {
- D("new device %s\n", path);
- done = context->cb_added(path, context->data);
- } else if (event->mask == IN_DELETE) {
- D("gone device %s\n", path);
- done = context->cb_removed(path, context->data);
+ } else {
+ for (i = 1; (i < MAX_USBFS_WD_COUNT) && !done; i++) {
+ if (wd == context->wds[i]) {
+ snprintf(path, sizeof(path), USB_FS_DIR "/%03d/%s", i, event->name);
+ if (event->mask == IN_CREATE) {
+ D("new device %s\n", path);
+ done = context->cb_added(path, context->data);
+ } else if (event->mask == IN_DELETE) {
+ D("gone device %s\n", path);
+ done = context->cb_removed(path, context->data);
+ }
}
}
}
+
+ offset += sizeof(struct inotify_event) + event->len;
}
}
diff --git a/logwrapper/Android.mk b/logwrapper/Android.mk
index 5fd635676..b4b6b2986 100644
--- a/logwrapper/Android.mk
+++ b/logwrapper/Android.mk
@@ -1,7 +1,34 @@
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
+
+# ========================================================
+# Static library
+# ========================================================
+include $(CLEAR_VARS)
+LOCAL_MODULE := liblogwrap
+LOCAL_SRC_FILES := logwrap.c
+LOCAL_SHARED_LIBRARIES := libcutils liblog
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
+LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
+include $(BUILD_STATIC_LIBRARY)
+
+# ========================================================
+# Shared library
+# ========================================================
+include $(CLEAR_VARS)
+LOCAL_MODULE := liblogwrap
+LOCAL_SHARED_LIBRARIES := libcutils liblog
+LOCAL_WHOLE_STATIC_LIBRARIES := liblogwrap
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
+LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
+include $(BUILD_SHARED_LIBRARY)
+
+# ========================================================
+# Executable
+# ========================================================
+include $(CLEAR_VARS)
LOCAL_SRC_FILES:= logwrapper.c
LOCAL_MODULE := logwrapper
-LOCAL_STATIC_LIBRARIES := liblog
+LOCAL_STATIC_LIBRARIES := liblog liblogwrap
include $(BUILD_EXECUTABLE)
diff --git a/logwrapper/include/logwrap/logwrap.h b/logwrapper/include/logwrap/logwrap.h
new file mode 100644
index 000000000..2be8736f6
--- /dev/null
+++ b/logwrapper/include/logwrap/logwrap.h
@@ -0,0 +1,60 @@
+/* system/core/include/logwrap/logwrap.h
+ *
+ * Copyright 2013, 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 __LIBS_LOGWRAP_H
+#define __LIBS_LOGWRAP_H
+
+#include <stdbool.h>
+
+__BEGIN_DECLS
+
+/*
+ * Run a command while logging its stdout and stderr
+ *
+ * WARNING: while this function is running it will clear all SIGCHLD handlers
+ * if you rely on SIGCHLD in the caller there is a chance zombies will be
+ * created if you're not calling waitpid after calling this. This function will
+ * log a warning when it clears SIGCHLD for processes other than the child it
+ * created.
+ *
+ * Arguments:
+ * argc: the number of elements in argv
+ * argv: an array of strings containing the command to be executed and its
+ * arguments as separate strings. argv does not need to be
+ * NULL-terminated
+ * status: the equivalent child status as populated by wait(status). This
+ * value is only valid when logwrap successfully completes. If NULL
+ * the return value of the child will be the function's return value.
+ * ignore_int_quit: set to true if you want to completely ignore SIGINT and
+ * SIGQUIT while logwrap is running. This may force the end-user to
+ * send a signal twice to signal the caller (once for the child, and
+ * once for the caller)
+ * logwrap: when true, log messages from the child
+ *
+ * Return value:
+ * 0 when logwrap successfully run the child process and captured its status
+ * -1 when an internal error occurred
+ * -ECHILD if status is NULL and the child didn't exit properly
+ * the return value of the child if it exited properly and status is NULL
+ *
+ */
+int android_fork_execvp(int argc, char* argv[], int *status, bool ignore_int_quit,
+ bool logwrap);
+
+__END_DECLS
+
+#endif /* __LIBS_LOGWRAP_H */
diff --git a/logwrapper/logwrap.c b/logwrapper/logwrap.c
new file mode 100644
index 000000000..bf9197759
--- /dev/null
+++ b/logwrapper/logwrap.c
@@ -0,0 +1,261 @@
+/*
+ * Copyright (C) 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
+ *
+ * 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 <sys/types.h>
+#include <sys/socket.h>
+#include <poll.h>
+#include <sys/wait.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <libgen.h>
+#include <stdbool.h>
+#include <pthread.h>
+
+#include <logwrap/logwrap.h>
+#include "private/android_filesystem_config.h"
+#include "cutils/log.h"
+
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x)))
+
+static pthread_mutex_t fd_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+#define ERROR(fmt, args...) \
+do { \
+ fprintf(stderr, fmt, ## args); \
+ ALOG(LOG_ERROR, "logwrapper", fmt, ## args); \
+} while(0)
+
+#define FATAL_CHILD(fmt, args...) \
+do { \
+ ERROR(fmt, ## args); \
+ _exit(-1); \
+} while(0)
+
+static int parent(const char *tag, int parent_read, pid_t pid, int *chld_sts,
+ bool logwrap) {
+ int status = 0;
+ char buffer[4096];
+ struct pollfd poll_fds[] = {
+ [0] = {
+ .fd = parent_read,
+ .events = POLLIN,
+ },
+ };
+ int rc = 0;
+
+ int a = 0; // start index of unprocessed data
+ int b = 0; // end index of unprocessed data
+ int sz;
+ bool found_child = false;
+
+ char *btag = basename(tag);
+ if (!btag) btag = (char*) tag;
+
+ while (!found_child) {
+ if (TEMP_FAILURE_RETRY(poll(poll_fds, ARRAY_SIZE(poll_fds), -1)) < 0) {
+ ERROR("poll failed\n");
+ rc = -1;
+ goto err_poll;
+ }
+
+ if (poll_fds[0].revents & POLLIN) {
+ sz = read(parent_read, &buffer[b], sizeof(buffer) - 1 - b);
+
+ sz += b;
+ // Log one line at a time
+ for (b = 0; b < sz; b++) {
+ if (buffer[b] == '\r') {
+ buffer[b] = '\0';
+ } else if (buffer[b] == '\n') {
+ buffer[b] = '\0';
+ if (logwrap)
+ ALOG(LOG_INFO, btag, "%s", &buffer[a]);
+ a = b + 1;
+ }
+ }
+
+ if (a == 0 && b == sizeof(buffer) - 1) {
+ // buffer is full, flush
+ buffer[b] = '\0';
+ if (logwrap)
+ ALOG(LOG_INFO, btag, "%s", &buffer[a]);
+ b = 0;
+ } else if (a != b) {
+ // Keep left-overs
+ b -= a;
+ memmove(buffer, &buffer[a], b);
+ a = 0;
+ } else {
+ a = 0;
+ b = 0;
+ }
+ }
+
+ if (poll_fds[0].revents & POLLHUP) {
+ int ret;
+
+ ret = waitpid(pid, &status, WNOHANG);
+ if (ret < 0) {
+ rc = errno;
+ ALOG(LOG_ERROR, "logwrap", "waitpid failed with %s\n", strerror(errno));
+ goto err_waitpid;
+ }
+ if (ret > 0) {
+ found_child = true;
+ }
+ }
+ }
+
+ if (chld_sts != NULL) {
+ *chld_sts = status;
+ } else {
+ if (WIFEXITED(status))
+ rc = WEXITSTATUS(status);
+ else
+ rc = -ECHILD;
+ }
+
+ if (logwrap) {
+ // Flush remaining data
+ if (a != b) {
+ buffer[b] = '\0';
+ ALOG(LOG_INFO, btag, "%s", &buffer[a]);
+ }
+ if (WIFEXITED(status)) {
+ if (WEXITSTATUS(status))
+ ALOG(LOG_INFO, "logwrapper", "%s terminated by exit(%d)", btag,
+ WEXITSTATUS(status));
+ } else {
+ if (WIFSIGNALED(status))
+ ALOG(LOG_INFO, "logwrapper", "%s terminated by signal %d", btag,
+ WTERMSIG(status));
+ else if (WIFSTOPPED(status))
+ ALOG(LOG_INFO, "logwrapper", "%s stopped by signal %d", btag,
+ WSTOPSIG(status));
+ }
+ }
+
+err_waitpid:
+err_poll:
+ return rc;
+}
+
+static void child(int argc, char* argv[], bool logwrap) {
+ // create null terminated argv_child array
+ char* argv_child[argc + 1];
+ memcpy(argv_child, argv, argc * sizeof(char *));
+ argv_child[argc] = NULL;
+
+ if (execvp(argv_child[0], argv_child)) {
+ FATAL_CHILD("executing %s failed: %s\n", argv_child[0],
+ strerror(errno));
+ }
+}
+
+int android_fork_execvp(int argc, char* argv[], int *status, bool ignore_int_quit,
+ bool logwrap) {
+ pid_t pid;
+ int parent_ptty;
+ int child_ptty;
+ char *child_devname = NULL;
+ struct sigaction intact;
+ struct sigaction quitact;
+ sigset_t blockset;
+ sigset_t oldset;
+ int rc = 0;
+
+ rc = pthread_mutex_lock(&fd_mutex);
+ if (rc) {
+ ERROR("failed to lock signal_fd mutex\n");
+ goto err_lock;
+ }
+
+ /* Use ptty instead of socketpair so that STDOUT is not buffered */
+ parent_ptty = open("/dev/ptmx", O_RDWR);
+ if (parent_ptty < 0) {
+ ERROR("Cannot create parent ptty\n");
+ rc = -1;
+ goto err_open;
+ }
+
+ if (grantpt(parent_ptty) || unlockpt(parent_ptty) ||
+ ((child_devname = (char*)ptsname(parent_ptty)) == 0)) {
+ ERROR("Problem with /dev/ptmx\n");
+ rc = -1;
+ goto err_ptty;
+ }
+
+ child_ptty = open(child_devname, O_RDWR);
+ if (child_ptty < 0) {
+ ERROR("Cannot open child_ptty\n");
+ rc = -1;
+ goto err_child_ptty;
+ }
+
+ sigemptyset(&blockset);
+ sigaddset(&blockset, SIGINT);
+ sigaddset(&blockset, SIGQUIT);
+ pthread_sigmask(SIG_BLOCK, &blockset, &oldset);
+
+ pid = fork();
+ if (pid < 0) {
+ close(child_ptty);
+ ERROR("Failed to fork\n");
+ rc = -1;
+ goto err_fork;
+ } else if (pid == 0) {
+ pthread_mutex_unlock(&fd_mutex);
+ pthread_sigmask(SIG_SETMASK, &oldset, NULL);
+ close(parent_ptty);
+
+ // redirect stdout and stderr
+ dup2(child_ptty, 1);
+ dup2(child_ptty, 2);
+ close(child_ptty);
+
+ child(argc, argv, logwrap);
+ } else {
+ close(child_ptty);
+ if (ignore_int_quit) {
+ struct sigaction ignact;
+
+ memset(&ignact, 0, sizeof(ignact));
+ ignact.sa_handler = SIG_IGN;
+ sigaction(SIGINT, &ignact, &intact);
+ sigaction(SIGQUIT, &ignact, &quitact);
+ }
+
+ rc = parent(argv[0], parent_ptty, pid, status, logwrap);
+ }
+
+ if (ignore_int_quit) {
+ sigaction(SIGINT, &intact, NULL);
+ sigaction(SIGQUIT, &quitact, NULL);
+ }
+err_fork:
+ pthread_sigmask(SIG_SETMASK, &oldset, NULL);
+err_child_ptty:
+err_ptty:
+ close(parent_ptty);
+err_open:
+ pthread_mutex_unlock(&fd_mutex);
+err_lock:
+ return rc;
+}
diff --git a/logwrapper/logwrapper.c b/logwrapper/logwrapper.c
index dd777c032..ed71a29e6 100644
--- a/logwrapper/logwrapper.c
+++ b/logwrapper/logwrapper.c
@@ -14,17 +14,12 @@
* limitations under the License.
*/
-#include <string.h>
-#include <sys/types.h>
-#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
-#include <unistd.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <libgen.h>
+#include <sys/wait.h>
+
+#include <logwrap/logwrap.h>
-#include "private/android_filesystem_config.h"
#include "cutils/log.h"
void fatal(const char *msg) {
@@ -45,90 +40,10 @@ void usage() {
" fault address is set to the status of wait()\n");
}
-void parent(const char *tag, int seg_fault_on_exit, int parent_read) {
- int status;
- char buffer[4096];
-
- int a = 0; // start index of unprocessed data
- int b = 0; // end index of unprocessed data
- int sz;
-
- char *btag = basename(tag);
- if (!btag) btag = (char*) tag;
-
- while ((sz = read(parent_read, &buffer[b], sizeof(buffer) - 1 - b)) > 0) {
-
- sz += b;
- // Log one line at a time
- for (b = 0; b < sz; b++) {
- if (buffer[b] == '\r') {
- buffer[b] = '\0';
- } else if (buffer[b] == '\n') {
- buffer[b] = '\0';
- ALOG(LOG_INFO, btag, "%s", &buffer[a]);
- a = b + 1;
- }
- }
-
- if (a == 0 && b == sizeof(buffer) - 1) {
- // buffer is full, flush
- buffer[b] = '\0';
- ALOG(LOG_INFO, btag, "%s", &buffer[a]);
- b = 0;
- } else if (a != b) {
- // Keep left-overs
- b -= a;
- memmove(buffer, &buffer[a], b);
- a = 0;
- } else {
- a = 0;
- b = 0;
- }
-
- }
- // Flush remaining data
- if (a != b) {
- buffer[b] = '\0';
- ALOG(LOG_INFO, btag, "%s", &buffer[a]);
- }
- status = 0xAAAA;
- if (wait(&status) != -1) { // Wait for child
- if (WIFEXITED(status) && WEXITSTATUS(status))
- ALOG(LOG_INFO, "logwrapper", "%s terminated by exit(%d)", tag,
- WEXITSTATUS(status));
- else if (WIFSIGNALED(status))
- ALOG(LOG_INFO, "logwrapper", "%s terminated by signal %d", tag,
- WTERMSIG(status));
- else if (WIFSTOPPED(status))
- ALOG(LOG_INFO, "logwrapper", "%s stopped by signal %d", tag,
- WSTOPSIG(status));
- } else
- ALOG(LOG_INFO, "logwrapper", "%s wait() failed: %s (%d)", tag,
- strerror(errno), errno);
- if (seg_fault_on_exit)
- *(int *)status = 0; // causes SIGSEGV with fault_address = status
-}
-
-void child(int argc, char* argv[]) {
- // create null terminated argv_child array
- char* argv_child[argc + 1];
- memcpy(argv_child, argv, argc * sizeof(char *));
- argv_child[argc] = NULL;
-
- if (execvp(argv_child[0], argv_child)) {
- ALOG(LOG_ERROR, "logwrapper",
- "executing %s failed: %s\n", argv_child[0], strerror(errno));
- exit(-1);
- }
-}
-
int main(int argc, char* argv[]) {
- pid_t pid;
int seg_fault_on_exit = 0;
-
- int parent_ptty;
- int child_ptty;
- char *child_devname = NULL;
+ int status = 0xAAAA;
+ int rc;
if (argc < 2) {
usage();
@@ -144,43 +59,17 @@ int main(int argc, char* argv[]) {
usage();
}
- /* Use ptty instead of socketpair so that STDOUT is not buffered */
- parent_ptty = open("/dev/ptmx", O_RDWR);
- if (parent_ptty < 0) {
- fatal("Cannot create parent ptty\n");
+ rc = android_fork_execvp(argc - 1, &argv[1], &status, true, true);
+ if (!rc) {
+ if (WIFEXITED(status))
+ rc = WEXITSTATUS(status);
+ else
+ rc = -ECHILD;
}
- if (grantpt(parent_ptty) || unlockpt(parent_ptty) ||
- ((child_devname = (char*)ptsname(parent_ptty)) == 0)) {
- fatal("Problem with /dev/ptmx\n");
- }
-
- pid = fork();
- if (pid < 0) {
- fatal("Failed to fork\n");
- } else if (pid == 0) {
- child_ptty = open(child_devname, O_RDWR);
- if (child_ptty < 0) {
- fatal("Problem with child ptty\n");
- }
-
- // redirect stdout and stderr
- close(parent_ptty);
- dup2(child_ptty, 1);
- dup2(child_ptty, 2);
- close(child_ptty);
-
- child(argc - 1, &argv[1]);
-
- } else {
- // switch user and group to "log"
- // this may fail if we are not root,
- // but in that case switching user/group is unnecessary
- setgid(AID_LOG);
- setuid(AID_LOG);
-
- parent(argv[1], seg_fault_on_exit, parent_ptty);
+ if (seg_fault_on_exit) {
+ *(int *)status = 0; // causes SIGSEGV with fault_address = status
}
- return 0;
+ return rc;
}
diff --git a/rootdir/Android.mk b/rootdir/Android.mk
index 64ff52244..e6887bb21 100644
--- a/rootdir/Android.mk
+++ b/rootdir/Android.mk
@@ -7,25 +7,6 @@ copy_from := \
etc/dbus.conf \
etc/hosts
-ifeq ($(TARGET_PRODUCT),full)
-copy_from += etc/vold.fstab
-endif
-
-ifeq ($(TARGET_PRODUCT),full_x86)
-copy_from += etc/vold.fstab
-endif
-
-ifeq ($(TARGET_PRODUCT),full_mips)
-copy_from += etc/vold.fstab
-endif
-
-# the /system/etc/init.goldfish.sh is needed to enable emulator support
-# in the system image. In theory, we don't need these for -user builds
-# which are device-specific. However, these builds require at the moment
-# to run the dex pre-optimization *in* the emulator. So keep the file until
-# we are capable of running dex preopt on the host.
-#
-copy_from += etc/init.goldfish.sh
copy_to := $(addprefix $(TARGET_OUT)/,$(copy_from))
copy_from := $(addprefix $(LOCAL_PATH)/,$(copy_from))
@@ -56,20 +37,6 @@ $(INSTALLED_RAMDISK_TARGET): $(file)
# init.usb.rc is handled by build/target/product/core.rc
-# Just like /system/etc/init.goldfish.sh, the /init.godlfish.rc is here
-# to allow -user builds to properly run the dex pre-optimization pass in
-# the emulator.
-file := $(TARGET_ROOT_OUT)/init.goldfish.rc
-$(file) : $(LOCAL_PATH)/etc/init.goldfish.rc | $(ACP)
- $(transform-prebuilt-to-target)
-ALL_PREBUILT += $(file)
-$(INSTALLED_RAMDISK_TARGET): $(file)
-
-file := $(TARGET_ROOT_OUT)/ueventd.goldfish.rc
-$(file) : $(LOCAL_PATH)/etc/ueventd.goldfish.rc | $(ACP)
- $(transform-prebuilt-to-target)
-ALL_PREBUILT += $(file)
-$(INSTALLED_RAMDISK_TARGET): $(file)
# create some directories (some are mount points)
DIRS := $(addprefix $(TARGET_ROOT_OUT)/, \
diff --git a/rootdir/etc/init.goldfish.rc b/rootdir/etc/init.goldfish.rc
deleted file mode 100644
index 1373be81d..000000000
--- a/rootdir/etc/init.goldfish.rc
+++ /dev/null
@@ -1,83 +0,0 @@
-on early-init
- export EXTERNAL_STORAGE /mnt/sdcard
- mkdir /mnt/sdcard 0000 system system
- # for backwards compatibility
- symlink /mnt/sdcard /sdcard
- mount debugfs debugfs /sys/kernel/debug
-
-on boot
- setsebool in_qemu 1
- restorecon /sys/qemu_trace/process_name
- restorecon /sys/qemu_trace/state
- restorecon /sys/qemu_trace/symbol
- setprop ARGH ARGH
- setprop net.eth0.gw 10.0.2.2
- setprop net.eth0.dns1 10.0.2.3
- setprop net.gprs.local-ip 10.0.2.15
- setprop ro.radio.use-ppp no
- setprop ro.build.product generic
- setprop ro.product.device generic
-
-# fake some battery state
- setprop status.battery.state Slow
- setprop status.battery.level 5
- setprop status.battery.level_raw 50
- setprop status.battery.level_scale 9
-
-# disable some daemons the emulator doesn't want
- stop dund
- stop akmd
-
-# start essential services
- start qemud
- start goldfish-logcat
- start goldfish-setup
-
- setprop ro.setupwizard.mode EMULATOR
-
-# enable Google-specific location features,
-# like NetworkLocationProvider and LocationCollector
- setprop ro.com.google.locationfeatures 1
-
-# For the emulator, which bypasses Setup Wizard, you can specify
-# account info for the device via these two properties. Google
-# Login Service will insert these accounts into the database when
-# it is created (ie, after a data wipe).
-#
-# setprop ro.config.hosted_account username@hosteddomain.org:password
-# setprop ro.config.google_account username@gmail.com:password
-#
-# You MUST have a Google account on the device, and you MAY
-# additionally have a hosted account. No other configuration is
-# supported, and arbitrary breakage may result if you specify
-# something else.
-
-service goldfish-setup /system/etc/init.goldfish.sh
- user root
- group root
- oneshot
-
-# The qemu-props program is used to set various system
-# properties on boot. It must be run early during the boot
-# process to avoid race conditions with other daemons that
-# might read them (e.g. surface flinger), so define it in
-# class 'core'
-#
-service qemu-props /system/bin/qemu-props
- class core
- user root
- group root
- oneshot
-
-service qemud /system/bin/qemud
- socket qemud stream 666
- oneshot
-
-# -Q is a special logcat option that forces the
-# program to check wether it runs on the emulator
-# if it does, it redirects its output to the device
-# named by the androidboot.console kernel option
-# if not, is simply exits immediately
-
-service goldfish-logcat /system/bin/logcat -Q
- oneshot
diff --git a/rootdir/etc/init.goldfish.sh b/rootdir/etc/init.goldfish.sh
deleted file mode 100755
index ece75b429..000000000
--- a/rootdir/etc/init.goldfish.sh
+++ /dev/null
@@ -1,68 +0,0 @@
-#!/system/bin/sh
-
-# Setup networking when boot starts
-ifconfig eth0 10.0.2.15 netmask 255.255.255.0 up
-route add default gw 10.0.2.2 dev eth0
-
-# ro.kernel.android.qemud is normally set when we
-# want the RIL (radio interface layer) to talk to
-# the emulated modem through qemud.
-#
-# However, this will be undefined in two cases:
-#
-# - When we want the RIL to talk directly to a guest
-# serial device that is connected to a host serial
-# device by the emulator.
-#
-# - We don't want to use the RIL but the VM-based
-# modem emulation that runs inside the guest system
-# instead.
-#
-# The following detects the latter case and sets up the
-# system for it.
-#
-qemud=`getprop ro.kernel.android.qemud`
-case "$qemud" in
- "")
- radio_ril=`getprop ro.kernel.android.ril`
- case "$radio_ril" in
- "")
- # no need for the radio interface daemon
- # telephony is entirely emulated in Java
- setprop ro.radio.noril yes
- stop ril-daemon
- ;;
- esac
- ;;
-esac
-
-# Setup additionnal DNS servers if needed
-num_dns=`getprop ro.kernel.ndns`
-case "$num_dns" in
- 2) setprop net.eth0.dns2 10.0.2.4
- ;;
- 3) setprop net.eth0.dns2 10.0.2.4
- setprop net.eth0.dns3 10.0.2.5
- ;;
- 4) setprop net.eth0.dns2 10.0.2.4
- setprop net.eth0.dns3 10.0.2.5
- setprop net.eth0.dns4 10.0.2.6
- ;;
-esac
-
-# disable boot animation for a faster boot sequence when needed
-boot_anim=`getprop ro.kernel.android.bootanim`
-case "$boot_anim" in
- 0) setprop debug.sf.nobootanimation 1
- ;;
-esac
-
-# set up the second interface (for inter-emulator connections)
-# if required
-my_ip=`getprop net.shared_net_ip`
-case "$my_ip" in
- "")
- ;;
- *) ifconfig eth1 "$my_ip" netmask 255.255.255.0 up
- ;;
-esac
diff --git a/rootdir/etc/ueventd.goldfish.rc b/rootdir/etc/ueventd.goldfish.rc
deleted file mode 100644
index 8de704962..000000000
--- a/rootdir/etc/ueventd.goldfish.rc
+++ /dev/null
@@ -1,5 +0,0 @@
-# These settings are specific to running under the Android emulator
-/dev/qemu_trace 0666 system system
-/dev/qemu_pipe 0666 system system
-/dev/ttyS* 0666 system system
-/proc 0666 system system
diff --git a/rootdir/etc/vold.fstab b/rootdir/etc/vold.fstab
deleted file mode 100644
index 4aad8dca2..000000000
--- a/rootdir/etc/vold.fstab
+++ /dev/null
@@ -1,24 +0,0 @@
-## Vold 2.0 Generic fstab
-## - San Mehat (san@android.com)
-##
-
-#######################
-## Regular device mount
-##
-## Format: dev_mount <label> <mount_point> <part> <sysfs_path1...>
-## label - Label for the volume
-## mount_point - Where the volume will be mounted
-## part - Partition # (1 based), or 'auto' for first usable partition.
-## <sysfs_path> - List of sysfs paths to source devices
-######################
-
-## Example of a standard sdcard mount for the emulator / Dream
-# Mounts the first usable partition of the specified device
-dev_mount sdcard /mnt/sdcard auto /devices/platform/goldfish_mmc.0 /devices/platform/msm_sdcc.2/mmc_host/mmc1
-
-## Example of a dual card setup
-# dev_mount left_sdcard /sdcard1 auto /devices/platform/goldfish_mmc.0 /devices/platform/msm_sdcc.2/mmc_host/mmc1
-# dev_mount right_sdcard /sdcard2 auto /devices/platform/goldfish_mmc.1 /devices/platform/msm_sdcc.3/mmc_host/mmc1
-
-## Example of specifying a specific partition for mounts
-# dev_mount sdcard /sdcard 2 /devices/platform/goldfish_mmc.0 /devices/platform/msm_sdcc.2/mmc_host/mmc1
diff --git a/rootdir/init.rc b/rootdir/init.rc
index e1b826e5e..c3ef50329 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -37,7 +37,7 @@ loglevel 3
export ANDROID_STORAGE /storage
export ASEC_MOUNTPOINT /mnt/asec
export LOOP_MOUNTPOINT /mnt/obb
- export BOOTCLASSPATH /system/framework/core.jar:/system/framework/okhttp.jar:/system/framework/core-junit.jar:/system/framework/bouncycastle.jar:/system/framework/ext.jar:/system/framework/framework.jar:/system/framework/telephony-common.jar:/system/framework/mms-common.jar:/system/framework/android.policy.jar:/system/framework/services.jar:/system/framework/apache-xml.jar
+ export BOOTCLASSPATH /system/framework/core.jar:/system/framework/okhttp.jar:/system/framework/core-junit.jar:/system/framework/bouncycastle.jar:/system/framework/ext.jar:/system/framework/framework.jar:/system/framework/telephony-common.jar:/system/framework/voip-common.jar:/system/framework/mms-common.jar:/system/framework/android.policy.jar:/system/framework/services.jar:/system/framework/apache-xml.jar
# Backward compatibility
symlink /system/etc /etc
@@ -214,6 +214,7 @@ on post-fs-data
mkdir /data/misc/wifi 0770 wifi wifi
chmod 0660 /data/misc/wifi/wpa_supplicant.conf
mkdir /data/local 0751 root root
+ mkdir /data/misc/media 0700 media media
# For security reasons, /data/local/tmp should always be empty.
# Do not place files or directories in /data/local/tmp
@@ -242,6 +243,9 @@ on post-fs-data
# the following directory.
mkdir /data/drm 0770 drm drm
+ # symlink to bugreport storage location
+ symlink /data/data/com.android.shell/files/bugreports /data/bugreports
+
# Separate location for storing security policy files on data
mkdir /data/security 0700 system system
@@ -291,10 +295,14 @@ on boot
chown system system /sys/devices/system/cpu/cpufreq/interactive/timer_rate
chmod 0660 /sys/devices/system/cpu/cpufreq/interactive/timer_rate
+ chown system system /sys/devices/system/cpu/cpufreq/interactive/timer_slack
+ chmod 0660 /sys/devices/system/cpu/cpufreq/interactive/timer_slack
chown system system /sys/devices/system/cpu/cpufreq/interactive/min_sample_time
chmod 0660 /sys/devices/system/cpu/cpufreq/interactive/min_sample_time
chown system system /sys/devices/system/cpu/cpufreq/interactive/hispeed_freq
chmod 0660 /sys/devices/system/cpu/cpufreq/interactive/hispeed_freq
+ chown system system /sys/devices/system/cpu/cpufreq/interactive/target_loads
+ chmod 0660 /sys/devices/system/cpu/cpufreq/interactive/target_loads
chown system system /sys/devices/system/cpu/cpufreq/interactive/go_hispeed_load
chmod 0660 /sys/devices/system/cpu/cpufreq/interactive/go_hispeed_load
chown system system /sys/devices/system/cpu/cpufreq/interactive/above_hispeed_delay
@@ -306,6 +314,8 @@ on boot
chmod 0660 /sys/devices/system/cpu/cpufreq/interactive/input_boost
chown system system /sys/devices/system/cpu/cpufreq/interactive/boostpulse_duration
chmod 0660 /sys/devices/system/cpu/cpufreq/interactive/boostpulse_duration
+ chown system system /sys/devices/system/cpu/cpufreq/interactive/io_is_busy
+ chmod 0660 /sys/devices/system/cpu/cpufreq/interactive/io_is_busy
# Assume SMP uses shared cpufreq policy for all CPUs
chown system system /sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq
@@ -338,6 +348,10 @@ on boot
chown system system /sys/kernel/ipv4/tcp_rmem_max
chown root radio /proc/cmdline
+# Set these so we can remotely update SELinux policy
+ chown system system /sys/fs/selinux/load
+ chown system system /sys/fs/selinux/enforce
+
# Define TCP buffer sizes for various networks
# ReadMin, ReadInitial, ReadMax, WriteMin, WriteInitial, WriteMax,
setprop net.tcp.buffersize.default 4096,87380,110208,4096,16384,110208
diff --git a/rootdir/init.usb.rc b/rootdir/init.usb.rc
index f37b630bc..15467cc21 100644
--- a/rootdir/init.usb.rc
+++ b/rootdir/init.usb.rc
@@ -88,5 +88,4 @@ on property:sys.usb.config=accessory,audio_source,adb
# Used to set USB configuration at boot and to switch the configuration
# when changing the default configuration
on property:persist.sys.usb.config=*
- setprop sys.usb.config none
setprop sys.usb.config ${persist.sys.usb.config}
diff --git a/sdcard/sdcard.c b/sdcard/sdcard.c
index 8d87ee92d..bff6e67d5 100644
--- a/sdcard/sdcard.c
+++ b/sdcard/sdcard.c
@@ -28,6 +28,8 @@
#include <limits.h>
#include <ctype.h>
#include <pthread.h>
+#include <sys/time.h>
+#include <sys/resource.h>
#include <private/android_filesystem_config.h>
@@ -1305,6 +1307,7 @@ int main(int argc, char **argv)
gid_t gid = 0;
int num_threads = DEFAULT_NUM_THREADS;
int i;
+ struct rlimit rlim;
for (i = 1; i < argc; i++) {
char* arg = argv[i];
@@ -1353,6 +1356,12 @@ int main(int argc, char **argv)
return usage();
}
+ rlim.rlim_cur = 8192;
+ rlim.rlim_max = 8192;
+ if (setrlimit(RLIMIT_NOFILE, &rlim)) {
+ ERROR("Error setting RLIMIT_NOFILE, errno = %d\n", errno);
+ }
+
res = run(source_path, dest_path, uid, gid, num_threads);
return res < 0 ? 1 : 0;
}
diff --git a/toolbox/Android.mk b/toolbox/Android.mk
index dbbce0603..2ecb62644 100644
--- a/toolbox/Android.mk
+++ b/toolbox/Android.mk
@@ -58,6 +58,7 @@ TOOLS := \
lsof \
du \
md5 \
+ clear \
getenforce \
setenforce \
chcon \
diff --git a/toolbox/clear.c b/toolbox/clear.c
new file mode 100644
index 000000000..df46ad251
--- /dev/null
+++ b/toolbox/clear.c
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2012, The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google, Inc. nor the names of its contributors
+ * may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+
+int clear_main(int argc, char **argv) {
+ /* This prints the clear screen and move cursor to top-left corner control
+ * characters for VT100 terminals. This means it will not work on
+ * non-VT100 compliant terminals, namely Windows' cmd.exe, but should
+ * work on anything unix-y. */
+ fputs("\x1b[2J\x1b[H", stdout);
+ return 0;
+}
diff --git a/toolbox/du.c b/toolbox/du.c
index 06374a440..fc7c94345 100644
--- a/toolbox/du.c
+++ b/toolbox/du.c
@@ -62,7 +62,7 @@ __RCSID("$NetBSD: du.c,v 1.33 2008/07/30 22:03:40 dsl Exp $");
int linkchk(dev_t, ino_t);
void prstat(const char *, int64_t);
-void usage(void);
+static void usage(void);
long blocksize;
@@ -312,7 +312,7 @@ linkchk(dev_t dev, ino_t ino)
return 0;
}
-void
+static void
usage(void)
{
diff --git a/toolbox/renice.c b/toolbox/renice.c
index 978b3295c..9dfeb51f9 100644
--- a/toolbox/renice.c
+++ b/toolbox/renice.c
@@ -35,11 +35,12 @@
#include <sys/time.h>
#include <sys/resource.h>
#include <sched.h>
+#include <getopt.h>
static void
usage(const char *s)
{
- fprintf(stderr, "USAGE: %s [[-r] priority pids ...] [-g pid]\n", s);
+ fprintf(stderr, "USAGE: %s [[-r] [-t TYPE] priority pids ...] [-g pid]\n", s);
exit(EXIT_FAILURE);
}
@@ -74,32 +75,49 @@ void print_prio(pid_t pid)
sched_get_priority_min(sched), sched_get_priority_max(sched));
}
+int get_sched(char *str)
+{
+ if (strcasecmp(str, "RR") == 0)
+ return SCHED_RR;
+ else if (strcasecmp(str, "FIFO") == 0)
+ return SCHED_FIFO;
+ else if (strcasecmp(str, "NORMAL") == 0)
+ return SCHED_OTHER;
+ else if (strcasecmp(str, "OTHER") == 0)
+ return SCHED_OTHER;
+ return SCHED_RR;
+}
+
int renice_main(int argc, char *argv[])
{
int prio;
int realtime = 0;
+ int opt;
+ int sched = SCHED_RR;
char *cmd = argv[0];
- // consume command name
- argc--;
- argv++;
-
- if (argc < 1)
- usage(cmd);
-
- if(strcmp("-r", argv[0]) == 0) {
- // do realtime priority adjustment
- realtime = 1;
- argc--;
- argv++;
- }
-
- if(strcmp("-g", argv[0]) == 0) {
- if (argc < 2)
+ do {
+ opt = getopt(argc, argv, "rt:g:");
+ if (opt == -1)
+ break;
+ switch (opt) {
+ case 'r':
+ // do realtime priority adjustment
+ realtime = 1;
+ break;
+ case 't':
+ sched = get_sched(optarg);
+ break;
+ case 'g':
+ print_prio(atoi(optarg));
+ return 0;
+ default:
usage(cmd);
- print_prio(atoi(argv[1]));
- return 0;
- }
+ }
+ } while (1);
+
+ argc -= optind;
+ argv += optind;
if (argc < 1)
usage(cmd);
@@ -122,7 +140,7 @@ int renice_main(int argc, char *argv[])
struct sched_param sp = { .sched_priority = prio };
int ret;
- ret = sched_setscheduler(pid, SCHED_RR, &sp);
+ ret = sched_setscheduler(pid, sched, &sp);
if (ret) {
perror("sched_set_scheduler");
exit(EXIT_FAILURE);
@@ -137,8 +155,6 @@ int renice_main(int argc, char *argv[])
}
}
}
-
+
return 0;
}
-
-