Merge "Print strerror instead of errno in tests."
diff --git a/adb/adb_client.cpp b/adb/adb_client.cpp
index 0f64998..0b2d038 100644
--- a/adb/adb_client.cpp
+++ b/adb/adb_client.cpp
@@ -29,6 +29,9 @@
 #include <sys/types.h>
 
 #include <string>
+#include <vector>
+
+#include <base/stringprintf.h>
 
 #include "adb_io.h"
 
@@ -63,10 +66,11 @@
         /* if no specific device was specified, we need to look at */
         /* the list of connected devices, and extract an emulator  */
         /* name from it. two emulators is an error                 */
-        char*  tmp = adb_query("host:devices");
+        std::string error;
+        char*  tmp = adb_query("host:devices", &error);
         char*  p   = tmp;
-        if(!tmp) {
-            printf("no emulator connected\n");
+        if (!tmp) {
+            printf("no emulator connected: %s\n", error.c_str());
             return -1;
         }
         while (*p) {
@@ -101,15 +105,11 @@
     return port;
 }
 
-static char __adb_error[256] = { 0 };
-
-const char *adb_error(void)
-{
-    return __adb_error;
+std::string perror_str(const char* msg) {
+    return android::base::StringPrintf("%s: %s", msg, strerror(errno));
 }
 
-static int switch_socket_transport(int fd)
-{
+static int switch_socket_transport(int fd, std::string* error) {
     std::string service;
     if (__adb_serial) {
         service += "host:transport:";
@@ -137,70 +137,64 @@
     char tmp[5];
     snprintf(tmp, sizeof(tmp), "%04zx", service.size());
     if (!WriteFdExactly(fd, tmp, 4) || !WriteFdExactly(fd, service.c_str(), service.size())) {
-        strcpy(__adb_error, "write failure during connection");
+        *error = perror_str("write failure during connection");
         adb_close(fd);
         return -1;
     }
     D("Switch transport in progress\n");
 
-    if (adb_status(fd)) {
+    if (!adb_status(fd, error)) {
         adb_close(fd);
-        D("Switch transport failed\n");
+        D("Switch transport failed: %s\n", error->c_str());
         return -1;
     }
     D("Switch transport success\n");
     return 0;
 }
 
-int adb_status(int fd)
-{
-    unsigned char buf[5];
-    unsigned len;
+bool adb_status(int fd, std::string* error) {
+    char buf[5];
 
-    if(!ReadFdExactly(fd, buf, 4)) {
-        strcpy(__adb_error, "protocol fault (no status)");
-        return -1;
+    if (!ReadFdExactly(fd, buf, 4)) {
+        *error = perror_str("protocol fault (couldn't read status)");
+        return false;
     }
 
-    if(!memcmp(buf, "OKAY", 4)) {
-        return 0;
+    if (!memcmp(buf, "OKAY", 4)) {
+        return true;
     }
 
-    if(memcmp(buf, "FAIL", 4)) {
-        sprintf(__adb_error,
-                "protocol fault (status %02x %02x %02x %02x?!)",
-                buf[0], buf[1], buf[2], buf[3]);
-        return -1;
+    if (memcmp(buf, "FAIL", 4)) {
+        *error = android::base::StringPrintf("protocol fault (status %02x %02x %02x %02x?!)",
+                                             buf[0], buf[1], buf[2], buf[3]);
+        return false;
     }
 
-    if(!ReadFdExactly(fd, buf, 4)) {
-        strcpy(__adb_error, "protocol fault (status len)");
-        return -1;
+    if (!ReadFdExactly(fd, buf, 4)) {
+        *error = perror_str("protocol fault (couldn't read status length)");
+        return false;
     }
     buf[4] = 0;
-    len = strtoul((char*)buf, 0, 16);
-    if(len > 255) len = 255;
-    if(!ReadFdExactly(fd, __adb_error, len)) {
-        strcpy(__adb_error, "protocol fault (status read)");
-        return -1;
+
+    unsigned long len = strtoul(buf, 0, 16);
+    error->resize(len + 1, '\0'); // Ensure NUL-termination.
+    if (!ReadFdExactly(fd, &(*error)[0], len)) {
+        *error = perror_str("protocol fault (couldn't read status message)");
     }
-    __adb_error[len] = 0;
-    return -1;
+    return false;
 }
 
-int _adb_connect(const char *service)
-{
+int _adb_connect(const char *service, std::string* error) {
     char tmp[5];
-    int len;
     int fd;
 
     D("_adb_connect: %s\n", service);
-    len = strlen(service);
-    if((len < 1) || (len > 1024)) {
-        strcpy(__adb_error, "service name too long");
+    size_t len = strlen(service);
+    if ((len < 1) || (len > 1024)) {
+        *error = android::base::StringPrintf("service name too long (%d)", static_cast<int>(len));
         return -1;
     }
-    snprintf(tmp, sizeof tmp, "%04x", len);
+    snprintf(tmp, sizeof tmp, "%04zx", len);
 
     if (__adb_server_name)
         fd = socket_network_client(__adb_server_name, __adb_server_port, SOCK_STREAM);
@@ -208,21 +202,21 @@
         fd = socket_loopback_client(__adb_server_port, SOCK_STREAM);
 
     if(fd < 0) {
-        strcpy(__adb_error, "cannot connect to daemon");
+        *error = perror_str("cannot connect to daemon");
         return -2;
     }
 
-    if (memcmp(service,"host",4) != 0 && switch_socket_transport(fd)) {
+    if (memcmp(service,"host",4) != 0 && switch_socket_transport(fd, error)) {
         return -1;
     }
 
     if(!WriteFdExactly(fd, tmp, 4) || !WriteFdExactly(fd, service, len)) {
-        strcpy(__adb_error, "write failure during connection");
+        *error = perror_str("write failure during connection");
         adb_close(fd);
         return -1;
     }
 
-    if(adb_status(fd)) {
+    if (!adb_status(fd, error)) {
         adb_close(fd);
         return -1;
     }
@@ -231,20 +225,19 @@
     return fd;
 }
 
-int adb_connect(const char *service)
-{
+int adb_connect(const char* service, std::string* error) {
     // first query the adb server's version
-    int fd = _adb_connect("host:version");
+    int fd = _adb_connect("host:version", error);
 
     D("adb_connect: service %s\n", service);
-    if(fd == -2 && __adb_server_name) {
+    if (fd == -2 && __adb_server_name) {
         fprintf(stderr,"** Cannot start server on remote host\n");
         return fd;
-    } else if(fd == -2) {
+    } else if (fd == -2) {
         fprintf(stdout,"* daemon not running. starting it now on port %d *\n",
                 __adb_server_port);
     start_server:
-        if(launch_server(__adb_server_port)) {
+        if (launch_server(__adb_server_port)) {
             fprintf(stderr,"* failed to start daemon *\n");
             return -1;
         } else {
@@ -260,7 +253,7 @@
         int version = ADB_SERVER_VERSION - 1;
 
         // if we have a file descriptor, then parse version result
-        if(fd >= 0) {
+        if (fd >= 0) {
             if(!ReadFdExactly(fd, buf, 4)) goto error;
 
             buf[4] = 0;
@@ -273,13 +266,14 @@
         } else {
             // if fd is -1, then check for "unknown host service",
             // which would indicate a version of adb that does not support the version command
-            if (strcmp(__adb_error, "unknown host service") != 0)
+            if (*error == "unknown host service") {
                 return fd;
+            }
         }
 
         if(version != ADB_SERVER_VERSION) {
             printf("adb server is out of date.  killing...\n");
-            fd = _adb_connect("host:kill");
+            fd = _adb_connect("host:kill", error);
             adb_close(fd);
 
             /* XXX can we better detect its death? */
@@ -289,12 +283,13 @@
     }
 
     // if the command is start-server, we are done.
-    if (!strcmp(service, "host:start-server"))
+    if (!strcmp(service, "host:start-server")) {
         return 0;
+    }
 
-    fd = _adb_connect(service);
-    if(fd == -1) {
-        D("_adb_connect error: %s", __adb_error);
+    fd = _adb_connect(service, error);
+    if (fd == -1) {
+        D("_adb_connect error: %s", error->c_str());
     } else if(fd == -2) {
         fprintf(stderr,"** daemon still not running\n");
     }
@@ -307,15 +302,14 @@
 }
 
 
-int adb_command(const char *service)
-{
-    int fd = adb_connect(service);
-    if(fd < 0) {
-        fprintf(stderr, "error: %s\n", adb_error());
+int adb_command(const char* service, std::string* error) {
+    int fd = adb_connect(service, error);
+    if (fd < 0) {
+        fprintf(stderr, "error: %s\n", error->c_str());
         return -1;
     }
 
-    if(adb_status(fd)) {
+    if (!adb_status(fd, error)) {
         adb_close(fd);
         return -1;
     }
@@ -323,25 +317,25 @@
     return 0;
 }
 
-char *adb_query(const char *service)
-{
+char* adb_query(const char* service, std::string* error) {
     char buf[5];
     unsigned long n;
     char* tmp;
 
     D("adb_query: %s\n", service);
-    int fd = adb_connect(service);
-    if(fd < 0) {
-        fprintf(stderr,"error: %s\n", __adb_error);
+    int fd = adb_connect(service, error);
+    if (fd < 0) {
+        fprintf(stderr,"error: %s\n", error->c_str());
         return 0;
     }
 
-    if(!ReadFdExactly(fd, buf, 4)) goto oops;
+    if (!ReadFdExactly(fd, buf, 4)) goto oops;
 
     buf[4] = 0;
     n = strtoul(buf, 0, 16);
-    if(n >= 0xffff) {
-        strcpy(__adb_error, "reply is too long (>= 64kB)");
+    // TODO: given that we just read a 4-byte hex length 0x????, why the test?
+    if (n >= 0xffff) {
+        *error = "reply is too long (>= 64KiB)";
         goto oops;
     }
 
diff --git a/adb/adb_client.h b/adb/adb_client.h
index 934362a..5ce7080 100644
--- a/adb/adb_client.h
+++ b/adb/adb_client.h
@@ -3,23 +3,25 @@
 
 #include "adb.h"
 
+#include <string>
+
 /* connect to adb, connect to the named service, and return
 ** a valid fd for interacting with that service upon success
 ** or a negative number on failure
 */
-int adb_connect(const char *service);
-int _adb_connect(const char *service);
+int adb_connect(const char* service, std::string* error);
+int _adb_connect(const char* service, std::string* error);
 
 /* connect to adb, connect to the named service, return 0 if
 ** the connection succeeded AND the service returned OKAY
 */
-int adb_command(const char *service);
+int adb_command(const char* service, std::string* error);
 
 /* connect to adb, connect to the named service, return
 ** a malloc'd string of its response upon success or NULL
 ** on failure.
 */
-char *adb_query(const char *service);
+char* adb_query(const char* service, std::string* error);
 
 /* Set the preferred transport to connect to.
 */
@@ -45,13 +47,9 @@
  */
 int  adb_send_emulator_command(int  argc, const char**  argv);
 
-/* return verbose error string from last operation */
-const char *adb_error(void);
-
-/* read a standard adb status response (OKAY|FAIL) and
-** return 0 in the event of OKAY, -1 in the event of FAIL
-** or protocol error
-*/
-int adb_status(int fd);
+// Reads a standard adb status response (OKAY|FAIL) and
+// returns true in the event of OKAY, false in the event of FAIL
+// or protocol error.
+bool adb_status(int fd, std::string* error);
 
 #endif
diff --git a/adb/commandline.cpp b/adb/commandline.cpp
index e59a96a..b5015ea 100644
--- a/adb/commandline.cpp
+++ b/adb/commandline.cpp
@@ -410,11 +410,12 @@
 
 static int interactive_shell() {
     adb_thread_t thr;
-    int fdi, fd;
+    int fdi;
 
-    fd = adb_connect("shell:");
-    if(fd < 0) {
-        fprintf(stderr,"error: %s\n", adb_error());
+    std::string error;
+    int fd = adb_connect("shell:", &error);
+    if (fd < 0) {
+        fprintf(stderr,"error: %s\n", error.c_str());
         return 1;
     }
     fdi = 0; //dup(0);
@@ -452,16 +453,17 @@
 }
 
 static int adb_download_buffer(const char *service, const char *fn, const void* data, int sz,
-                               unsigned progress)
+                               bool show_progress)
 {
     char buf[4096];
     unsigned total;
-    int fd;
 
     sprintf(buf,"%s:%d", service, sz);
-    fd = adb_connect(buf);
-    if(fd < 0) {
-        fprintf(stderr,"error: %s\n", adb_error());
+
+    std::string error;
+    int fd = adb_connect(buf, &error);
+    if (fd < 0) {
+        fprintf(stderr,"error: %s\n", error.c_str());
         return -1;
     }
 
@@ -471,26 +473,27 @@
     total = sz;
     const uint8_t* ptr = reinterpret_cast<const uint8_t*>(data);
 
-    if(progress) {
+    if (show_progress) {
         char *x = strrchr(service, ':');
         if(x) service = x + 1;
     }
 
     while(sz > 0) {
         unsigned xfer = (sz > CHUNK_SIZE) ? CHUNK_SIZE : sz;
-        if(!WriteFdExactly(fd, ptr, xfer)) {
-            adb_status(fd);
-            fprintf(stderr,"* failed to write data '%s' *\n", adb_error());
+        if (!WriteFdExactly(fd, ptr, xfer)) {
+            std::string error;
+            adb_status(fd, &error);
+            fprintf(stderr,"* failed to write data '%s' *\n", error.c_str());
             return -1;
         }
         sz -= xfer;
         ptr += xfer;
-        if(progress) {
+        if (show_progress) {
             printf("sending: '%s' %4d%%    \r", fn, (int)(100LL - ((100LL * sz) / (total))));
             fflush(stdout);
         }
     }
-    if(progress) {
+    if (show_progress) {
         printf("\n");
     }
 
@@ -549,12 +552,13 @@
 
     char buf[100];
     sprintf(buf, "sideload-host:%d:%d", sz, SIDELOAD_HOST_BLOCK_SIZE);
-    int fd = adb_connect(buf);
+    std::string error;
+    int fd = adb_connect(buf, &error);
     if (fd < 0) {
         // Try falling back to the older sideload method.  Maybe this
         // is an older device that doesn't support sideload-host.
         printf("\n");
-        status = adb_download_buffer("sideload", fn, data, sz, 1);
+        status = adb_download_buffer("sideload", fn, data, sz, true);
         goto done;
     }
 
@@ -562,7 +566,7 @@
 
     while (true) {
         if (!ReadFdExactly(fd, buf, 8)) {
-            fprintf(stderr, "* failed to read command: %s\n", adb_error());
+            fprintf(stderr, "* failed to read command: %s\n", strerror(errno));
             status = -1;
             goto done;
         }
@@ -577,7 +581,7 @@
 
         size_t offset = block * SIDELOAD_HOST_BLOCK_SIZE;
         if (offset >= sz) {
-            fprintf(stderr, "* attempt to read past end: %s\n", adb_error());
+            fprintf(stderr, "* attempt to read block %d past end\n", block);
             status = -1;
             goto done;
         }
@@ -589,8 +593,8 @@
         }
 
         if(!WriteFdExactly(fd, start, to_write)) {
-            adb_status(fd);
-            fprintf(stderr,"* failed to write data '%s' *\n", adb_error());
+            adb_status(fd, &error);
+            fprintf(stderr,"* failed to write data '%s' *\n", error.c_str());
             status = -1;
             goto done;
         }
@@ -636,21 +640,22 @@
 
     format_host_command(command, sizeof command, "get-state", ttype, serial);
 
-    for(;;) {
+    while (true) {
         adb_sleep_ms(250);
 
-        if(state) {
+        if (state) {
             free(state);
             state = 0;
         }
 
-        state = adb_query(command);
+        std::string error;
+        state = adb_query(command, &error);
 
-        if(state) {
-            if(laststate && !strcmp(state,laststate)){
+        if (state) {
+            if (laststate && !strcmp(state,laststate)){
                 continue;
             } else {
-                if(laststate) free(laststate);
+                if (laststate) free(laststate);
                 laststate = strdup(state);
             }
         }
@@ -674,9 +679,6 @@
     fprintf(stderr, "error: adb %s not implemented on Win32\n", argv[0]);
     return -1;
 #else
-    pid_t pid;
-    int fd;
-
     if (argc < 2) {
         fprintf(stderr, "usage: adb %s <adb service name> [ppp opts]\n",
                 argv[0]);
@@ -685,15 +687,15 @@
     }
 
     const char* adb_service_name = argv[1];
-    fd = adb_connect(adb_service_name);
-
-    if(fd < 0) {
+    std::string error;
+    int fd = adb_connect(adb_service_name, &error);
+    if (fd < 0) {
         fprintf(stderr,"Error: Could not open adb service: %s. Error: %s\n",
-                adb_service_name, adb_error());
+                adb_service_name, error.c_str());
         return 1;
     }
 
-    pid = fork();
+    pid_t pid = fork();
 
     if (pid < 0) {
         perror("from fork()");
@@ -738,9 +740,11 @@
                               const std::string& command) {
     int fd;
     while (true) {
-        fd = adb_connect(command.c_str());
-        if (fd >= 0)
+        std::string error;
+        fd = adb_connect(command.c_str(), &error);
+        if (fd >= 0) {
             break;
+        }
         fprintf(stderr,"- waiting for device -\n");
         adb_sleep_ms(1000);
         do_cmd(transport, serial, "wait-for-device", 0);
@@ -830,9 +834,10 @@
     }
 
     D("backup. filename=%s cmd=%s\n", filename, cmd.c_str());
-    int fd = adb_connect(cmd.c_str());
+    std::string error;
+    int fd = adb_connect(cmd.c_str(), &error);
     if (fd < 0) {
-        fprintf(stderr, "adb: unable to connect for backup\n");
+        fprintf(stderr, "adb: unable to connect for backup: %s\n", error.c_str());
         adb_close(outFd);
         return -1;
     }
@@ -846,21 +851,19 @@
 }
 
 static int restore(int argc, const char** argv) {
-    const char* filename;
-    int fd, tarFd;
-
     if (argc != 2) return usage();
 
-    filename = argv[1];
-    tarFd = adb_open(filename, O_RDONLY);
+    const char* filename = argv[1];
+    int tarFd = adb_open(filename, O_RDONLY);
     if (tarFd < 0) {
-        fprintf(stderr, "adb: unable to open file %s\n", filename);
+        fprintf(stderr, "adb: unable to open file %s: %s\n", filename, strerror(errno));
         return -1;
     }
 
-    fd = adb_connect("restore:");
+    std::string error;
+    int fd = adb_connect("restore:", &error);
     if (fd < 0) {
-        fprintf(stderr, "adb: unable to connect for restore\n");
+        fprintf(stderr, "adb: unable to connect for restore: %s\n", error.c_str());
         adb_close(tarFd);
         return -1;
     }
@@ -962,13 +965,14 @@
 }
 
 static int adb_connect_command(const char* command) {
-    int fd = adb_connect(command);
+    std::string error;
+    int fd = adb_connect(command, &error);
     if (fd != -1) {
         read_and_dump(fd);
         adb_close(fd);
         return 0;
     }
-    fprintf(stderr, "Error: %s\n", adb_error());
+    fprintf(stderr, "Error: %s\n", error.c_str());
     return 1;
 }
 
@@ -1127,9 +1131,10 @@
 
         format_host_command(buf, sizeof buf, service, ttype, serial);
 
-        if (adb_command(buf)) {
-            D("failure: %s *\n",adb_error());
-            fprintf(stderr,"error: %s\n", adb_error());
+        std::string error;
+        if (adb_command(buf, &error)) {
+            D("failure: %s *\n", error.c_str());
+            fprintf(stderr,"error: %s\n", error.c_str());
             return 1;
         }
 
@@ -1158,7 +1163,8 @@
             return 1;
         }
         snprintf(buf, sizeof buf, "host:%s%s", argv[0], listopt);
-        tmp = adb_query(buf);
+        std::string error;
+        tmp = adb_query(buf, &error);
         if (tmp) {
             printf("List of devices attached \n");
             printf("%s\n", tmp);
@@ -1174,7 +1180,8 @@
             return 1;
         }
         snprintf(buf, sizeof buf, "host:connect:%s", argv[1]);
-        tmp = adb_query(buf);
+        std::string error;
+        tmp = adb_query(buf, &error);
         if (tmp) {
             printf("%s\n", tmp);
             return 0;
@@ -1193,7 +1200,8 @@
         } else {
             snprintf(buf, sizeof buf, "host:disconnect:");
         }
-        tmp = adb_query(buf);
+        std::string error;
+        tmp = adb_query(buf, &error);
         if (tmp) {
             printf("%s\n", tmp);
             return 0;
@@ -1232,7 +1240,8 @@
 
         while (true) {
             D("interactive shell loop. cmd=%s\n", cmd.c_str());
-            int fd = adb_connect(cmd.c_str());
+            std::string error;
+            int fd = adb_connect(cmd.c_str(), &error);
             int r;
             if (fd >= 0) {
                 D("about to read_and_dump(fd=%d)\n", fd);
@@ -1241,7 +1250,7 @@
                 adb_close(fd);
                 r = 0;
             } else {
-                fprintf(stderr,"error: %s\n", adb_error());
+                fprintf(stderr,"error: %s\n", error.c_str());
                 r = -1;
             }
 
@@ -1270,9 +1279,10 @@
             cmd += " " + escape_arg(*argv++);
         }
 
-        int fd = adb_connect(cmd.c_str());
+        std::string error;
+        int fd = adb_connect(cmd.c_str(), &error);
         if (fd < 0) {
-            fprintf(stderr, "error: %s\n", adb_error());
+            fprintf(stderr, "error: %s\n", error.c_str());
             return -1;
         }
 
@@ -1286,8 +1296,8 @@
         return 0;
     }
     else if (!strcmp(argv[0], "kill-server")) {
-        int fd;
-        fd = _adb_connect("host:kill");
+        std::string error;
+        int fd = _adb_connect("host:kill", &error);
         if (fd == -1) {
             fprintf(stderr,"* server not running *\n");
             return 1;
@@ -1378,9 +1388,10 @@
             if (argc != 1)
                 return usage();
             snprintf(buf, sizeof buf, "%s:list-forward", host_prefix);
-            char* forwards = adb_query(buf);
+            std::string error;
+            char* forwards = adb_query(buf, &error);
             if (forwards == NULL) {
-                fprintf(stderr, "error: %s\n", adb_error());
+                fprintf(stderr, "error: %s\n", error.c_str());
                 return 1;
             }
             printf("%s", forwards);
@@ -1412,8 +1423,9 @@
           snprintf(buf, sizeof buf, "%s:%s:%s;%s", host_prefix, command, argv[1], argv[2]);
         }
 
-        if (adb_command(buf)) {
-            fprintf(stderr,"error: %s\n", adb_error());
+        std::string error;
+        if (adb_command(buf, &error)) {
+            fprintf(stderr,"error: %s\n", error.c_str());
             return 1;
         }
         return 0;
@@ -1511,10 +1523,9 @@
         !strcmp(argv[0],"get-serialno") ||
         !strcmp(argv[0],"get-devpath"))
     {
-        char *tmp;
-
         format_host_command(buf, sizeof buf, argv[0], ttype, serial);
-        tmp = adb_query(buf);
+        std::string error;
+        char* tmp = adb_query(buf, &error);
         if (tmp) {
             printf("%s\n", tmp);
             return 0;
@@ -1534,7 +1545,8 @@
         return ppp(argc, argv);
     }
     else if (!strcmp(argv[0], "start-server")) {
-        return adb_connect("host:start-server");
+        std::string error;
+        return adb_connect("host:start-server", &error);
     }
     else if (!strcmp(argv[0], "backup")) {
         return backup(argc, argv);
@@ -1742,9 +1754,10 @@
     }
 
     // Create install session
-    int fd = adb_connect(cmd.c_str());
+    std::string error;
+    int fd = adb_connect(cmd.c_str(), &error);
     if (fd < 0) {
-        fprintf(stderr, "Connect error for create: %s\n", adb_error());
+        fprintf(stderr, "Connect error for create: %s\n", error.c_str());
         return -1;
     }
     char buf[BUFSIZ];
@@ -1788,14 +1801,15 @@
 
         int localFd = adb_open(file, O_RDONLY);
         if (localFd < 0) {
-            fprintf(stderr, "Failed to open %s: %s\n", file, adb_error());
+            fprintf(stderr, "Failed to open %s: %s\n", file, strerror(errno));
             success = 0;
             goto finalize_session;
         }
 
-        int remoteFd = adb_connect(cmd.c_str());
+        std::string error;
+        int remoteFd = adb_connect(cmd.c_str(), &error);
         if (remoteFd < 0) {
-            fprintf(stderr, "Connect error for write: %s\n", adb_error());
+            fprintf(stderr, "Connect error for write: %s\n", error.c_str());
             adb_close(localFd);
             success = 0;
             goto finalize_session;
@@ -1823,9 +1837,9 @@
         snprintf(buf, sizeof(buf), "exec:pm install-abandon %d", session_id);
     }
 
-    fd = adb_connect(buf);
+    fd = adb_connect(buf, &error);
     if (fd < 0) {
-        fprintf(stderr, "Connect error for finalize: %s\n", adb_error());
+        fprintf(stderr, "Connect error for finalize: %s\n", error.c_str());
         return -1;
     }
     read_status_line(fd, buf, sizeof(buf));
diff --git a/adb/file_sync_client.cpp b/adb/file_sync_client.cpp
index 49d8783..aded301 100644
--- a/adb/file_sync_client.cpp
+++ b/adb/file_sync_client.cpp
@@ -539,11 +539,11 @@
     printf("%08x %08x %08x %s\n", mode, size, time, name);
 }
 
-int do_sync_ls(const char *path)
-{
-    int fd = adb_connect("sync:");
-    if(fd < 0) {
-        fprintf(stderr,"error: %s\n", adb_error());
+int do_sync_ls(const char* path) {
+    std::string error;
+    int fd = adb_connect("sync:", &error);
+    if (fd < 0) {
+        fprintf(stderr,"error: %s\n", error.c_str());
         return 1;
     }
 
@@ -743,11 +743,11 @@
 {
     struct stat st;
     unsigned mode;
-    int fd;
 
-    fd = adb_connect("sync:");
-    if(fd < 0) {
-        fprintf(stderr,"error: %s\n", adb_error());
+    std::string error;
+    int fd = adb_connect("sync:", &error);
+    if (fd < 0) {
+        fprintf(stderr,"error: %s\n", error.c_str());
         return 1;
     }
 
@@ -967,11 +967,10 @@
     unsigned mode, time;
     struct stat st;
 
-    int fd;
-
-    fd = adb_connect("sync:");
-    if(fd < 0) {
-        fprintf(stderr,"error: %s\n", adb_error());
+    std::string error;
+    int fd = adb_connect("sync:", &error);
+    if (fd < 0) {
+        fprintf(stderr,"error: %s\n", error.c_str());
         return 1;
     }
 
@@ -1031,9 +1030,10 @@
 {
     fprintf(stderr, "syncing %s...\n", rpath.c_str());
 
-    int fd = adb_connect("sync:");
+    std::string error;
+    int fd = adb_connect("sync:", &error);
     if (fd < 0) {
-        fprintf(stderr, "error: %s\n", adb_error());
+        fprintf(stderr, "error: %s\n", error.c_str());
         return 1;
     }
 
diff --git a/fastboot/Android.mk b/fastboot/Android.mk
index 7b2975b..dee471a 100644
--- a/fastboot/Android.mk
+++ b/fastboot/Android.mk
@@ -58,7 +58,8 @@
     libsparse_host \
     libutils \
     liblog \
-    libz
+    libz \
+    libbase
 
 ifneq ($(HOST_OS),windows)
 LOCAL_STATIC_LIBRARIES += libselinux
diff --git a/fs_mgr/fs_mgr.c b/fs_mgr/fs_mgr.c
index 47ea9aa..d5e94ac 100644
--- a/fs_mgr/fs_mgr.c
+++ b/fs_mgr/fs_mgr.c
@@ -31,7 +31,7 @@
 #include <dirent.h>
 #include <ext4.h>
 #include <ext4_sb.h>
-#include <ext4_crypt.h>
+#include <ext4_crypt_init_extensions.h>
 
 #include <linux/loop.h>
 #include <private/android_filesystem_config.h>
@@ -483,16 +483,6 @@
             return FS_MGR_MNTALL_FAIL;
         }
 
-        // Link it to the normal place so ext4_crypt functions work normally
-        strlcat(tmp_mnt, "/unencrypted", sizeof(tmp_mnt));
-        char link_path[PATH_MAX];
-        strlcpy(link_path, rec->mount_point, sizeof(link_path));
-        strlcat(link_path, "/unencrypted", sizeof(link_path));
-        if (symlink(tmp_mnt, link_path)) {
-            ERROR("Error creating symlink to unencrypted directory\n");
-            return FS_MGR_MNTALL_FAIL;
-        }
-
         return FS_MGR_MNTALL_DEV_NON_DEFAULT_FILE_ENCRYPTED;
     }
 
diff --git a/include/log/log.h b/include/log/log.h
index ce253e2..f9299b0 100644
--- a/include/log/log.h
+++ b/include/log/log.h
@@ -492,6 +492,7 @@
     EVENT_TYPE_LONG     = 1,
     EVENT_TYPE_STRING   = 2,
     EVENT_TYPE_LIST     = 3,
+    EVENT_TYPE_FLOAT    = 4,
 } AndroidEventLogType;
 #define sizeof_AndroidEventLogType sizeof(typeof_AndroidEventLogType)
 #define typeof_AndroidEventLogType unsigned char
@@ -510,6 +511,13 @@
             sizeof(longBuf));                                               \
     }
 #endif
+#ifndef LOG_EVENT_FLOAT
+#define LOG_EVENT_FLOAT(_tag, _value) {                                     \
+        float floatBuf = _value;                                            \
+        (void) android_btWriteLog(_tag, EVENT_TYPE_FLOAT, &floatBuf,        \
+            sizeof(floatBuf));                                              \
+    }
+#endif
 #ifndef LOG_EVENT_STRING
 #define LOG_EVENT_STRING(_tag, _value)                                      \
         (void) __android_log_bswrite(_tag, _value);
diff --git a/include/system/window.h b/include/system/window.h
index a875427..508ce00 100644
--- a/include/system/window.h
+++ b/include/system/window.h
@@ -267,7 +267,16 @@
      * The default data space for the buffers as set by the consumer.
      * The values are defined in graphics.h.
      */
-    NATIVE_WINDOW_DEFAULT_DATASPACE = 12
+    NATIVE_WINDOW_DEFAULT_DATASPACE = 12,
+
+    /*
+     * Returns the age of the contents of the most recently dequeued buffer as
+     * the number of frames that have elapsed since it was last queued. For
+     * example, if the window is double-buffered, the age of any given buffer in
+     * steady state will be 2. If the dequeued buffer has never been queued, its
+     * age will be 0.
+     */
+    NATIVE_WINDOW_BUFFER_AGE = 13,
 };
 
 /* Valid operations for the (*perform)() hook.
diff --git a/init/builtins.cpp b/init/builtins.cpp
index 4567b04..d772383 100644
--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -29,7 +29,7 @@
 #include <sys/wait.h>
 #include <unistd.h>
 #include <linux/loop.h>
-#include <ext4_crypt.h>
+#include <ext4_crypt_init_extensions.h>
 
 #include <selinux/selinux.h>
 #include <selinux/label.h>
@@ -386,18 +386,6 @@
 }
 
 /*
- * Callback to make a directory from the ext4 code
- */
-static int do_mount_alls_make_dir(const char* dir)
-{
-    if (make_dir(dir, 0700) && errno != EEXIST) {
-        return -1;
-    }
-
-    return 0;
-}
-
-/*
  * This function might request a reboot, in which case it will
  * not return.
  */
@@ -452,6 +440,7 @@
         property_set("vold.decrypt", "trigger_encryption");
     } else if (ret == FS_MGR_MNTALL_DEV_MIGHT_BE_ENCRYPTED) {
         property_set("ro.crypto.state", "encrypted");
+        property_set("ro.crypto.type", "block");
         property_set("vold.decrypt", "trigger_default_encryption");
     } else if (ret == FS_MGR_MNTALL_DEV_NOT_ENCRYPTED) {
         property_set("ro.crypto.state", "unencrypted");
@@ -465,26 +454,11 @@
         ret = wipe_data_via_recovery();
         /* If reboot worked, there is no return. */
     } else if (ret == FS_MGR_MNTALL_DEV_DEFAULT_FILE_ENCRYPTED) {
-        // We have to create the key files here. Only init can call make_dir,
-        // and we can't do it from fs_mgr as then fs_mgr would depend on
-        // make_dir creating a circular dependency.
-        fstab = fs_mgr_read_fstab(args[1]);
-        for (int i = 0; i < fstab->num_entries; ++i) {
-            if (fs_mgr_is_file_encrypted(&fstab->recs[i])) {
-              if (e4crypt_create_device_key(fstab->recs[i].mount_point,
-                                            do_mount_alls_make_dir)) {
-                    ERROR("Could not create device key on %s"
-                          " - continue unencrypted\n",
-                          fstab->recs[i].mount_point);
-                }
-            }
-        }
-        fs_mgr_free_fstab(fstab);
-
         if (e4crypt_install_keyring()) {
             return -1;
         }
         property_set("ro.crypto.state", "encrypted");
+        property_set("ro.crypto.type", "file");
 
         // Although encrypted, we have device key, so we do not need to
         // do anything different from the nonencrypted case.
@@ -494,6 +468,7 @@
             return -1;
         }
         property_set("ro.crypto.state", "encrypted");
+        property_set("ro.crypto.type", "file");
         property_set("vold.decrypt", "trigger_restart_min_framework");
     } else if (ret > 0) {
         ERROR("fs_mgr_mount_all returned unexpected error %d\n", ret);
@@ -840,11 +815,30 @@
         return -1;
 }
 
-int do_installkey(int nargs, char **args)
+/*
+ * Callback to make a directory from the ext4 code
+ */
+static int do_installkeys_ensure_dir_exists(const char* dir)
 {
-    if (nargs == 2) {
-        return e4crypt_install_key(args[1]);
+    if (make_dir(dir, 0700) && errno != EEXIST) {
+        return -1;
     }
 
-    return -1;
+    return 0;
+}
+
+int do_installkey(int nargs, char **args)
+{
+    if (nargs != 2) {
+        return -1;
+    }
+
+    char prop_value[PROP_VALUE_MAX] = {0};
+    property_get("ro.crypto.type", prop_value);
+    if (strcmp(prop_value, "file")) {
+        return 0;
+    }
+
+    return e4crypt_create_device_key(args[1],
+                                     do_installkeys_ensure_dir_exists);
 }
diff --git a/liblog/logprint.c b/liblog/logprint.c
index 7ba4c8e..0f01542 100644
--- a/liblog/logprint.c
+++ b/liblog/logprint.c
@@ -26,6 +26,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <inttypes.h>
 #include <sys/param.h>
 
 #include <log/logd.h>
@@ -432,7 +433,7 @@
 
     low = src[0] | (src[1] << 8) | (src[2] << 16) | (src[3] << 24);
     high = src[4] | (src[5] << 8) | (src[6] << 16) | (src[7] << 24);
-    return ((long long) high << 32) | (long long) low;
+    return ((uint64_t) high << 32) | (uint64_t) low;
 }
 
 
@@ -490,7 +491,7 @@
     case EVENT_TYPE_LONG:
         /* 64-bit signed long */
         {
-            long long lval;
+            uint64_t lval;
 
             if (eventDataLen < 8)
                 return -1;
@@ -498,7 +499,30 @@
             eventData += 8;
             eventDataLen -= 8;
 
-            outCount = snprintf(outBuf, outBufLen, "%lld", lval);
+            outCount = snprintf(outBuf, outBufLen, "%" PRId64, lval);
+            if (outCount < outBufLen) {
+                outBuf += outCount;
+                outBufLen -= outCount;
+            } else {
+                /* halt output */
+                goto no_room;
+            }
+        }
+        break;
+    case EVENT_TYPE_FLOAT:
+        /* float */
+        {
+            uint32_t ival;
+            float fval;
+
+            if (eventDataLen < 4)
+                return -1;
+            ival = get4LE(eventData);
+            fval = *(float*)&ival;
+            eventData += 4;
+            eventDataLen -= 4;
+
+            outCount = snprintf(outBuf, outBufLen, "%f", fval);
             if (outCount < outBufLen) {
                 outBuf += outCount;
                 outBufLen -= outCount;
diff --git a/libziparchive/zip_archive.cc b/libziparchive/zip_archive.cc
index 34131f1..79c4c53 100644
--- a/libziparchive/zip_archive.cc
+++ b/libziparchive/zip_archive.cc
@@ -30,6 +30,7 @@
 #include <memory>
 #include <vector>
 
+#include "base/file.h"
 #include "base/macros.h"  // TEMP_FAILURE_RETRY may or may not be in unistd
 #include "base/memory.h"
 #include "log/log.h"
@@ -1033,24 +1034,14 @@
       return false;
     }
 
-    // Keep track of the start position so we can calculate the
-    // total number of bytes written.
-    const uint8_t* const start = buf;
-    while (buf_size > 0) {
-      ssize_t bytes_written = TEMP_FAILURE_RETRY(write(fd_, buf, buf_size));
-      if (bytes_written == -1) {
-        ALOGW("Zip: unable to write " ZD " bytes to file; %s", buf_size, strerror(errno));
-        return false;
-      }
-
-      buf_size -= bytes_written;
-      buf += bytes_written;
+    const bool result = android::base::WriteFully(fd_, buf, buf_size);
+    if (result) {
+      total_bytes_written_ += buf_size;
+    } else {
+      ALOGW("Zip: unable to write " ZD " bytes to file; %s", buf_size, strerror(errno));
     }
 
-    total_bytes_written_ += static_cast<size_t>(
-        reinterpret_cast<uintptr_t>(buf) - reinterpret_cast<uintptr_t>(start));
-
-    return true;
+    return result;
   }
  private:
   FileWriter(const int fd, const size_t declared_length) :
diff --git a/logcat/event.logtags b/logcat/event.logtags
index 1b5c6f4..909f8e2 100644
--- a/logcat/event.logtags
+++ b/logcat/event.logtags
@@ -21,6 +21,7 @@
 # 2: long
 # 3: string
 # 4: list
+# 5: float
 #
 # The data unit is a number taken from the following list:
 # 1: Number of objects
diff --git a/rootdir/init.rc b/rootdir/init.rc
index c00c590..3709b82 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -220,14 +220,17 @@
     mkdir /cache/lost+found 0770 root root
 
 on post-fs-data
-    installkey /data
-
     # We chown/chmod /data again so because mount is run as root + defaults
     chown system system /data
     chmod 0771 /data
     # We restorecon /data in case the userdata partition has been reset.
     restorecon /data
 
+    # Make sure we have the device encryption key
+    start logd
+    start vold
+    installkey /data
+
     # Start bootcharting as soon as possible after the data partition is
     # mounted to collect more data.
     mkdir /data/bootchart 0755 shell shell
@@ -449,7 +452,6 @@
     class_start main
 
 on property:vold.decrypt=trigger_restart_framework
-    installkey /data
     class_start main
     class_start late_start