diff options
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),) @@ -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) @@ -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", ®_NAMES[reg * 2]); - dump_memory(log, tid, addr, at_fault); + _LOG(log, scopeFlags | SCOPE_SENSITIVE, "\nmemory near %.2s:\n", ®_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", ®_NAMES[reg * 2]); - dump_memory(log, tid, addr, at_fault); + _LOG(log, scopeFlags | SCOPE_SENSITIVE, "\nmemory near %.2s:\n", ®_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; } - - |