Merge "Add /data/misc/perfprofd to store perf profile."
diff --git a/adb/Android.mk b/adb/Android.mk
index dd1343b..7d6238c 100644
--- a/adb/Android.mk
+++ b/adb/Android.mk
@@ -6,11 +6,18 @@
 LOCAL_PATH:= $(call my-dir)
 
 ifeq ($(HOST_OS),windows)
-  adb_host_clang := false  # libc++ for mingw not ready yet.
+    adb_host_clang := false  # libc++ for mingw not ready yet.
 else
-  adb_host_clang := true
+    adb_host_clang := true
 endif
 
+adb_version := $(shell git -C $(LOCAL_PATH) rev-parse --short=12 HEAD 2>/dev/null)-android
+
+ADB_COMMON_CFLAGS := \
+    -Wall -Werror \
+    -Wno-unused-parameter \
+    -DADB_REVISION='"$(adb_version)"' \
+
 # libadb
 # =========================================================
 
@@ -37,8 +44,7 @@
     transport_test.cpp \
 
 LIBADB_CFLAGS := \
-    -Wall -Werror \
-    -Wno-unused-parameter \
+    $(ADB_COMMON_CFLAGS) \
     -Wno-missing-field-initializers \
     -fvisibility=hidden \
 
@@ -103,6 +109,7 @@
 LOCAL_SHARED_LIBRARIES := liblog libbase libcutils
 include $(BUILD_NATIVE_TEST)
 
+ifneq ($(HOST_OS),windows)
 include $(CLEAR_VARS)
 LOCAL_CLANG := $(adb_host_clang)
 LOCAL_MODULE := adb_test
@@ -115,14 +122,15 @@
     libcutils \
 
 ifeq ($(HOST_OS),linux)
-  LOCAL_LDLIBS += -lrt -ldl -lpthread
+    LOCAL_LDLIBS += -lrt -ldl -lpthread
 endif
 
 ifeq ($(HOST_OS),darwin)
-  LOCAL_LDLIBS += -framework CoreFoundation -framework IOKit
+    LOCAL_LDLIBS += -framework CoreFoundation -framework IOKit
 endif
 
 include $(BUILD_HOST_NATIVE_TEST)
+endif
 
 # adb device tracker (used by ddms) test tool
 # =========================================================
@@ -169,8 +177,7 @@
     file_sync_client.cpp \
 
 LOCAL_CFLAGS += \
-    -Wall -Werror \
-    -Wno-unused-parameter \
+    $(ADB_COMMON_CFLAGS) \
     -D_GNU_SOURCE \
     -DADB_HOST=1 \
 
@@ -222,10 +229,9 @@
     set_verity_enable_state_service.cpp \
 
 LOCAL_CFLAGS := \
+    $(ADB_COMMON_CFLAGS) \
     -DADB_HOST=0 \
     -D_GNU_SOURCE \
-    -Wall -Werror \
-    -Wno-unused-parameter \
     -Wno-deprecated-declarations \
 
 ifneq (,$(filter userdebug eng,$(TARGET_BUILD_VARIANT)))
diff --git a/adb/adb.cpp b/adb/adb.cpp
index 8a7b9c9..c78076d 100644
--- a/adb/adb.cpp
+++ b/adb/adb.cpp
@@ -696,7 +696,7 @@
 // Try to handle a network forwarding request.
 // This returns 1 on success, 0 on failure, and -1 to indicate this is not
 // a forwarding-related request.
-int handle_forward_request(const char* service, transport_type ttype, char* serial, int reply_fd)
+int handle_forward_request(const char* service, TransportType type, char* serial, int reply_fd)
 {
     if (!strcmp(service, "list-forward")) {
         // Create the list of forward redirections.
@@ -757,13 +757,13 @@
         }
 
         std::string error_msg;
-        transport = acquire_one_transport(CS_ANY, ttype, serial, &error_msg);
+        transport = acquire_one_transport(CS_ANY, type, serial, &error_msg);
         if (!transport) {
             SendFail(reply_fd, error_msg);
             return 1;
         }
 
-        install_status_t r;
+        InstallStatus r;
         if (createForward) {
             r = install_listener(local, remote, transport, no_rebind);
         } else {
@@ -796,7 +796,7 @@
     return 0;
 }
 
-int handle_host_request(char *service, transport_type ttype, char* serial, int reply_fd, asocket *s)
+int handle_host_request(char *service, TransportType type, char* serial, int reply_fd, asocket *s)
 {
     if(!strcmp(service, "kill")) {
         fprintf(stderr,"adb server killed by remote request\n");
@@ -813,7 +813,7 @@
     // "transport-local:" is used for switching transport to the only local transport
     // "transport-any:" is used for switching transport to the only transport
     if (!strncmp(service, "transport", strlen("transport"))) {
-        transport_type type = kTransportAny;
+        TransportType type = kTransportAny;
 
         if (!strncmp(service, "transport-usb", strlen("transport-usb"))) {
             type = kTransportUsb;
@@ -890,7 +890,7 @@
 
     if(!strncmp(service,"get-serialno",strlen("get-serialno"))) {
         const char *out = "unknown";
-        transport = acquire_one_transport(CS_ANY, ttype, serial, NULL);
+        transport = acquire_one_transport(CS_ANY, type, serial, NULL);
         if (transport && transport->serial) {
             out = transport->serial;
         }
@@ -900,7 +900,7 @@
     }
     if(!strncmp(service,"get-devpath",strlen("get-devpath"))) {
         const char *out = "unknown";
-        transport = acquire_one_transport(CS_ANY, ttype, serial, NULL);
+        transport = acquire_one_transport(CS_ANY, type, serial, NULL);
         if (transport && transport->devpath) {
             out = transport->devpath;
         }
@@ -917,14 +917,14 @@
     }
 
     if(!strncmp(service,"get-state",strlen("get-state"))) {
-        transport = acquire_one_transport(CS_ANY, ttype, serial, NULL);
+        transport = acquire_one_transport(CS_ANY, type, serial, NULL);
         SendOkay(reply_fd);
         SendProtocolString(reply_fd, transport->connection_state_name());
         return 0;
     }
 #endif // ADB_HOST
 
-    int ret = handle_forward_request(service, ttype, serial, reply_fd);
+    int ret = handle_forward_request(service, type, serial, reply_fd);
     if (ret >= 0)
       return ret - 1;
     return -1;
diff --git a/adb/adb.h b/adb/adb.h
index fd9d0e6..5d20165 100644
--- a/adb/adb.h
+++ b/adb/adb.h
@@ -161,7 +161,7 @@
 ** object, it's a special value used to indicate that a client wants to
 ** connect to a service implemented within the ADB server itself.
 */
-enum transport_type {
+enum TransportType {
         kTransportUsb,
         kTransportLocal,
         kTransportAny,
@@ -187,7 +187,7 @@
     unsigned sync_token;
     int connection_state;
     int online;
-    transport_type type;
+    TransportType type;
 
         /* usb handle or socket fd as needed */
     usb_handle *usb;
@@ -284,7 +284,7 @@
 int       create_jdwp_connection_fd(int  jdwp_pid);
 #endif
 
-int handle_forward_request(const char* service, transport_type ttype, char* serial, int reply_fd);
+int handle_forward_request(const char* service, TransportType type, char* serial, int reply_fd);
 
 #if !ADB_HOST
 void framebuffer_service(int fd, void *cookie);
@@ -353,11 +353,6 @@
 extern int HOST;
 extern int SHELL_EXIT_NOTIFY_FD;
 
-enum subproc_mode {
-    SUBPROC_PTY = 0,
-    SUBPROC_RAW = 1,
-} ;
-
 #define CHUNK_SIZE (64*1024)
 
 #if !ADB_HOST
@@ -371,7 +366,7 @@
 #define USB_FFS_ADB_IN    USB_FFS_ADB_EP(ep2)
 #endif
 
-int handle_host_request(char *service, transport_type ttype, char* serial, int reply_fd, asocket *s);
+int handle_host_request(char *service, TransportType type, char* serial, int reply_fd, asocket *s);
 
 void handle_online(atransport *t);
 void handle_offline(atransport *t);
diff --git a/adb/adb_client.cpp b/adb/adb_client.cpp
index 7bb8e4a..18e14de 100644
--- a/adb/adb_client.cpp
+++ b/adb/adb_client.cpp
@@ -36,7 +36,7 @@
 
 #include "adb_io.h"
 
-static transport_type __adb_transport = kTransportAny;
+static TransportType __adb_transport = kTransportAny;
 static const char* __adb_serial = NULL;
 
 static int __adb_server_port = DEFAULT_ADB_PORT;
@@ -64,7 +64,7 @@
     return true;
 }
 
-void adb_set_transport(transport_type type, const char* serial)
+void adb_set_transport(TransportType type, const char* serial)
 {
     __adb_transport = type;
     __adb_serial = serial;
diff --git a/adb/adb_client.h b/adb/adb_client.h
index 96416f5..de5c2db 100644
--- a/adb/adb_client.h
+++ b/adb/adb_client.h
@@ -21,9 +21,8 @@
 // Returns true on success; returns false and fills 'error' on failure.
 bool adb_query(const std::string& service, std::string* result, std::string* error);
 
-/* Set the preferred transport to connect to.
-*/
-void adb_set_transport(transport_type type, const char* serial);
+// Set the preferred transport to connect to.
+void adb_set_transport(TransportType type, const char* serial);
 
 /* Set TCP specifics of the transport to use
 */
diff --git a/adb/adb_listeners.cpp b/adb/adb_listeners.cpp
index 3fc4719..cf193ab 100644
--- a/adb/adb_listeners.cpp
+++ b/adb/adb_listeners.cpp
@@ -160,8 +160,7 @@
     return result;
 }
 
-install_status_t remove_listener(const char *local_name, atransport* transport)
-{
+InstallStatus remove_listener(const char *local_name, atransport* transport) {
     alistener *l;
 
     for (l = listener_list.next; l != &listener_list; l = l->next) {
@@ -185,7 +184,7 @@
     }
 }
 
-install_status_t install_listener(const std::string& local_name,
+InstallStatus install_listener(const std::string& local_name,
                                   const char *connect_to,
                                   atransport* transport,
                                   int no_rebind)
diff --git a/adb/adb_listeners.h b/adb/adb_listeners.h
index 67168ae..9a7ded1 100644
--- a/adb/adb_listeners.h
+++ b/adb/adb_listeners.h
@@ -22,7 +22,7 @@
 #include <string>
 
 // error/status codes for install_listener.
-enum install_status_t {
+enum InstallStatus {
   INSTALL_STATUS_OK = 0,
   INSTALL_STATUS_INTERNAL_ERROR = -1,
   INSTALL_STATUS_CANNOT_BIND = -2,
@@ -36,14 +36,14 @@
 void listener_event_func(int _fd, unsigned ev, void *_l);
 void ss_listener_event_func(int _fd, unsigned ev, void *_l);
 
-install_status_t install_listener(const std::string& local_name,
-                                  const char* connect_to,
-                                  atransport* transport,
-                                  int no_rebind);
+InstallStatus install_listener(const std::string& local_name,
+                               const char* connect_to,
+                               atransport* transport,
+                               int no_rebind);
 
 std::string format_listeners();
 
-install_status_t remove_listener(const char* local_name, atransport* transport);
+InstallStatus remove_listener(const char* local_name, atransport* transport);
 void remove_all_listeners(void);
 
 #endif /* __ADB_LISTENERS_H */
diff --git a/adb/adb_main.cpp b/adb/adb_main.cpp
index bd22d74..3f88d13 100644
--- a/adb/adb_main.cpp
+++ b/adb/adb_main.cpp
@@ -358,29 +358,25 @@
 }
 #endif
 
+// TODO(danalbert): Split this file up into adb_main.cpp and adbd_main.cpp.
 int main(int argc, char **argv) {
 #if ADB_HOST
+    // adb client/server
     adb_sysdeps_init();
-#else
-    close_stdin();
-#endif
     adb_trace_init();
-
-#if ADB_HOST
     D("Handling commandline()\n");
     return adb_commandline(argc - 1, const_cast<const char**>(argv + 1));
 #else
-    /* If adbd runs inside the emulator this will enable adb tracing via
-     * adb-debug qemud service in the emulator. */
-    adb_qemu_trace_init();
+    // adbd
     while (true) {
-        int c;
-        int option_index = 0;
         static struct option opts[] = {
-            {"root_seclabel", required_argument, 0, 's' },
-            {"device_banner", required_argument, 0, 'b' }
+            {"root_seclabel", required_argument, nullptr, 's'},
+            {"device_banner", required_argument, nullptr, 'b'},
+            {"version", no_argument, nullptr, 'v'},
         };
-        c = getopt_long(argc, argv, "", opts, &option_index);
+
+        int option_index = 0;
+        int c = getopt_long(argc, argv, "", opts, &option_index);
         if (c == -1)
             break;
         switch (c) {
@@ -390,11 +386,24 @@
         case 'b':
             adb_device_banner = optarg;
             break;
+        case 'v':
+            printf("Android Debug Bridge Daemon version %d.%d.%d %s\n",
+                   ADB_VERSION_MAJOR, ADB_VERSION_MINOR, ADB_SERVER_VERSION,
+                   ADB_REVISION);
+            return 0;
         default:
             break;
         }
     }
 
+    close_stdin();
+
+    adb_trace_init();
+
+    /* If adbd runs inside the emulator this will enable adb tracing via
+     * adb-debug qemud service in the emulator. */
+    adb_qemu_trace_init();
+
     D("Handling main()\n");
     return adb_main(0, DEFAULT_ADB_PORT);
 #endif
diff --git a/adb/commandline.cpp b/adb/commandline.cpp
index b385517..76eb8c0 100644
--- a/adb/commandline.cpp
+++ b/adb/commandline.cpp
@@ -47,14 +47,9 @@
 #include "adb_utils.h"
 #include "file_sync_service.h"
 
-static int do_cmd(transport_type ttype, const char* serial, const char *cmd, ...);
-
-static int install_app(transport_type transport, const char* serial, int argc,
-                       const char** argv);
-static int install_multiple_app(transport_type transport, const char* serial, int argc,
-                                const char** argv);
-static int uninstall_app(transport_type transport, const char* serial, int argc,
-                         const char** argv);
+static int install_app(TransportType t, const char* serial, int argc, const char** argv);
+static int install_multiple_app(TransportType t, const char* serial, int argc, const char** argv);
+static int uninstall_app(TransportType t, const char* serial, int argc, const char** argv);
 
 static std::string gProductOutPath;
 extern int gListenAll;
@@ -71,8 +66,8 @@
 }
 
 static void version(FILE* out) {
-    fprintf(out, "Android Debug Bridge version %d.%d.%d\n",
-            ADB_VERSION_MAJOR, ADB_VERSION_MINOR, ADB_SERVER_VERSION);
+    fprintf(out, "Android Debug Bridge version %d.%d.%d %s\n", ADB_VERSION_MAJOR,
+            ADB_VERSION_MINOR, ADB_SERVER_VERSION, ADB_REVISION);
 }
 
 static void help() {
@@ -408,7 +403,6 @@
 }
 
 static int interactive_shell() {
-    adb_thread_t thr;
     int fdi;
 
     std::string error;
@@ -429,14 +423,15 @@
     fds[1] = fdi;
 
     stdin_raw_init(fdi);
-    adb_thread_create(&thr, stdin_read_thread, fds);
+
+    adb_thread_create(stdin_read_thread, fds);
     read_and_dump(fd);
     stdin_raw_restore(fdi);
     return 0;
 }
 
 
-static std::string format_host_command(const char* command, transport_type type, const char* serial) {
+static std::string format_host_command(const char* command, TransportType type, const char* serial) {
     if (serial) {
         return android::base::StringPrintf("host-serial:%s:%s", serial, command);
     }
@@ -678,7 +673,31 @@
 #endif /* !defined(_WIN32) */
 }
 
-static int send_shell_command(transport_type transport, const char* serial,
+static bool wait_for_device(const char* service, TransportType t, const char* serial) {
+    // Was the caller vague about what they'd like us to wait for?
+    // If so, check they weren't more specific in their choice of transport type.
+    if (strcmp(service, "wait-for-device") == 0) {
+        if (t == kTransportUsb) {
+            service = "wait-for-usb";
+        } else if (t == kTransportLocal) {
+            service = "wait-for-local";
+        } else {
+            service = "wait-for-any";
+        }
+    }
+
+    std::string cmd = format_host_command(service, t, serial);
+    std::string error;
+    if (adb_command(cmd, &error)) {
+        D("failure: %s *\n", error.c_str());
+        fprintf(stderr,"error: %s\n", error.c_str());
+        return false;
+    }
+
+    return true;
+}
+
+static int send_shell_command(TransportType transport_type, const char* serial,
                               const std::string& command) {
     int fd;
     while (true) {
@@ -689,7 +708,7 @@
         }
         fprintf(stderr,"- waiting for device -\n");
         adb_sleep_ms(1000);
-        do_cmd(transport, serial, "wait-for-device", 0);
+        wait_for_device("wait-for-device", transport_type, serial);
     }
 
     read_and_dump(fd);
@@ -700,7 +719,7 @@
     return rc;
 }
 
-static int logcat(transport_type transport, const char* serial, int argc, const char** argv) {
+static int logcat(TransportType transport, const char* serial, int argc, const char** argv) {
     char* log_tags = getenv("ANDROID_LOG_TAGS");
     std::string quoted = escape_arg(log_tags == nullptr ? "" : log_tags);
 
@@ -933,11 +952,8 @@
     int no_daemon = 0;
     int is_daemon = 0;
     int is_server = 0;
-    int persist = 0;
     int r;
-    transport_type ttype = kTransportAny;
-    const char* serial = NULL;
-    const char* server_port_str = NULL;
+    TransportType transport_type = kTransportAny;
 
     // If defined, this should be an absolute path to
     // the directory containing all of the various system images
@@ -950,10 +966,10 @@
     }
     // TODO: also try TARGET_PRODUCT/TARGET_DEVICE as a hint
 
-    serial = getenv("ANDROID_SERIAL");
+    const char* serial = getenv("ANDROID_SERIAL");
 
     /* Validate and assign the server port */
-    server_port_str = getenv("ANDROID_ADB_SERVER_PORT");
+    const char* server_port_str = getenv("ANDROID_ADB_SERVER_PORT");
     int server_port = DEFAULT_ADB_PORT;
     if (server_port_str && strlen(server_port_str) > 0) {
         server_port = (int) strtol(server_port_str, NULL, 0);
@@ -974,8 +990,6 @@
         } else if (!strcmp(argv[0], "fork-server")) {
             /* this is a special flag used only when the ADB client launches the ADB Server */
             is_daemon = 1;
-        } else if (!strcmp(argv[0],"persist")) {
-            persist = 1;
         } else if (!strncmp(argv[0], "-p", 2)) {
             const char *product = NULL;
             if (argv[0][2] == '\0') {
@@ -1001,9 +1015,9 @@
                 argv++;
             }
         } else if (!strcmp(argv[0],"-d")) {
-            ttype = kTransportUsb;
+            transport_type = kTransportUsb;
         } else if (!strcmp(argv[0],"-e")) {
-            ttype = kTransportLocal;
+            transport_type = kTransportLocal;
         } else if (!strcmp(argv[0],"-a")) {
             gListenAll = 1;
         } else if (!strncmp(argv[0], "-H", 2)) {
@@ -1048,7 +1062,7 @@
         argv++;
     }
 
-    adb_set_transport(ttype, serial);
+    adb_set_transport(transport_type, serial);
     adb_set_tcp_specifics(server_port);
 
     if (is_server) {
@@ -1070,27 +1084,13 @@
     /* handle wait-for-* prefix */
     if (!strncmp(argv[0], "wait-for-", strlen("wait-for-"))) {
         const char* service = argv[0];
-        if (!strncmp(service, "wait-for-device", strlen("wait-for-device"))) {
-            if (ttype == kTransportUsb) {
-                service = "wait-for-usb";
-            } else if (ttype == kTransportLocal) {
-                service = "wait-for-local";
-            } else {
-                service = "wait-for-any";
-            }
-        }
 
-        std::string cmd = format_host_command(service, ttype, serial);
-        std::string error;
-        if (adb_command(cmd, &error)) {
-            D("failure: %s *\n", error.c_str());
-            fprintf(stderr,"error: %s\n", error.c_str());
+        if (!wait_for_device(service, transport_type, serial)) {
             return 1;
         }
 
-        /* Allow a command to be run after wait-for-device,
-            * e.g. 'adb wait-for-device shell'.
-            */
+        // Allow a command to be run after wait-for-device,
+        // e.g. 'adb wait-for-device shell'.
         if (argc == 1) {
             return 0;
         }
@@ -1157,11 +1157,12 @@
         }
 
         std::string cmd = "shell:";
-        cmd += argv[1];
-        argc -= 2;
-        argv += 2;
+        --argc;
+        ++argv;
         while (argc-- > 0) {
-            cmd += " " + escape_arg(*argv++);
+            // We don't escape here, just like ssh(1). http://b/20564385.
+            cmd += *argv++;
+            if (*argv) cmd += " ";
         }
 
         while (true) {
@@ -1180,18 +1181,12 @@
                 r = -1;
             }
 
-            if (persist) {
-                fprintf(stderr,"\n- waiting for device -\n");
-                adb_sleep_ms(1000);
-                do_cmd(ttype, serial, "wait-for-device", 0);
-            } else {
-                if (h) {
-                    printf("\x1b[0m");
-                    fflush(stdout);
-                }
-                D("interactive shell loop. return r=%d\n", r);
-                return r;
+            if (h) {
+                printf("\x1b[0m");
+                fflush(stdout);
             }
+            D("interactive shell loop. return r=%d\n", r);
+            return r;
         }
     }
     else if (!strcmp(argv[0], "exec-in") || !strcmp(argv[0], "exec-out")) {
@@ -1259,8 +1254,7 @@
     }
     else if (!strcmp(argv[0], "bugreport")) {
         if (argc != 1) return usage();
-        do_cmd(ttype, serial, "shell", "bugreport", 0);
-        return 0;
+        return send_shell_command(transport_type, serial, "shell:bugreport");
     }
     /* adb_command() wrapper commands */
     else if (!strcmp(argv[0], "forward") || !strcmp(argv[0], "reverse")) {
@@ -1301,9 +1295,9 @@
             if (serial) {
                 snprintf(host_prefix, sizeof host_prefix, "host-serial:%s",
                         serial);
-            } else if (ttype == kTransportUsb) {
+            } else if (transport_type == kTransportUsb) {
                 snprintf(host_prefix, sizeof host_prefix, "host-usb");
-            } else if (ttype == kTransportLocal) {
+            } else if (transport_type == kTransportLocal) {
                 snprintf(host_prefix, sizeof host_prefix, "host-local");
             } else {
                 snprintf(host_prefix, sizeof host_prefix, "host");
@@ -1380,15 +1374,15 @@
     }
     else if (!strcmp(argv[0], "install")) {
         if (argc < 2) return usage();
-        return install_app(ttype, serial, argc, argv);
+        return install_app(transport_type, serial, argc, argv);
     }
     else if (!strcmp(argv[0], "install-multiple")) {
         if (argc < 2) return usage();
-        return install_multiple_app(ttype, serial, argc, argv);
+        return install_multiple_app(transport_type, serial, argc, argv);
     }
     else if (!strcmp(argv[0], "uninstall")) {
         if (argc < 2) return usage();
-        return uninstall_app(ttype, serial, argc, argv);
+        return uninstall_app(transport_type, serial, argc, argv);
     }
     else if (!strcmp(argv[0], "sync")) {
         std::string src;
@@ -1440,11 +1434,11 @@
         !strcmp(argv[0],"get-serialno") ||
         !strcmp(argv[0],"get-devpath"))
     {
-        return adb_query_command(format_host_command(argv[0], ttype, serial));
+        return adb_query_command(format_host_command(argv[0], transport_type, serial));
     }
     /* other commands */
     else if (!strcmp(argv[0],"logcat") || !strcmp(argv[0],"lolcat") || !strcmp(argv[0],"longcat")) {
-        return logcat(ttype, serial, argc, argv);
+        return logcat(transport_type, serial, argc, argv);
     }
     else if (!strcmp(argv[0],"ppp")) {
         return ppp(argc, argv);
@@ -1480,45 +1474,7 @@
     return 1;
 }
 
-#define MAX_ARGV_LENGTH 16
-static int do_cmd(transport_type ttype, const char* serial, const char *cmd, ...)
-{
-    const char *argv[MAX_ARGV_LENGTH];
-    int argc;
-    va_list ap;
-
-    va_start(ap, cmd);
-    argc = 0;
-
-    if (serial) {
-        argv[argc++] = "-s";
-        argv[argc++] = serial;
-    } else if (ttype == kTransportUsb) {
-        argv[argc++] = "-d";
-    } else if (ttype == kTransportLocal) {
-        argv[argc++] = "-e";
-    }
-
-    argv[argc++] = cmd;
-    while(argc < MAX_ARGV_LENGTH &&
-        (argv[argc] = va_arg(ap, char*)) != 0) argc++;
-    assert(argc < MAX_ARGV_LENGTH);
-    va_end(ap);
-
-#if 0
-    int n;
-    fprintf(stderr,"argc = %d\n",argc);
-    for(n = 0; n < argc; n++) {
-        fprintf(stderr,"argv[%d] = \"%s\"\n", n, argv[n]);
-    }
-#endif
-
-    return adb_commandline(argc, argv);
-}
-
-static int pm_command(transport_type transport, const char* serial,
-                      int argc, const char** argv)
-{
+static int pm_command(TransportType transport, const char* serial, int argc, const char** argv) {
     std::string cmd = "shell:pm";
 
     while (argc-- > 0) {
@@ -1528,9 +1484,7 @@
     return send_shell_command(transport, serial, cmd);
 }
 
-static int uninstall_app(transport_type transport, const char* serial, int argc,
-                         const char** argv)
-{
+static int uninstall_app(TransportType transport, const char* serial, int argc, const char** argv) {
     /* if the user choose the -k option, we refuse to do it until devices are
        out with the option to uninstall the remaining data somehow (adb/ui) */
     if (argc == 3 && strcmp(argv[1], "-k") == 0)
@@ -1547,8 +1501,7 @@
     return pm_command(transport, serial, argc, argv);
 }
 
-static int delete_file(transport_type transport, const char* serial, char* filename)
-{
+static int delete_file(TransportType transport, const char* serial, char* filename) {
     std::string cmd = "shell:rm -f " + escape_arg(filename);
     return send_shell_command(transport, serial, cmd);
 }
@@ -1564,9 +1517,7 @@
     }
 }
 
-static int install_app(transport_type transport, const char* serial, int argc,
-                       const char** argv)
-{
+static int install_app(TransportType transport, const char* serial, int argc, const char** argv) {
     static const char *const DATA_DEST = "/data/local/tmp/%s";
     static const char *const SD_DEST = "/sdcard/tmp/%s";
     const char* where = DATA_DEST;
@@ -1618,7 +1569,7 @@
     return err;
 }
 
-static int install_multiple_app(transport_type transport, const char* serial, int argc,
+static int install_multiple_app(TransportType transport, const char* serial, int argc,
                                 const char** argv)
 {
     int i;
diff --git a/adb/file_sync_client.cpp b/adb/file_sync_client.cpp
index aded301..2efc890 100644
--- a/adb/file_sync_client.cpp
+++ b/adb/file_sync_client.cpp
@@ -79,8 +79,7 @@
     fflush(stderr);
 }
 
-void sync_quit(int fd)
-{
+static void sync_quit(int fd) {
     syncmsg msg;
 
     msg.req.id = ID_QUIT;
@@ -91,8 +90,7 @@
 
 typedef void (*sync_ls_cb)(unsigned mode, unsigned size, unsigned time, const char *name, void *cookie);
 
-int sync_ls(int fd, const char *path, sync_ls_cb func, void *cookie)
-{
+static int sync_ls(int fd, const char* path, sync_ls_cb func, void* cookie) {
     syncmsg msg;
     char buf[257];
     int len;
@@ -138,9 +136,7 @@
 
 static syncsendbuf send_buffer;
 
-int sync_readtime(int fd, const char *path, unsigned int *timestamp,
-                  unsigned int *mode)
-{
+static int sync_readtime(int fd, const char* path, unsigned int* timestamp, unsigned int* mode) {
     syncmsg msg;
     int len = strlen(path);
 
@@ -199,8 +195,7 @@
     return 0;
 }
 
-int sync_readmode(int fd, const char *path, unsigned *mode)
-{
+static int sync_readmode(int fd, const char* path, unsigned* mode) {
     syncmsg msg;
     int len = strlen(path);
 
@@ -419,8 +414,7 @@
     return 0;
 }
 
-int sync_recv(int fd, const char *rpath, const char *lpath, int show_progress)
-{
+static int sync_recv(int fd, const char* rpath, const char* lpath, int show_progress) {
     syncmsg msg;
     int len;
     int lfd = -1;
@@ -566,17 +560,14 @@
     int flag;
 };
 
-copyinfo *mkcopyinfo(const char *spath, const char *dpath,
-                     const char *name, int isdir)
-{
+static copyinfo* mkcopyinfo(const char* spath, const char* dpath, const char* name, int isdir) {
     int slen = strlen(spath);
     int dlen = strlen(dpath);
     int nlen = strlen(name);
     int ssize = slen + nlen + 2;
     int dsize = dlen + nlen + 2;
 
-    copyinfo *ci = reinterpret_cast<copyinfo*>(
-        malloc(sizeof(copyinfo) + ssize + dsize));
+    copyinfo *ci = reinterpret_cast<copyinfo*>(malloc(sizeof(copyinfo) + ssize + dsize));
     if(ci == 0) {
         fprintf(stderr,"out of memory\n");
         abort();
@@ -807,9 +798,8 @@
     const char *lpath;
 };
 
-void
-sync_ls_build_list_cb(unsigned mode, unsigned size, unsigned time,
-                      const char *name, void *cookie)
+static void sync_ls_build_list_cb(unsigned mode, unsigned size, unsigned time,
+                                  const char* name, void* cookie)
 {
     sync_ls_build_list_cb_args *args = (sync_ls_build_list_cb_args *)cookie;
     copyinfo *ci;
diff --git a/adb/services.cpp b/adb/services.cpp
index 1847447..e53a28c 100644
--- a/adb/services.cpp
+++ b/adb/services.cpp
@@ -210,8 +210,7 @@
     sti->cookie = cookie;
     sti->fd = s[1];
 
-    adb_thread_t t;
-    if (adb_thread_create(&t, service_bootstrap_func, sti)) {
+    if (!adb_thread_create(service_bootstrap_func, sti)) {
         free(sti);
         adb_close(s[0]);
         adb_close(s[1]);
@@ -378,12 +377,7 @@
     }
 }
 
-static int create_subproc_thread(const char *name, const subproc_mode mode)
-{
-    adb_thread_t t;
-    int ret_fd;
-    pid_t pid = -1;
-
+static int create_subproc_thread(const char *name, bool pty = false) {
     const char *arg0, *arg1;
     if (name == 0 || *name == 0) {
         arg0 = "-"; arg1 = 0;
@@ -391,16 +385,12 @@
         arg0 = "-c"; arg1 = name;
     }
 
-    switch (mode) {
-    case SUBPROC_PTY:
+    pid_t pid = -1;
+    int ret_fd;
+    if (pty) {
         ret_fd = create_subproc_pty(SHELL_COMMAND, arg0, arg1, &pid);
-        break;
-    case SUBPROC_RAW:
+    } else {
         ret_fd = create_subproc_raw(SHELL_COMMAND, arg0, arg1, &pid);
-        break;
-    default:
-        fprintf(stderr, "invalid subproc_mode %d\n", mode);
-        return -1;
     }
     D("create_subproc ret_fd=%d pid=%d\n", ret_fd, pid);
 
@@ -410,7 +400,7 @@
     sti->cookie = (void*) (uintptr_t) pid;
     sti->fd = ret_fd;
 
-    if (adb_thread_create(&t, service_bootstrap_func, sti)) {
+    if (!adb_thread_create(service_bootstrap_func, sti)) {
         free(sti);
         adb_close(ret_fd);
         fprintf(stderr, "cannot create service thread\n");
@@ -462,9 +452,9 @@
     } else if (!strncmp(name, "jdwp:", 5)) {
         ret = create_jdwp_connection_fd(atoi(name+5));
     } else if(!HOST && !strncmp(name, "shell:", 6)) {
-        ret = create_subproc_thread(name + 6, SUBPROC_PTY);
+        ret = create_subproc_thread(name + 6, true);
     } else if(!HOST && !strncmp(name, "exec:", 5)) {
-        ret = create_subproc_thread(name + 5, SUBPROC_RAW);
+        ret = create_subproc_thread(name + 5);
     } else if(!strncmp(name, "sync:", 5)) {
         ret = create_service_thread(file_sync_service, NULL);
     } else if(!strncmp(name, "remount:", 8)) {
@@ -479,9 +469,9 @@
         ret = create_service_thread(restart_unroot_service, NULL);
     } else if(!strncmp(name, "backup:", 7)) {
         ret = create_subproc_thread(android::base::StringPrintf("/system/bin/bu backup %s",
-                                                                (name + 7)).c_str(), SUBPROC_RAW);
+                                                                (name + 7)).c_str());
     } else if(!strncmp(name, "restore:", 8)) {
-        ret = create_subproc_thread("/system/bin/bu restore", SUBPROC_RAW);
+        ret = create_subproc_thread("/system/bin/bu restore");
     } else if(!strncmp(name, "tcpip:", 6)) {
         int port;
         if (sscanf(name + 6, "%d", &port) != 1) {
@@ -514,7 +504,7 @@
 
 #if ADB_HOST
 struct state_info {
-    transport_type transport;
+    TransportType transport_type;
     char* serial;
     int state;
 };
@@ -526,7 +516,8 @@
     D("wait_for_state %d\n", sinfo->state);
 
     std::string error_msg = "unknown error";
-    atransport* t = acquire_one_transport(sinfo->state, sinfo->transport, sinfo->serial, &error_msg);
+    atransport* t = acquire_one_transport(sinfo->state, sinfo->transport_type, sinfo->serial,
+                                          &error_msg);
     if (t != 0) {
         SendOkay(fd);
     } else {
@@ -664,13 +655,13 @@
         name += strlen("wait-for-");
 
         if (!strncmp(name, "local", strlen("local"))) {
-            sinfo->transport = kTransportLocal;
+            sinfo->transport_type = kTransportLocal;
             sinfo->state = CS_DEVICE;
         } else if (!strncmp(name, "usb", strlen("usb"))) {
-            sinfo->transport = kTransportUsb;
+            sinfo->transport_type = kTransportUsb;
             sinfo->state = CS_DEVICE;
         } else if (!strncmp(name, "any", strlen("any"))) {
-            sinfo->transport = kTransportAny;
+            sinfo->transport_type = kTransportAny;
             sinfo->state = CS_DEVICE;
         } else {
             free(sinfo);
diff --git a/adb/sockets.cpp b/adb/sockets.cpp
index 32ca17d..62cba6d 100644
--- a/adb/sockets.cpp
+++ b/adb/sockets.cpp
@@ -691,7 +691,7 @@
 #if ADB_HOST
     char *service = NULL;
     char* serial = NULL;
-    transport_type ttype = kTransportAny;
+    TransportType type = kTransportAny;
 #endif
 
     D("SS(%d): enqueue %d\n", s->id, p->len);
@@ -748,13 +748,13 @@
             service = serial_end + 1;
         }
     } else if (!strncmp(service, "host-usb:", strlen("host-usb:"))) {
-        ttype = kTransportUsb;
+        type = kTransportUsb;
         service += strlen("host-usb:");
     } else if (!strncmp(service, "host-local:", strlen("host-local:"))) {
-        ttype = kTransportLocal;
+        type = kTransportLocal;
         service += strlen("host-local:");
     } else if (!strncmp(service, "host:", strlen("host:"))) {
-        ttype = kTransportAny;
+        type = kTransportAny;
         service += strlen("host:");
     } else {
         service = NULL;
@@ -768,7 +768,7 @@
             ** the OKAY or FAIL message and all we have to do
             ** is clean up.
             */
-        if(handle_host_request(service, ttype, serial, s->peer->fd, s) == 0) {
+        if(handle_host_request(service, type, serial, s->peer->fd, s) == 0) {
                 /* XXX fail message? */
             D( "SS(%d): handled host service '%s'\n", s->id, service );
             goto fail;
diff --git a/adb/sysdeps.h b/adb/sysdeps.h
index 59e5b0b..0aa1570 100644
--- a/adb/sysdeps.h
+++ b/adb/sysdeps.h
@@ -79,19 +79,13 @@
     LeaveCriticalSection( lock );
 }
 
-typedef struct { unsigned  tid; }  adb_thread_t;
-
 typedef  void*  (*adb_thread_func_t)(void*  arg);
 
 typedef  void (*win_thread_func_t)(void*  arg);
 
-static __inline__ int  adb_thread_create( adb_thread_t  *thread, adb_thread_func_t  func, void*  arg)
-{
-    thread->tid = _beginthread( (win_thread_func_t)func, 0, arg );
-    if (thread->tid == (unsigned)-1L) {
-        return -1;
-    }
-    return 0;
+static __inline__ bool adb_thread_create(adb_thread_func_t func, void* arg) {
+    uintptr_t tid = _beginthread((win_thread_func_t)func, 0, arg);
+    return (tid != static_cast<uintptr_t>(-1L));
 }
 
 static __inline__  unsigned long adb_thread_id()
@@ -429,18 +423,16 @@
 #define  unix_write  adb_write
 #define  unix_close  adb_close
 
-typedef  pthread_t                 adb_thread_t;
-
 typedef void*  (*adb_thread_func_t)( void*  arg );
 
-static __inline__ int  adb_thread_create( adb_thread_t  *pthread, adb_thread_func_t  start, void*  arg )
-{
-    pthread_attr_t   attr;
+static __inline__ bool adb_thread_create(adb_thread_func_t start, void* arg) {
+    pthread_attr_t attr;
+    pthread_attr_init(&attr);
+    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
 
-    pthread_attr_init (&attr);
-    pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
-
-    return pthread_create( pthread, &attr, start, arg );
+    pthread_t thread;
+    errno = pthread_create(&thread, &attr, start, arg);
+    return (errno == 0);
 }
 
 static __inline__  int  adb_socket_setbufsize( int   fd, int  bufsize )
diff --git a/adb/tests/test_adb.py b/adb/tests/test_adb.py
index 52d8056..237ef47 100755
--- a/adb/tests/test_adb.py
+++ b/adb/tests/test_adb.py
@@ -272,13 +272,24 @@
         adb = AdbWrapper()
 
         # http://b/19734868
+        # Note that this actually matches ssh(1)'s behavior --- it's
+        # converted to "sh -c echo hello; echo world" which sh interprets
+        # as "sh -c echo" (with an argument to that shell of "hello"),
+        # and then "echo world" back in the first shell.
         result = adb.shell("sh -c 'echo hello; echo world'").splitlines()
+        self.assertEqual(["", "world"], result)
+        # If you really wanted "hello" and "world", here's what you'd do:
+        result = adb.shell("echo hello\;echo world").splitlines()
         self.assertEqual(["hello", "world"], result)
 
         # http://b/15479704
         self.assertEqual('t', adb.shell("'true && echo t'").strip())
         self.assertEqual('t', adb.shell("sh -c 'true && echo t'").strip())
 
+        # http://b/20564385
+        self.assertEqual('t', adb.shell("FOO=a BAR=b echo t").strip())
+        self.assertEqual('123Linux', adb.shell("echo -n 123\;uname").strip())
+
 
 class AdbFile(unittest.TestCase):
     SCRATCH_DIR = "/data/local/tmp"
diff --git a/adb/transport.cpp b/adb/transport.cpp
index 5c50c0a..bb5be6b 100644
--- a/adb/transport.cpp
+++ b/adb/transport.cpp
@@ -530,8 +530,6 @@
 static void transport_registration_func(int _fd, unsigned ev, void *data)
 {
     tmsg m;
-    adb_thread_t output_thread_ptr;
-    adb_thread_t input_thread_ptr;
     int s[2];
     atransport *t;
 
@@ -600,11 +598,11 @@
 
         fdevent_set(&(t->transport_fde), FDE_READ);
 
-        if(adb_thread_create(&input_thread_ptr, input_thread, t)){
+        if (!adb_thread_create(input_thread, t)) {
             fatal_errno("cannot create input thread");
         }
 
-        if(adb_thread_create(&output_thread_ptr, output_thread, t)){
+        if (!adb_thread_create(output_thread, t)) {
             fatal_errno("cannot create output thread");
         }
     }
@@ -740,7 +738,7 @@
     return !*to_test;
 }
 
-atransport* acquire_one_transport(int state, transport_type ttype,
+atransport* acquire_one_transport(int state, TransportType type,
                                   const char* serial, std::string* error_out)
 {
     atransport *t;
@@ -773,7 +771,7 @@
                 result = t;
             }
         } else {
-            if (ttype == kTransportUsb && t->type == kTransportUsb) {
+            if (type == kTransportUsb && t->type == kTransportUsb) {
                 if (result) {
                     if (error_out) *error_out = "more than one device";
                     ambiguous = 1;
@@ -781,7 +779,7 @@
                     break;
                 }
                 result = t;
-            } else if (ttype == kTransportLocal && t->type == kTransportLocal) {
+            } else if (type == kTransportLocal && t->type == kTransportLocal) {
                 if (result) {
                     if (error_out) *error_out = "more than one emulator";
                     ambiguous = 1;
@@ -789,7 +787,7 @@
                     break;
                 }
                 result = t;
-            } else if (ttype == kTransportAny) {
+            } else if (type == kTransportAny) {
                 if (result) {
                     if (error_out) *error_out = "more than one device/emulator";
                     ambiguous = 1;
diff --git a/adb/transport.h b/adb/transport.h
index 5b6fdac..7b799b9 100644
--- a/adb/transport.h
+++ b/adb/transport.h
@@ -29,7 +29,7 @@
  * If serial is non-NULL then only the device with that serial will be chosen.
  * If no suitable transport is found, error is set.
  */
-atransport* acquire_one_transport(int state, transport_type ttype,
+atransport* acquire_one_transport(int state, TransportType type,
                                   const char* serial, std::string* error_out);
 void add_transport_disconnect(atransport* t, adisconnect* dis);
 void remove_transport_disconnect(atransport* t, adisconnect* dis);
diff --git a/adb/transport_local.cpp b/adb/transport_local.cpp
index b1deffd..5f7449d 100644
--- a/adb/transport_local.cpp
+++ b/adb/transport_local.cpp
@@ -234,9 +234,8 @@
     if (fd < 0) {
         /* This could be an older version of the emulator, that doesn't
          * implement adb QEMUD service. Fall back to the old TCP way. */
-        adb_thread_t thr;
         D("adb service is not available. Falling back to TCP socket.\n");
-        adb_thread_create(&thr, server_socket_thread, arg);
+        adb_thread_create(server_socket_thread, arg);
         return 0;
     }
 
@@ -279,7 +278,6 @@
 
 void local_init(int port)
 {
-    adb_thread_t thr;
     void* (*func)(void *);
 
     if(HOST) {
@@ -304,9 +302,8 @@
 
     D("transport: local %s init\n", HOST ? "client" : "server");
 
-    if(adb_thread_create(&thr, func, (void *) (uintptr_t) port)) {
-        fatal_errno("cannot create local socket %s thread",
-                    HOST ? "client" : "server");
+    if (!adb_thread_create(func, (void *) (uintptr_t) port)) {
+        fatal_errno("cannot create local socket %s thread", HOST ? "client" : "server");
     }
 }
 
diff --git a/adb/usb_linux.cpp b/adb/usb_linux.cpp
index 999eb11..b61bf71 100644
--- a/adb/usb_linux.cpp
+++ b/adb/usb_linux.cpp
@@ -668,7 +668,6 @@
 
 void usb_init()
 {
-    adb_thread_t tid;
     struct sigaction    actions;
 
     memset(&actions, 0, sizeof(actions));
@@ -677,7 +676,7 @@
     actions.sa_handler = sigalrm_handler;
     sigaction(SIGALRM,& actions, NULL);
 
-    if(adb_thread_create(&tid, device_poll_thread, NULL)){
+    if (!adb_thread_create(device_poll_thread, nullptr)) {
         fatal_errno("cannot create input thread");
     }
 }
diff --git a/adb/usb_linux_client.cpp b/adb/usb_linux_client.cpp
index 18289e2..1d6ed94 100644
--- a/adb/usb_linux_client.cpp
+++ b/adb/usb_linux_client.cpp
@@ -82,7 +82,7 @@
     struct func_desc fs_descs, hs_descs;
 } __attribute__((packed));
 
-struct func_desc fs_descriptors = {
+static struct func_desc fs_descriptors = {
     .intf = {
         .bLength = sizeof(fs_descriptors.intf),
         .bDescriptorType = USB_DT_INTERFACE,
@@ -109,7 +109,7 @@
     },
 };
 
-struct func_desc hs_descriptors = {
+static struct func_desc hs_descriptors = {
     .intf = {
         .bLength = sizeof(hs_descriptors.intf),
         .bDescriptorType = USB_DT_INTERFACE,
@@ -264,8 +264,7 @@
     }
 
     D("[ usb_init - starting thread ]\n");
-    adb_thread_t tid;
-    if(adb_thread_create(&tid, usb_adb_open_thread, h)){
+    if (!adb_thread_create(usb_adb_open_thread, h)) {
         fatal_errno("cannot create usb thread");
     }
 }
@@ -483,8 +482,7 @@
     adb_mutex_init(&h->lock, 0);
 
     D("[ usb_init - starting thread ]\n");
-    adb_thread_t tid;
-    if (adb_thread_create(&tid, usb_ffs_open_thread, h)){
+    if (!adb_thread_create(usb_ffs_open_thread, h)) {
         fatal_errno("[ cannot create usb thread ]\n");
     }
 }
diff --git a/adb/usb_osx.cpp b/adb/usb_osx.cpp
index a795ce3..0d0b3ad 100644
--- a/adb/usb_osx.cpp
+++ b/adb/usb_osx.cpp
@@ -398,22 +398,20 @@
     IONotificationPortDestroy(notificationPort);
 
     DBG("RunLoopThread done\n");
-    return NULL;    
+    return NULL;
 }
 
 
 static int initialized = 0;
-void usb_init()
-{
+void usb_init() {
     if (!initialized)
     {
-        adb_thread_t    tid;
-
         adb_mutex_init(&start_lock, NULL);
         adb_cond_init(&start_cond, NULL);
 
-        if(adb_thread_create(&tid, RunLoopThread, NULL))
+        if (!adb_thread_create(RunLoopThread, nullptr)) {
             fatal_errno("cannot create input thread");
+        }
 
         // Wait for initialization to finish
         adb_mutex_lock(&start_lock);
diff --git a/adb/usb_windows.cpp b/adb/usb_windows.cpp
index d2bd58c..1d6ec8c 100644
--- a/adb/usb_windows.cpp
+++ b/adb/usb_windows.cpp
@@ -181,9 +181,7 @@
 }
 
 void usb_init() {
-  adb_thread_t tid;
-
-  if(adb_thread_create(&tid, device_poll_thread, NULL)) {
+  if (!adb_thread_create(device_poll_thread, nullptr)) {
     fatal_errno("cannot create input thread");
   }
 }
diff --git a/debuggerd/tombstone.cpp b/debuggerd/tombstone.cpp
index 81da16d..56c03f7 100644
--- a/debuggerd/tombstone.cpp
+++ b/debuggerd/tombstone.cpp
@@ -795,7 +795,7 @@
   *detach_failed = dump_crash(&log, pid, tid, signal, original_si_code, abort_msg_address,
                               dump_sibling_threads, total_sleep_time_usec);
 
-  ALOGI("\nTombstone written to: %s\n", path);
+  _LOG(&log, logtype::BACKTRACE, "\nTombstone written to: %s\n", path);
 
   // Either of these file descriptors can be -1, any error is ignored.
   close(amfd);
diff --git a/debuggerd/utility.cpp b/debuggerd/utility.cpp
index d6a6d2e..e722f82 100644
--- a/debuggerd/utility.cpp
+++ b/debuggerd/utility.cpp
@@ -67,7 +67,7 @@
   }
 
   if (write_to_logcat) {
-    __android_log_buf_write(LOG_ID_CRASH, ANDROID_LOG_INFO, LOG_TAG, buf);
+    __android_log_buf_write(LOG_ID_CRASH, ANDROID_LOG_FATAL, LOG_TAG, buf);
     if (write_to_activitymanager) {
       if (!android::base::WriteFully(log->amfd, buf, len)) {
         // timeout or other failure on write; stop informing the activity manager
diff --git a/rootdir/Android.mk b/rootdir/Android.mk
index 3ecb1db..7ab76b8 100644
--- a/rootdir/Android.mk
+++ b/rootdir/Android.mk
@@ -26,7 +26,7 @@
 #
 # create some directories (some are mount points)
 LOCAL_POST_INSTALL_CMD := mkdir -p $(addprefix $(TARGET_ROOT_OUT)/, \
-    sbin dev proc sys system data)
+    sbin dev proc sys system data oem)
 
 include $(BUILD_SYSTEM)/base_rules.mk