am e3bbb2ab: (-s ours) am 6c04e9a9: am 42640e52: Merge "Add missing #include <memory> for std::unique_ptr on Windows."

* commit 'e3bbb2ab00a117bf749d0c7e3072118276c89564':
diff --git a/adb/Android.mk b/adb/Android.mk
index e271a63..df0c7a1 100644
--- a/adb/Android.mk
+++ b/adb/Android.mk
@@ -118,6 +118,8 @@
 
 ifeq ($(HOST_OS),windows)
     LOCAL_C_INCLUDES += development/host/windows/usb/api/
+else
+    LOCAL_MULTILIB := 64
 endif
 
 include $(BUILD_HOST_STATIC_LIBRARY)
diff --git a/adb/adb.cpp b/adb/adb.cpp
index 29c9481..a0501a6 100644
--- a/adb/adb.cpp
+++ b/adb/adb.cpp
@@ -243,6 +243,11 @@
     D("adb: offline\n");
     //Close the associated usb
     t->online = 0;
+
+    // This is necessary to avoid a race condition that occured when a transport closes
+    // while a client socket is still active.
+    close_all_sockets(t);
+
     run_transport_disconnects(t);
 }
 
diff --git a/adb/commandline.cpp b/adb/commandline.cpp
index 2186b3e..ed25f3b 100644
--- a/adb/commandline.cpp
+++ b/adb/commandline.cpp
@@ -284,10 +284,7 @@
     count--;
     while (count > 0) {
         int len = adb_read(fd, buf, count);
-        if (len == 0) {
-            break;
-        } else if (len < 0) {
-            if (errno == EINTR) continue;
+        if (len <= 0) {
             break;
         }
 
@@ -340,11 +337,7 @@
             break;
         }
         if (len < 0) {
-            if (errno == EINTR) {
-                D("copy_to_file() : EINTR, retrying\n");
-                continue;
-            }
-            D("copy_to_file() : error %d\n", errno);
+            D("copy_to_file(): read failed: %s\n", strerror(errno));
             break;
         }
         if (outFd == STDOUT_FILENO) {
@@ -394,12 +387,8 @@
         D("stdin_read_thread(): pre unix_read(fdi=%d,...)\n", fdi);
         r = unix_read(fdi, buf, 1024);
         D("stdin_read_thread(): post unix_read(fdi=%d,...)\n", fdi);
-        if(r == 0) break;
-        if(r < 0) {
-            if(errno == EINTR) continue;
-            break;
-        }
-        for(n = 0; n < r; n++){
+        if (r <= 0) break;
+        for (n = 0; n < r; n++){
             switch(buf[n]) {
             case '\n':
                 state = 1;
diff --git a/adb/fdevent.cpp b/adb/fdevent.cpp
index e722d66..d25bbfb 100644
--- a/adb/fdevent.cpp
+++ b/adb/fdevent.cpp
@@ -205,8 +205,8 @@
 
     n = epoll_wait(epoll_fd, events, 256, -1);
 
-    if(n < 0) {
-        if(errno == EINTR) return;
+    if (n < 0) {
+        if (errno == EINTR) return;
         perror("epoll_wait");
         exit(1);
     }
diff --git a/adb/file_sync_client.cpp b/adb/file_sync_client.cpp
index ab11619..e70d550 100644
--- a/adb/file_sync_client.cpp
+++ b/adb/file_sync_client.cpp
@@ -203,13 +203,8 @@
     sbuf->id = ID_DATA;
     while (true) {
         int ret = adb_read(lfd, sbuf->data, sc.max);
-        if (!ret)
-            break;
-
-        if (ret < 0) {
-            if(errno == EINTR)
-                continue;
-            fprintf(stderr, "cannot read '%s': %s\n", path, strerror(errno));
+        if (ret <= 0) {
+            if (ret < 0) fprintf(stderr, "cannot read '%s': %s\n", path, strerror(errno));
             break;
         }
 
diff --git a/adb/file_sync_service.cpp b/adb/file_sync_service.cpp
index 43d907c..536dbbc 100644
--- a/adb/file_sync_service.cpp
+++ b/adb/file_sync_service.cpp
@@ -71,6 +71,7 @@
             if (chown(partial_path.c_str(), uid, gid) == -1) {
                 return false;
             }
+            // Not all filesystems support setting SELinux labels. http://b/23530370.
             selinux_android_restorecon(partial_path.c_str(), 0);
         }
     }
@@ -128,101 +129,90 @@
     return WriteFdExactly(s, &msg.dent, sizeof(msg.dent));
 }
 
-static bool fail_message(int s, const std::string& reason) {
+static bool SendSyncFail(int fd, const std::string& reason) {
     D("sync: failure: %s\n", reason.c_str());
 
     syncmsg msg;
     msg.data.id = ID_FAIL;
     msg.data.size = reason.size();
-    return WriteFdExactly(s, &msg.data, sizeof(msg.data)) && WriteFdExactly(s, reason);
+    return WriteFdExactly(fd, &msg.data, sizeof(msg.data)) && WriteFdExactly(fd, reason);
 }
 
-// TODO: callers of this have already failed, and should probably ignore its
-// return value (http://b/23437039).
-static bool fail_errno(int s) {
-    return fail_message(s, strerror(errno));
+static bool SendSyncFailErrno(int fd, const std::string& reason) {
+    return SendSyncFail(fd, android::base::StringPrintf("%s: %s", reason.c_str(), strerror(errno)));
 }
 
-static bool handle_send_file(int s, char *path, uid_t uid,
+static bool handle_send_file(int s, const char* path, uid_t uid,
                              gid_t gid, mode_t mode, std::vector<char>& buffer, bool do_unlink) {
     syncmsg msg;
     unsigned int timestamp = 0;
 
     int fd = adb_open_mode(path, O_WRONLY | O_CREAT | O_EXCL | O_CLOEXEC, mode);
-    if(fd < 0 && errno == ENOENT) {
+    if (fd < 0 && errno == ENOENT) {
         if (!secure_mkdirs(path)) {
-            if (fail_errno(s)) return false;
-            fd = -1;
-        } else {
-            fd = adb_open_mode(path, O_WRONLY | O_CREAT | O_EXCL | O_CLOEXEC, mode);
+            SendSyncFailErrno(s, "secure_mkdirs failed");
+            goto fail;
         }
+        fd = adb_open_mode(path, O_WRONLY | O_CREAT | O_EXCL | O_CLOEXEC, mode);
     }
-    if(fd < 0 && errno == EEXIST) {
+    if (fd < 0 && errno == EEXIST) {
         fd = adb_open_mode(path, O_WRONLY | O_CLOEXEC, mode);
     }
-    if(fd < 0) {
-        if (fail_errno(s)) return false;
-        fd = -1;
+    if (fd < 0) {
+        SendSyncFailErrno(s, "couldn't create file");
+        goto fail;
     } else {
-        if(fchown(fd, uid, gid) != 0) {
-            fail_errno(s);
-            errno = 0;
+        if (fchown(fd, uid, gid) == -1) {
+            SendSyncFailErrno(s, "fchown failed");
+            goto fail;
         }
 
-        /*
-         * fchown clears the setuid bit - restore it if present.
-         * Ignore the result of calling fchmod. It's not supported
-         * by all filesystems. b/12441485
-         */
+        // Not all filesystems support setting SELinux labels. http://b/23530370.
+        selinux_android_restorecon(path, 0);
+
+        // fchown clears the setuid bit - restore it if present.
+        // Ignore the result of calling fchmod. It's not supported
+        // by all filesystems. b/12441485
         fchmod(fd, mode);
     }
 
     while (true) {
         unsigned int len;
 
-        if(!ReadFdExactly(s, &msg.data, sizeof(msg.data)))
-            goto fail;
+        if (!ReadFdExactly(s, &msg.data, sizeof(msg.data))) goto fail;
 
-        if(msg.data.id != ID_DATA) {
-            if(msg.data.id == ID_DONE) {
+        if (msg.data.id != ID_DATA) {
+            if (msg.data.id == ID_DONE) {
                 timestamp = msg.data.size;
                 break;
             }
-            fail_message(s, "invalid data message");
+            SendSyncFail(s, "invalid data message");
             goto fail;
         }
         len = msg.data.size;
         if (len > buffer.size()) { // TODO: resize buffer?
-            fail_message(s, "oversize data message");
+            SendSyncFail(s, "oversize data message");
             goto fail;
         }
+
         if (!ReadFdExactly(s, &buffer[0], len)) goto fail;
 
-        if (fd < 0) continue;
-
         if (!WriteFdExactly(fd, &buffer[0], len)) {
-            int saved_errno = errno;
-            adb_close(fd);
-            if (do_unlink) adb_unlink(path);
-            fd = -1;
-            errno = saved_errno;
-            if (fail_errno(s)) return false;
+            SendSyncFailErrno(s, "write failed");
+            goto fail;
         }
     }
 
-    if(fd >= 0) {
-        struct utimbuf u;
-        adb_close(fd);
-        selinux_android_restorecon(path, 0);
-        u.actime = timestamp;
-        u.modtime = timestamp;
-        utime(path, &u);
+    adb_close(fd);
 
-        msg.status.id = ID_OKAY;
-        msg.status.msglen = 0;
-        if (!WriteFdExactly(s, &msg.status, sizeof(msg.status))) return false;
-    }
-    return true;
+    utimbuf u;
+    u.actime = timestamp;
+    u.modtime = timestamp;
+    utime(path, &u);
+
+    msg.status.id = ID_OKAY;
+    msg.status.msglen = 0;
+    return WriteFdExactly(s, &msg.status, sizeof(msg.status));
 
 fail:
     if (fd >= 0) adb_close(fd);
@@ -231,9 +221,9 @@
 }
 
 #if defined(_WIN32)
-extern bool handle_send_link(int s, char *path, std::vector<char>& buffer) __attribute__((error("no symlinks on Windows")));
+extern bool handle_send_link(int s, const std::string& path, std::vector<char>& buffer) __attribute__((error("no symlinks on Windows")));
 #else
-static bool handle_send_link(int s, char *path, std::vector<char>& buffer) {
+static bool handle_send_link(int s, const std::string& path, std::vector<char>& buffer) {
     syncmsg msg;
     unsigned int len;
     int ret;
@@ -241,27 +231,27 @@
     if (!ReadFdExactly(s, &msg.data, sizeof(msg.data))) return false;
 
     if (msg.data.id != ID_DATA) {
-        fail_message(s, "invalid data message: expected ID_DATA");
+        SendSyncFail(s, "invalid data message: expected ID_DATA");
         return false;
     }
 
     len = msg.data.size;
     if (len > buffer.size()) { // TODO: resize buffer?
-        fail_message(s, "oversize data message");
+        SendSyncFail(s, "oversize data message");
         return false;
     }
     if (!ReadFdExactly(s, &buffer[0], len)) return false;
 
-    ret = symlink(&buffer[0], path);
+    ret = symlink(&buffer[0], path.c_str());
     if (ret && errno == ENOENT) {
         if (!secure_mkdirs(path)) {
-            fail_errno(s);
+            SendSyncFailErrno(s, "secure_mkdirs failed");
             return false;
         }
-        ret = symlink(&buffer[0], path);
+        ret = symlink(&buffer[0], path.c_str());
     }
     if (ret) {
-        fail_errno(s);
+        SendSyncFailErrno(s, "symlink failed");
         return false;
     }
 
@@ -272,7 +262,7 @@
         msg.status.msglen = 0;
         if (!WriteFdExactly(s, &msg.status, sizeof(msg.status))) return false;
     } else {
-        fail_message(s, "invalid data message: expected ID_DONE");
+        SendFail(s, "invalid data message: expected ID_DONE");
         return false;
     }
 
@@ -280,59 +270,55 @@
 }
 #endif
 
-static bool do_send(int s, char* path, std::vector<char>& buffer) {
-    unsigned int mode;
-    bool is_link = false;
-    bool do_unlink;
-
-    char* tmp = strrchr(path,',');
-    if(tmp) {
-        *tmp = 0;
-        errno = 0;
-        mode = strtoul(tmp + 1, NULL, 0);
-        is_link = S_ISLNK((mode_t) mode);
-        mode &= 0777;
-    }
-    if(!tmp || errno) {
-        mode = 0644;
-        is_link = 0;
-        do_unlink = true;
-    } else {
-        struct stat st;
-        /* Don't delete files before copying if they are not "regular" */
-        do_unlink = lstat(path, &st) || S_ISREG(st.st_mode) || S_ISLNK(st.st_mode);
-        if (do_unlink) {
-            adb_unlink(path);
-        }
+static bool do_send(int s, const std::string& spec, std::vector<char>& buffer) {
+    // 'spec' is of the form "/some/path,0755". Break it up.
+    size_t comma = spec.find_last_of(',');
+    if (comma == std::string::npos) {
+        SendFail(s, "missing , in ID_SEND");
+        return false;
     }
 
-    if (is_link) {
-        return handle_send_link(s, path, buffer);
+    std::string path = spec.substr(0, comma);
+
+    errno = 0;
+    mode_t mode = strtoul(spec.substr(comma + 1).c_str(), nullptr, 0);
+    if (errno != 0) {
+        SendFail(s, "bad mode");
+        return false;
     }
 
+    // Don't delete files before copying if they are not "regular" or symlinks.
+    struct stat st;
+    bool do_unlink = (lstat(path.c_str(), &st) == -1) || S_ISREG(st.st_mode) || S_ISLNK(st.st_mode);
+    if (do_unlink) {
+        adb_unlink(path.c_str());
+    }
+
+    if (S_ISLNK(mode)) {
+        return handle_send_link(s, path.c_str(), buffer);
+    }
+
+    // Copy user permission bits to "group" and "other" permissions.
+    mode &= 0777;
+    mode |= ((mode >> 3) & 0070);
+    mode |= ((mode >> 3) & 0007);
+
     uid_t uid = -1;
     gid_t gid = -1;
     uint64_t cap = 0;
-
-    /* copy user permission bits to "group" and "other" permissions */
-    mode |= ((mode >> 3) & 0070);
-    mode |= ((mode >> 3) & 0007);
-
-    tmp = path;
-    if(*tmp == '/') {
-        tmp++;
-    }
     if (should_use_fs_config(path)) {
-        fs_config(tmp, 0, NULL, &uid, &gid, &mode, &cap);
+        unsigned int broken_api_hack = mode;
+        fs_config(path.c_str(), 0, nullptr, &uid, &gid, &broken_api_hack, &cap);
+        mode = broken_api_hack;
     }
-    return handle_send_file(s, path, uid, gid, mode, buffer, do_unlink);
+    return handle_send_file(s, path.c_str(), uid, gid, mode, buffer, do_unlink);
 }
 
 static bool do_recv(int s, const char* path, std::vector<char>& buffer) {
     int fd = adb_open(path, O_RDONLY | O_CLOEXEC);
     if (fd < 0) {
-        if (fail_errno(s)) return false;
-        return true;
+        SendSyncFailErrno(s, "open failed");
+        return false;
     }
 
     syncmsg msg;
@@ -341,10 +327,9 @@
         int r = adb_read(fd, &buffer[0], buffer.size());
         if (r <= 0) {
             if (r == 0) break;
-            if (errno == EINTR) continue;
-            bool status = fail_errno(s);
+            SendSyncFailErrno(s, "read failed");
             adb_close(fd);
-            return status;
+            return false;
         }
         msg.data.size = r;
         if (!WriteFdExactly(s, &msg.data, sizeof(msg.data)) || !WriteFdExactly(s, &buffer[0], r)) {
@@ -365,17 +350,17 @@
 
     SyncRequest request;
     if (!ReadFdExactly(fd, &request, sizeof(request))) {
-        fail_message(fd, "command read failure");
+        SendSyncFail(fd, "command read failure");
         return false;
     }
     size_t path_length = request.path_length;
     if (path_length > 1024) {
-        fail_message(fd, "path too long");
+        SendSyncFail(fd, "path too long");
         return false;
     }
     char name[1025];
     if (!ReadFdExactly(fd, name, path_length)) {
-        fail_message(fd, "filename read failure");
+        SendSyncFail(fd, "filename read failure");
         return false;
     }
     name[path_length] = 0;
@@ -399,7 +384,7 @@
       case ID_QUIT:
         return false;
       default:
-        fail_message(fd, android::base::StringPrintf("unknown command '%.4s' (%08x)",
+        SendSyncFail(fd, android::base::StringPrintf("unknown command '%.4s' (%08x)",
                                                      id, request.id));
         return false;
     }
diff --git a/adb/transport.cpp b/adb/transport.cpp
index ea673f2..5e4ffbb 100644
--- a/adb/transport.cpp
+++ b/adb/transport.cpp
@@ -140,8 +140,7 @@
             len -= r;
             p += r;
         } else {
-            D("%s: read_packet (fd=%d), error ret=%d errno=%d: %s\n", name, fd, r, errno, strerror(errno));
-            if((r < 0) && (errno == EINTR)) continue;
+            D("%s: read_packet (fd=%d), error ret=%d: %s\n", name, fd, r, strerror(errno));
             return -1;
         }
     }
@@ -171,8 +170,7 @@
             len -= r;
             p += r;
         } else {
-            D("%s: write_packet (fd=%d) error ret=%d errno=%d: %s\n", name, fd, r, errno, strerror(errno));
-            if((r < 0) && (errno == EINTR)) continue;
+            D("%s: write_packet (fd=%d) error ret=%d: %s\n", name, fd, r, strerror(errno));
             return -1;
         }
     }
@@ -332,10 +330,6 @@
         put_apacket(p);
     }
 
-    // this is necessary to avoid a race condition that occured when a transport closes
-    // while a client socket is still active.
-    close_all_sockets(t);
-
     D("%s: transport input thread is exiting, fd %d\n", t->serial, t->fd);
     kick_transport(t);
     transport_unref(t);
@@ -489,9 +483,7 @@
             len -= r;
             p   += r;
         } else {
-            if((r < 0) && (errno == EINTR)) continue;
-            D("transport_read_action: on fd %d, error %d: %s\n",
-              fd, errno, strerror(errno));
+            D("transport_read_action: on fd %d: %s\n", fd, strerror(errno));
             return -1;
         }
     }
@@ -511,9 +503,7 @@
             len -= r;
             p   += r;
         } else {
-            if((r < 0) && (errno == EINTR)) continue;
-            D("transport_write_action: on fd %d, error %d: %s\n",
-              fd, errno, strerror(errno));
+            D("transport_write_action: on fd %d: %s\n", fd, strerror(errno));
             return -1;
         }
     }
diff --git a/adb/usb_linux_client.cpp b/adb/usb_linux_client.cpp
index c6ad00d..dc44f16 100644
--- a/adb/usb_linux_client.cpp
+++ b/adb/usb_linux_client.cpp
@@ -431,17 +431,12 @@
 static int bulk_write(int bulk_in, const uint8_t* buf, size_t length)
 {
     size_t count = 0;
-    int ret;
 
-    do {
-        ret = adb_write(bulk_in, buf + count, length - count);
-        if (ret < 0) {
-            if (errno != EINTR)
-                return ret;
-        } else {
-            count += ret;
-        }
-    } while (count < length);
+    while (count < length) {
+        int ret = adb_write(bulk_in, buf + count, length - count);
+        if (ret < 0) return -1;
+        count += ret;
+    }
 
     D("[ bulk_write done fd=%d ]\n", bulk_in);
     return count;
@@ -462,20 +457,15 @@
 static int bulk_read(int bulk_out, uint8_t* buf, size_t length)
 {
     size_t count = 0;
-    int ret;
 
-    do {
-        ret = adb_read(bulk_out, buf + count, length - count);
+    while (count < length) {
+        int ret = adb_read(bulk_out, buf + count, length - count);
         if (ret < 0) {
-            if (errno != EINTR) {
-                D("[ bulk_read failed fd=%d length=%zu count=%zu ]\n",
-                                           bulk_out, length, count);
-                return ret;
-            }
-        } else {
-            count += ret;
+            D("[ bulk_read failed fd=%d length=%zu count=%zu ]\n", bulk_out, length, count);
+            return -1;
         }
-    } while (count < length);
+        count += ret;
+    }
 
     return count;
 }
diff --git a/adb/usb_osx.cpp b/adb/usb_osx.cpp
index 2ba3ff7..0ce85f3 100644
--- a/adb/usb_osx.cpp
+++ b/adb/usb_osx.cpp
@@ -118,7 +118,7 @@
     IOUSBDeviceInterface197  **dev = NULL;
     HRESULT                  result;
     SInt32                   score;
-    UInt32                   locationId;
+    uint32_t                 locationId;
     UInt8                    if_class, subclass, protocol;
     UInt16                   vendor;
     UInt16                   product;
diff --git a/crash_reporter/user_collector.cc b/crash_reporter/user_collector.cc
index ee24648..61ccc37 100644
--- a/crash_reporter/user_collector.cc
+++ b/crash_reporter/user_collector.cc
@@ -24,6 +24,7 @@
 #include <stdint.h>
 #include <sys/cdefs.h>  // For __WORDSIZE
 #include <sys/types.h>  // For getpwuid_r, getgrnam_r, WEXITSTATUS.
+#include <unistd.h>  // For setgroups
 
 #include <string>
 #include <vector>
@@ -37,6 +38,7 @@
 #include <chromeos/process.h>
 #include <chromeos/syslog_logging.h>
 #include <cutils/properties.h>
+#include <private/android_filesystem_config.h>
 
 static const char kCollectionErrorSignature[] =
     "crash_reporter-user-collection";
@@ -77,6 +79,11 @@
   core2md_failure_ = core2md_failure;
   directory_failure_ = directory_failure;
   filter_in_ = filter_in;
+
+  gid_t groups[] = { AID_SYSTEM, AID_DBUS };
+  if (setgroups(arraysize(groups), groups) != 0) {
+    PLOG(FATAL) << "Unable to set groups to system and dbus";
+  }
 }
 
 UserCollector::~UserCollector() {
diff --git a/fastboot/bootimg_utils.cpp b/fastboot/bootimg_utils.cpp
index d8905a6..c1028ef 100644
--- a/fastboot/bootimg_utils.cpp
+++ b/fastboot/bootimg_utils.cpp
@@ -32,32 +32,27 @@
 #include <stdlib.h>
 #include <string.h>
 
-void bootimg_set_cmdline(boot_img_hdr *h, const char *cmdline)
+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, 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)
+boot_img_hdr* mkbootimg(void* kernel, int64_t kernel_size, off_t kernel_offset,
+                        void* ramdisk, int64_t ramdisk_size, off_t ramdisk_offset,
+                        void* second, int64_t second_size, off_t second_offset,
+                        size_t page_size, size_t base, off_t tags_offset,
+                        int64_t* bootimg_size)
 {
-    unsigned kernel_actual;
-    unsigned ramdisk_actual;
-    unsigned second_actual;
-    unsigned page_mask;
+    size_t page_mask = page_size - 1;
 
-    page_mask = page_size - 1;
-
-    kernel_actual = (kernel_size + page_mask) & (~page_mask);
-    ramdisk_actual = (ramdisk_size + page_mask) & (~page_mask);
-    second_actual = (second_size + page_mask) & (~page_mask);
+    int64_t kernel_actual = (kernel_size + page_mask) & (~page_mask);
+    int64_t ramdisk_actual = (ramdisk_size + page_mask) & (~page_mask);
+    int64_t second_actual = (second_size + page_mask) & (~page_mask);
 
     *bootimg_size = page_size + kernel_actual + ramdisk_actual + second_actual;
 
     boot_img_hdr* hdr = reinterpret_cast<boot_img_hdr*>(calloc(*bootimg_size, 1));
-    if (hdr == 0) {
+    if (hdr == nullptr) {
         return hdr;
     }
 
@@ -74,12 +69,9 @@
 
     hdr->page_size =    page_size;
 
+    memcpy(hdr->magic + page_size, kernel, kernel_size);
+    memcpy(hdr->magic + page_size + kernel_actual, ramdisk, ramdisk_size);
+    memcpy(hdr->magic + page_size + kernel_actual + ramdisk_actual, second, second_size);
 
-    memcpy(hdr->magic + page_size,
-           kernel, kernel_size);
-    memcpy(hdr->magic + page_size + kernel_actual,
-           ramdisk, ramdisk_size);
-    memcpy(hdr->magic + page_size + kernel_actual + ramdisk_actual,
-           second, second_size);
     return hdr;
 }
diff --git a/fastboot/bootimg_utils.h b/fastboot/bootimg_utils.h
index b1a86cd..fcc8662 100644
--- a/fastboot/bootimg_utils.h
+++ b/fastboot/bootimg_utils.h
@@ -30,20 +30,14 @@
 #define _FASTBOOT_BOOTIMG_UTILS_H_
 
 #include <bootimg.h>
+#include <inttypes.h>
+#include <sys/types.h>
 
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-void bootimg_set_cmdline(boot_img_hdr *h, const char *cmdline);
-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);
-
-#if defined(__cplusplus)
-}
-#endif
+void bootimg_set_cmdline(boot_img_hdr* h, const char* cmdline);
+boot_img_hdr* mkbootimg(void* kernel, int64_t kernel_size, off_t kernel_offset,
+                        void* ramdisk, int64_t ramdisk_size, off_t ramdisk_offset,
+                        void* second, int64_t second_size, off_t second_offset,
+                        size_t page_size, size_t base, off_t tags_offset,
+                        int64_t* bootimg_size);
 
 #endif
diff --git a/fastboot/engine.cpp b/fastboot/engine.cpp
index 66b8140..a0e990a 100644
--- a/fastboot/engine.cpp
+++ b/fastboot/engine.cpp
@@ -31,7 +31,6 @@
 
 #include <errno.h>
 #include <stdarg.h>
-#include <stdbool.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -39,12 +38,6 @@
 #include <sys/types.h>
 #include <unistd.h>
 
-#ifdef USE_MINGW
-#include <fcntl.h>
-#else
-#include <sys/mman.h>
-#endif
-
 #define ARRAY_SIZE(x)           (sizeof(x)/sizeof(x[0]))
 
 #define OP_DOWNLOAD   1
@@ -58,15 +51,17 @@
 
 #define CMD_SIZE 64
 
-struct Action
-{
+struct Action {
     unsigned op;
-    Action *next;
+    Action* next;
 
     char cmd[CMD_SIZE];
-    const char *prod;
-    void *data;
-    unsigned size;
+    const char* prod;
+    void* data;
+
+    // The protocol only supports 32-bit sizes, so you'll have to break
+    // anything larger into chunks.
+    uint32_t size;
 
     const char *msg;
     int (*func)(Action* a, int status, const char* resp);
@@ -267,7 +262,7 @@
 }
 
 void fb_queue_require(const char *prod, const char *var,
-                      int invert, unsigned nvalues, const char **value)
+                      bool invert, size_t nvalues, const char **value)
 {
     Action *a;
     a = queue_action(OP_QUERY, "getvar:%s", var);
diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp
index 4dbf32f..e2971f2 100644
--- a/fastboot/fastboot.cpp
+++ b/fastboot/fastboot.cpp
@@ -34,7 +34,6 @@
 #include <getopt.h>
 #include <inttypes.h>
 #include <limits.h>
-#include <stdbool.h>
 #include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -67,12 +66,12 @@
 static int64_t sparse_limit = -1;
 static int64_t target_sparse_limit = -1;
 
-unsigned page_size = 2048;
-unsigned base_addr      = 0x10000000;
-unsigned kernel_offset  = 0x00008000;
-unsigned ramdisk_offset = 0x01000000;
-unsigned second_offset  = 0x00f00000;
-unsigned tags_offset    = 0x00000100;
+static unsigned page_size = 2048;
+static unsigned base_addr      = 0x10000000;
+static unsigned kernel_offset  = 0x00008000;
+static unsigned ramdisk_offset = 0x01000000;
+static unsigned second_offset  = 0x00f00000;
+static unsigned tags_offset    = 0x00000100;
 
 enum fb_buffer_type {
     FB_BUFFER,
@@ -81,8 +80,8 @@
 
 struct fastboot_buffer {
     enum fb_buffer_type type;
-    void *data;
-    unsigned int sz;
+    void* data;
+    int64_t sz;
 };
 
 static struct {
@@ -97,8 +96,7 @@
     {"vendor.img", "vendor.sig", "vendor", true},
 };
 
-char *find_item(const char *item, const char *product)
-{
+static char* find_item(const char* item, const char* product) {
     char *dir;
     const char *fn;
     char path[PATH_MAX + 128];
@@ -139,36 +137,26 @@
     return strdup(path);
 }
 
-static int64_t file_size(int fd)
-{
-    struct stat st;
-    int ret;
-
-    ret = fstat(fd, &st);
-
-    return ret ? -1 : st.st_size;
+static int64_t get_file_size(int fd) {
+    struct stat sb;
+    return fstat(fd, &sb) == -1 ? -1 : sb.st_size;
 }
 
-static void *load_fd(int fd, unsigned *_sz)
-{
-    char *data;
-    int sz;
+static void* load_fd(int fd, int64_t* sz) {
     int errno_tmp;
+    char* data = nullptr;
 
-    data = 0;
-
-    sz = file_size(fd);
-    if (sz < 0) {
+    *sz = get_file_size(fd);
+    if (*sz < 0) {
         goto oops;
     }
 
-    data = (char*) malloc(sz);
-    if(data == 0) goto oops;
+    data = (char*) malloc(*sz);
+    if (data == nullptr) goto oops;
 
-    if(read(fd, data, sz) != sz) goto oops;
+    if(read(fd, data, *sz) != *sz) goto oops;
     close(fd);
 
-    if(_sz) *_sz = sz;
     return data;
 
 oops:
@@ -179,17 +167,13 @@
     return 0;
 }
 
-static void *load_file(const char *fn, unsigned *_sz)
-{
-    int fd;
-
-    fd = open(fn, O_RDONLY | O_BINARY);
-    if(fd < 0) return 0;
-
-    return load_fd(fd, _sz);
+static void* load_file(const char* fn, int64_t* sz) {
+    int fd = open(fn, O_RDONLY | O_BINARY);
+    if (fd == -1) return nullptr;
+    return load_fd(fd, sz);
 }
 
-int match_fastboot_with_serial(usb_ifc_info* info, const char* local_serial) {
+static int match_fastboot_with_serial(usb_ifc_info* info, const char* local_serial) {
     // Require a matching vendor id if the user specified one with -i.
     if (vendor_id != 0 && info->dev_vendor != vendor_id) {
         return -1;
@@ -206,14 +190,12 @@
     return 0;
 }
 
-int match_fastboot(usb_ifc_info *info)
-{
+static 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) {
+static int list_devices_callback(usb_ifc_info* info) {
+    if (match_fastboot_with_serial(info, nullptr) == 0) {
         const char* serial = info->serial_number;
         if (!info->writable) {
             serial = "no permissions"; // like "adb devices"
@@ -234,8 +216,7 @@
     return -1;
 }
 
-usb_handle *open_device(void)
-{
+static usb_handle* open_device() {
     static usb_handle *usb = 0;
     int announce = 1;
 
@@ -252,15 +233,14 @@
     }
 }
 
-void list_devices(void) {
+static void list_devices() {
     // We don't actually open a USB device here,
     // just getting our callback called so we can
     // list all the connected devices.
     usb_open(list_devices_callback);
 }
 
-void usage(void)
-{
+static void usage() {
     fprintf(stderr,
 /*           1234567890123456789012345678901234567890123456789012345678901234567890123456 */
             "usage: fastboot [ <option> ] <command>\n"
@@ -315,31 +295,26 @@
         );
 }
 
-void *load_bootable_image(const char *kernel, const char *ramdisk,
-                          const char *secondstage, unsigned *sz,
-                          const char *cmdline)
-{
-    void *kdata = 0, *rdata = 0, *sdata = 0;
-    unsigned ksize = 0, rsize = 0, ssize = 0;
-    void *bdata;
-    unsigned bsize;
-
-    if(kernel == 0) {
+static void* load_bootable_image(const char* kernel, const char* ramdisk,
+                                 const char* secondstage, int64_t* sz,
+                                 const char* cmdline) {
+    if (kernel == nullptr) {
         fprintf(stderr, "no image specified\n");
         return 0;
     }
 
-    kdata = load_file(kernel, &ksize);
-    if(kdata == 0) {
+    int64_t ksize;
+    void* kdata = load_file(kernel, &ksize);
+    if (kdata == nullptr) {
         fprintf(stderr, "cannot load '%s': %s\n", kernel, strerror(errno));
         return 0;
     }
 
-        /* is this actually a boot image? */
+    // Is this actually a boot image?
     if(!memcmp(kdata, BOOT_MAGIC, BOOT_MAGIC_SIZE)) {
-        if(cmdline) bootimg_set_cmdline((boot_img_hdr*) kdata, cmdline);
+        if (cmdline) bootimg_set_cmdline((boot_img_hdr*) kdata, cmdline);
 
-        if(ramdisk) {
+        if (ramdisk) {
             fprintf(stderr, "cannot boot a boot.img *and* ramdisk\n");
             return 0;
         }
@@ -348,39 +323,44 @@
         return kdata;
     }
 
-    if(ramdisk) {
+    void* rdata = nullptr;
+    int64_t rsize = 0;
+    if (ramdisk) {
         rdata = load_file(ramdisk, &rsize);
-        if(rdata == 0) {
+        if (rdata == nullptr) {
             fprintf(stderr,"cannot load '%s': %s\n", ramdisk, strerror(errno));
             return  0;
         }
     }
 
+    void* sdata = nullptr;
+    int64_t ssize = 0;
     if (secondstage) {
         sdata = load_file(secondstage, &ssize);
-        if(sdata == 0) {
+        if (sdata == nullptr) {
             fprintf(stderr,"cannot load '%s': %s\n", secondstage, strerror(errno));
             return  0;
         }
     }
 
     fprintf(stderr,"creating boot image...\n");
-    bdata = mkbootimg(kdata, ksize, kernel_offset,
+    int64_t bsize = 0;
+    void* bdata = mkbootimg(kdata, ksize, kernel_offset,
                       rdata, rsize, ramdisk_offset,
                       sdata, ssize, second_offset,
                       page_size, base_addr, tags_offset, &bsize);
-    if(bdata == 0) {
+    if (bdata == nullptr) {
         fprintf(stderr,"failed to create boot.img\n");
         return 0;
     }
-    if(cmdline) bootimg_set_cmdline((boot_img_hdr*) bdata, cmdline);
-    fprintf(stderr,"creating boot image - %d bytes\n", bsize);
+    if (cmdline) bootimg_set_cmdline((boot_img_hdr*) bdata, cmdline);
+    fprintf(stderr, "creating boot image - %" PRId64 " bytes\n", bsize);
     *sz = bsize;
 
     return bdata;
 }
 
-static void* unzip_file(ZipArchiveHandle zip, const char* entry_name, unsigned* sz)
+static void* unzip_file(ZipArchiveHandle zip, const char* entry_name, int64_t* sz)
 {
     ZipString zip_entry_name(entry_name);
     ZipEntry zip_entry;
@@ -392,8 +372,8 @@
     *sz = zip_entry.uncompressed_length;
 
     uint8_t* data = reinterpret_cast<uint8_t*>(malloc(zip_entry.uncompressed_length));
-    if (data == NULL) {
-        fprintf(stderr, "failed to allocate %u bytes for '%s'\n", *sz, entry_name);
+    if (data == nullptr) {
+        fprintf(stderr, "failed to allocate %" PRId64 " bytes for '%s'\n", *sz, entry_name);
         return 0;
     }
 
@@ -438,7 +418,7 @@
 
 static int unzip_to_file(ZipArchiveHandle zip, char* entry_name) {
     FILE* fp = tmpfile();
-    if (fp == NULL) {
+    if (fp == nullptr) {
         fprintf(stderr, "failed to create temporary file for '%s': %s\n",
                 entry_name, strerror(errno));
         return -1;
@@ -478,7 +458,7 @@
 static int setup_requirement_line(char *name)
 {
     char *val[MAX_OPTIONS];
-    char *prod = NULL;
+    char *prod = nullptr;
     unsigned n, count;
     char *x;
     int invert = 0;
@@ -539,13 +519,10 @@
     return 0;
 }
 
-static void setup_requirements(char *data, unsigned sz)
-{
-    char *s;
-
-    s = data;
+static void setup_requirements(char* data, int64_t sz) {
+    char* s = data;
     while (sz-- > 0) {
-        if(*s == '\n') {
+        if (*s == '\n') {
             *s++ = 0;
             if (setup_requirement_line(data)) {
                 die("out of memory");
@@ -557,8 +534,7 @@
     }
 }
 
-void queue_info_dump(void)
-{
+static void queue_info_dump() {
     fb_queue_notice("--------------------------------------------");
     fb_queue_display("version-bootloader", "Bootloader Version...");
     fb_queue_display("version-baseband",   "Baseband Version.....");
@@ -573,7 +549,7 @@
         die("cannot sparse read file\n");
     }
 
-    int files = sparse_file_resparse(s, max_size, NULL, 0);
+    int files = sparse_file_resparse(s, max_size, nullptr, 0);
     if (files < 0) {
         die("Failed to resparse\n");
     }
@@ -598,7 +574,7 @@
     int status = fb_getvar(usb, response, "max-download-size");
 
     if (!status) {
-        limit = strtoul(response, NULL, 0);
+        limit = strtoul(response, nullptr, 0);
         if (limit > 0) {
             fprintf(stderr, "target reported max download size of %" PRId64 " bytes\n",
                     limit);
@@ -643,35 +619,27 @@
     /* The function fb_format_supported() currently returns the value
      * we want, so just call it.
      */
-     return fb_format_supported(usb, part, NULL);
+     return fb_format_supported(usb, part, nullptr);
 }
 
-static int load_buf_fd(usb_handle *usb, int fd,
-        struct fastboot_buffer *buf)
-{
-    int64_t sz64;
-    void *data;
-    int64_t limit;
-
-
-    sz64 = file_size(fd);
-    if (sz64 < 0) {
+static int load_buf_fd(usb_handle* usb, int fd, struct fastboot_buffer* buf) {
+    int64_t sz = get_file_size(fd);
+    if (sz == -1) {
         return -1;
     }
 
-    lseek(fd, 0, SEEK_SET);
-    limit = get_sparse_limit(usb, sz64);
+    lseek64(fd, 0, SEEK_SET);
+    int64_t limit = get_sparse_limit(usb, sz);
     if (limit) {
-        struct sparse_file **s = load_sparse_files(fd, limit);
-        if (s == NULL) {
+        sparse_file** s = load_sparse_files(fd, limit);
+        if (s == nullptr) {
             return -1;
         }
         buf->type = FB_BUFFER_SPARSE;
         buf->data = s;
     } else {
-        unsigned int sz;
-        data = load_fd(fd, &sz);
-        if (data == 0) return -1;
+        void* data = load_fd(fd, &sz);
+        if (data == nullptr) return -1;
         buf->type = FB_BUFFER;
         buf->data = data;
         buf->sz = sz;
@@ -701,8 +669,8 @@
         case FB_BUFFER_SPARSE:
             s = reinterpret_cast<sparse_file**>(buf->data);
             while (*s) {
-                int64_t sz64 = sparse_file_len(*s, true, false);
-                fb_queue_flash_sparse(pname, *s++, sz64);
+                int64_t sz = sparse_file_len(*s, true, false);
+                fb_queue_flash_sparse(pname, *s++, sz);
             }
             break;
         case FB_BUFFER:
@@ -713,8 +681,7 @@
     }
 }
 
-void do_flash(usb_handle *usb, const char *pname, const char *fname)
-{
+static void do_flash(usb_handle* usb, const char* pname, const char* fname) {
     struct fastboot_buffer buf;
 
     if (load_buf(usb, fname, &buf)) {
@@ -723,17 +690,15 @@
     flash_buf(pname, &buf);
 }
 
-void do_update_signature(ZipArchiveHandle zip, char *fn)
-{
-    unsigned sz;
+static void do_update_signature(ZipArchiveHandle zip, char* fn) {
+    int64_t sz;
     void* data = unzip_file(zip, fn, &sz);
-    if (data == 0) return;
+    if (data == nullptr) return;
     fb_queue_download("signature", data, sz);
     fb_queue_command("signature", "installing signature");
 }
 
-void do_update(usb_handle *usb, const char *filename, int erase_first)
-{
+static void do_update(usb_handle* usb, const char* filename, bool erase_first) {
     queue_info_dump();
 
     fb_queue_query_save("product", cur_product, sizeof(cur_product));
@@ -745,9 +710,9 @@
         die("failed to open zip file '%s': %s", filename, ErrorCodeString(error));
     }
 
-    unsigned sz;
+    int64_t sz;
     void* data = unzip_file(zip, "android-info.txt", &sz);
-    if (data == 0) {
+    if (data == nullptr) {
         CloseArchive(zip);
         die("update package '%s' has no android-info.txt", filename);
     }
@@ -780,36 +745,33 @@
     CloseArchive(zip);
 }
 
-void do_send_signature(char *fn)
-{
-    void *data;
-    unsigned sz;
-    char *xtn;
-
-    xtn = strrchr(fn, '.');
+static void do_send_signature(char* fn) {
+    char* xtn = strrchr(fn, '.');
     if (!xtn) return;
+
     if (strcmp(xtn, ".img")) return;
 
-    strcpy(xtn,".sig");
-    data = load_file(fn, &sz);
-    strcpy(xtn,".img");
-    if (data == 0) return;
+    strcpy(xtn, ".sig");
+
+    int64_t sz;
+    void* data = load_file(fn, &sz);
+    strcpy(xtn, ".img");
+    if (data == nullptr) return;
     fb_queue_download("signature", data, sz);
     fb_queue_command("signature", "installing signature");
 }
 
-void do_flashall(usb_handle *usb, int erase_first)
-{
+static void do_flashall(usb_handle* usb, int erase_first) {
     queue_info_dump();
 
     fb_queue_query_save("product", cur_product, sizeof(cur_product));
 
     char* fname = find_item("info", product);
-    if (fname == 0) die("cannot find android-info.txt");
+    if (fname == nullptr) die("cannot find android-info.txt");
 
-    unsigned sz;
+    int64_t sz;
     void* data = load_file(fname, &sz);
-    if (data == 0) die("could not load android-info.txt: %s", strerror(errno));
+    if (data == nullptr) die("could not load android-info.txt: %s", strerror(errno));
 
     setup_requirements(reinterpret_cast<char*>(data), sz);
 
@@ -832,8 +794,7 @@
 #define skip(n) do { argc -= (n); argv += (n); } while (0)
 #define require(n) do { if (argc < (n)) {usage(); exit(1);}} while (0)
 
-int do_oem_command(int argc, char **argv)
-{
+static int do_oem_command(int argc, char** argv) {
     char command[256];
     if (argc <= 1) return 0;
 
@@ -890,16 +851,15 @@
     return num;
 }
 
-void fb_perform_format(usb_handle* usb,
-                       const char *partition, int skip_if_not_supported,
-                       const char *type_override, const char *size_override)
-{
+static void fb_perform_format(usb_handle* usb,
+                              const char *partition, int skip_if_not_supported,
+                              const char *type_override, const char *size_override) {
     char pTypeBuff[FB_RESPONSE_SZ + 1], pSizeBuff[FB_RESPONSE_SZ + 1];
     char *pType = pTypeBuff;
     char *pSize = pSizeBuff;
     unsigned int limit = INT_MAX;
     struct fastboot_buffer buf;
-    const char *errMsg = NULL;
+    const char *errMsg = nullptr;
     const struct fs_generator *gen;
     uint64_t pSz;
     int status;
@@ -949,7 +909,7 @@
         return;
     }
 
-    pSz = strtoll(pSize, (char **)NULL, 16);
+    pSz = strtoll(pSize, (char **)nullptr, 16);
 
     fd = fileno(tmpfile());
     if (fs_generator_generate(gen, fd, pSz)) {
@@ -982,9 +942,9 @@
     int wants_wipe = 0;
     int wants_reboot = 0;
     int wants_reboot_bootloader = 0;
-    int erase_first = 1;
+    bool erase_first = true;
     void *data;
-    unsigned sz;
+    int64_t sz;
     int status;
     int c;
     int longindex;
@@ -1020,7 +980,7 @@
             usage();
             return 1;
         case 'i': {
-                char *endptr = NULL;
+                char *endptr = nullptr;
                 unsigned long val;
 
                 val = strtoul(optarg, &endptr, 0);
@@ -1036,7 +996,7 @@
             long_listing = 1;
             break;
         case 'n':
-            page_size = (unsigned)strtoul(optarg, NULL, 0);
+            page_size = (unsigned)strtoul(optarg, nullptr, 0);
             if (!page_size) die("invalid page size");
             break;
         case 'p':
@@ -1058,7 +1018,7 @@
             }
             break;
         case 'u':
-            erase_first = 0;
+            erase_first = false;
             break;
         case 'w':
             wants_wipe = 1;
@@ -1067,8 +1027,8 @@
             return 1;
         case 0:
             if (strcmp("unbuffered", longopts[longindex].name) == 0) {
-                setvbuf(stdout, NULL, _IONBF, 0);
-                setvbuf(stderr, NULL, _IONBF, 0);
+                setvbuf(stdout, nullptr, _IONBF, 0);
+                setvbuf(stderr, nullptr, _IONBF, 0);
             } else if (strcmp("version", longopts[longindex].name) == 0) {
                 fprintf(stdout, "fastboot version %s\n", FASTBOOT_REVISION);
                 return 0;
@@ -1108,7 +1068,7 @@
         } else if(!strcmp(*argv, "erase")) {
             require(2);
 
-            if (fb_format_supported(usb, argv[1], NULL)) {
+            if (fb_format_supported(usb, argv[1], nullptr)) {
                 fprintf(stderr, "******** Did you mean to fastboot format this partition?\n");
             }
 
@@ -1116,8 +1076,8 @@
             skip(2);
         } else if(!strncmp(*argv, "format", strlen("format"))) {
             char *overrides;
-            char *type_override = NULL;
-            char *size_override = NULL;
+            char *type_override = nullptr;
+            char *size_override = nullptr;
             require(2);
             /*
              * Parsing for: "format[:[type][:[size]]]"
@@ -1138,8 +1098,8 @@
                 }
                 type_override = overrides;
             }
-            if (type_override && !type_override[0]) type_override = NULL;
-            if (size_override && !size_override[0]) size_override = NULL;
+            if (type_override && !type_override[0]) type_override = nullptr;
+            if (size_override && !size_override[0]) size_override = nullptr;
             if (erase_first && needs_erase(usb, argv[1])) {
                 fb_queue_erase(argv[1]);
             }
@@ -1148,7 +1108,7 @@
         } else if(!strcmp(*argv, "signature")) {
             require(2);
             data = load_file(argv[1], &sz);
-            if (data == 0) die("could not load '%s': %s", argv[1], strerror(errno));
+            if (data == nullptr) die("could not load '%s': %s", argv[1], strerror(errno));
             if (sz != 256) die("signature must be 256 bytes");
             fb_queue_download("signature", data, sz);
             fb_queue_command("signature", "installing signature");
@@ -1258,9 +1218,9 @@
 
     if (wants_wipe) {
         fb_queue_erase("userdata");
-        fb_perform_format(usb, "userdata", 1, NULL, NULL);
+        fb_perform_format(usb, "userdata", 1, nullptr, nullptr);
         fb_queue_erase("cache");
-        fb_perform_format(usb, "cache", 1, NULL, NULL);
+        fb_perform_format(usb, "cache", 1, nullptr, nullptr);
     }
     if (wants_reboot) {
         fb_queue_reboot();
diff --git a/fastboot/fastboot.h b/fastboot/fastboot.h
index 481c501..091a70f 100644
--- a/fastboot/fastboot.h
+++ b/fastboot/fastboot.h
@@ -29,18 +29,17 @@
 #ifndef _FASTBOOT_H_
 #define _FASTBOOT_H_
 
-#include "usb.h"
+#include <inttypes.h>
+#include <stdlib.h>
 
-#if defined(__cplusplus)
-extern "C" {
-#endif
+#include "usb.h"
 
 struct sparse_file;
 
 /* protocol.c - fastboot protocol */
 int fb_command(usb_handle *usb, const char *cmd);
 int fb_command_response(usb_handle *usb, const char *cmd, char *response);
-int fb_download_data(usb_handle *usb, const void *data, unsigned size);
+int fb_download_data(usb_handle *usb, const void *data, uint32_t size);
 int fb_download_data_sparse(usb_handle *usb, struct sparse_file *s);
 char *fb_get_error(void);
 
@@ -50,17 +49,17 @@
 /* engine.c - high level command queue engine */
 int fb_getvar(struct usb_handle *usb, char *response, const char *fmt, ...);
 int fb_format_supported(usb_handle *usb, const char *partition, const char *type_override);
-void fb_queue_flash(const char *ptn, void *data, unsigned sz);
-void fb_queue_flash_sparse(const char *ptn, struct sparse_file *s, unsigned sz);
+void fb_queue_flash(const char *ptn, void *data, uint32_t sz);
+void fb_queue_flash_sparse(const char *ptn, struct sparse_file *s, uint32_t sz);
 void fb_queue_erase(const char *ptn);
-void fb_queue_format(const char *ptn, int skip_if_not_supported, unsigned int max_chunk_sz);
-void fb_queue_require(const char *prod, const char *var, int invert,
-        unsigned nvalues, const char **value);
+void fb_queue_format(const char *ptn, int skip_if_not_supported, int32_t max_chunk_sz);
+void fb_queue_require(const char *prod, const char *var, bool invert,
+                      size_t nvalues, const char **value);
 void fb_queue_display(const char *var, const char *prettyname);
-void fb_queue_query_save(const char *var, char *dest, unsigned dest_size);
+void fb_queue_query_save(const char *var, char *dest, uint32_t dest_size);
 void fb_queue_reboot(void);
 void fb_queue_command(const char *cmd, const char *msg);
-void fb_queue_download(const char *name, void *data, unsigned size);
+void fb_queue_download(const char *name, void *data, uint32_t size);
 void fb_queue_notice(const char *notice);
 void fb_queue_wait_for_disconnect(void);
 int fb_execute_queue(usb_handle *usb);
@@ -76,8 +75,4 @@
 /* Current product */
 extern char cur_product[FB_RESPONSE_SZ + 1];
 
-#if defined(__cplusplus)
-}
-#endif
-
 #endif
diff --git a/fastboot/fastboot_protocol.txt b/fastboot/fastboot_protocol.txt
index 37b1959..bb73d8a 100644
--- a/fastboot/fastboot_protocol.txt
+++ b/fastboot/fastboot_protocol.txt
@@ -41,7 +41,7 @@
 
    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
+      DATA00000000 where the 8 digit hexadecimal number represents
       the total data size to transfer.
 
 3. Data phase.  Depending on the command, the host or client will 
diff --git a/fastboot/fs.cpp b/fastboot/fs.cpp
index d8f9e16..c58a505 100644
--- a/fastboot/fs.cpp
+++ b/fastboot/fs.cpp
@@ -6,21 +6,12 @@
 #include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
-#include <stdarg.h>
-#include <stdbool.h>
 #include <string.h>
 #include <sys/stat.h>
 #include <sys/types.h>
-#include <sparse/sparse.h>
 #include <unistd.h>
 
-#ifdef USE_MINGW
-#include <fcntl.h>
-#else
-#include <sys/mman.h>
-#endif
-
-
+#include <sparse/sparse.h>
 
 static int generate_ext4_image(int fd, long long partSize)
 {
@@ -48,15 +39,13 @@
 #endif
 };
 
-const struct fs_generator* fs_get_generator(const char *fs_type)
-{
-    unsigned i;
-
-    for (i = 0; i < sizeof(generators) / sizeof(*generators); i++)
-        if (!strcmp(generators[i].fs_type, fs_type))
+const struct fs_generator* fs_get_generator(const char* fs_type) {
+    for (size_t i = 0; i < sizeof(generators) / sizeof(*generators); i++) {
+        if (strcmp(generators[i].fs_type, fs_type) == 0) {
             return generators + i;
-
-    return NULL;
+        }
+    }
+    return nullptr;
 }
 
 int fs_generator_generate(const struct fs_generator* gen, int tmpFileNo, long long partSize)
diff --git a/fastboot/fs.h b/fastboot/fs.h
index 307772b..8444081 100644
--- a/fastboot/fs.h
+++ b/fastboot/fs.h
@@ -3,18 +3,10 @@
 
 #include <stdint.h>
 
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
 struct fs_generator;
 
 const struct fs_generator* fs_get_generator(const char *fs_type);
 int fs_generator_generate(const struct fs_generator* gen, int tmpFileNo, long long partSize);
 
-#if defined(__cplusplus)
-}
-#endif
-
 #endif
 
diff --git a/fastboot/protocol.cpp b/fastboot/protocol.cpp
index 00c8a03..cbd48e8 100644
--- a/fastboot/protocol.cpp
+++ b/fastboot/protocol.cpp
@@ -26,8 +26,6 @@
  * SUCH DAMAGE.
  */
 
-#define min(a, b) \
-    ({ typeof(a) _a = (a); typeof(b) _b = (b); (_a < _b) ? _a : _b; })
 #define round_down(a, b) \
     ({ typeof(a) _a = (a); typeof(b) _b = (b); _a - (_a % _b); })
 
@@ -36,6 +34,8 @@
 #include <string.h>
 #include <errno.h>
 
+#include <algorithm>
+
 #include <sparse/sparse.h>
 
 #include "fastboot.h"
@@ -47,40 +47,38 @@
     return ERROR;
 }
 
-static int check_response(usb_handle *usb, unsigned int size, char *response)
-{
-    unsigned char status[65];
-    int r;
+static int check_response(usb_handle* usb, uint32_t size, char* response) {
+    char status[65];
 
-    for(;;) {
-        r = usb_read(usb, status, 64);
-        if(r < 0) {
+    while (true) {
+        int r = usb_read(usb, status, 64);
+        if (r < 0) {
             sprintf(ERROR, "status read failed (%s)", strerror(errno));
             usb_close(usb);
             return -1;
         }
         status[r] = 0;
 
-        if(r < 4) {
+        if (r < 4) {
             sprintf(ERROR, "status malformed (%d bytes)", r);
             usb_close(usb);
             return -1;
         }
 
-        if(!memcmp(status, "INFO", 4)) {
+        if (!memcmp(status, "INFO", 4)) {
             fprintf(stderr,"(bootloader) %s\n", status + 4);
             continue;
         }
 
-        if(!memcmp(status, "OKAY", 4)) {
-            if(response) {
+        if (!memcmp(status, "OKAY", 4)) {
+            if (response) {
                 strcpy(response, (char*) status + 4);
             }
             return 0;
         }
 
-        if(!memcmp(status, "FAIL", 4)) {
-            if(r > 4) {
+        if (!memcmp(status, "FAIL", 4)) {
+            if (r > 4) {
                 sprintf(ERROR, "remote: %s", status + 4);
             } else {
                 strcpy(ERROR, "remote failure");
@@ -88,9 +86,9 @@
             return -1;
         }
 
-        if(!memcmp(status, "DATA", 4) && size > 0){
-            unsigned dsize = strtoul((char*) status + 4, 0, 16);
-            if(dsize > size) {
+        if (!memcmp(status, "DATA", 4) && size > 0){
+            uint32_t dsize = strtol(status + 4, 0, 16);
+            if (dsize > size) {
                 strcpy(ERROR, "data size too large");
                 usb_close(usb);
                 return -1;
@@ -106,22 +104,19 @@
     return -1;
 }
 
-static int _command_start(usb_handle *usb, const char *cmd, unsigned size,
-                          char *response)
-{
-    int cmdsize = strlen(cmd);
-
-    if(response) {
-        response[0] = 0;
-    }
-
-    if(cmdsize > 64) {
-        sprintf(ERROR,"command too large");
+static int _command_start(usb_handle* usb, const char* cmd, uint32_t size, char* response) {
+    size_t cmdsize = strlen(cmd);
+    if (cmdsize > 64) {
+        sprintf(ERROR, "command too large");
         return -1;
     }
 
-    if(usb_write(usb, cmd, cmdsize) != cmdsize) {
-        sprintf(ERROR,"command write failed (%s)", strerror(errno));
+    if (response) {
+        response[0] = 0;
+    }
+
+    if (usb_write(usb, cmd, cmdsize) != static_cast<int>(cmdsize)) {
+        sprintf(ERROR, "command write failed (%s)", strerror(errno));
         usb_close(usb);
         return -1;
     }
@@ -129,45 +124,32 @@
     return check_response(usb, size, response);
 }
 
-static int _command_data(usb_handle *usb, const void *data, unsigned size)
-{
-    int r;
-
-    r = usb_write(usb, data, size);
-    if(r < 0) {
+static int _command_data(usb_handle* usb, const void* data, uint32_t size) {
+    int r = usb_write(usb, data, size);
+    if (r < 0) {
         sprintf(ERROR, "data transfer failure (%s)", strerror(errno));
         usb_close(usb);
         return -1;
     }
-    if(r != ((int) size)) {
+    if (r != ((int) size)) {
         sprintf(ERROR, "data transfer failure (short transfer)");
         usb_close(usb);
         return -1;
     }
-
     return r;
 }
 
-static int _command_end(usb_handle *usb)
-{
-    int r;
-    r = check_response(usb, 0, 0);
-    if(r < 0) {
-        return -1;
-    }
-    return 0;
+static int _command_end(usb_handle* usb) {
+    return check_response(usb, 0, 0) < 0 ? -1 : 0;
 }
 
-static int _command_send(usb_handle *usb, const char *cmd,
-                         const void *data, unsigned size,
-                         char *response)
-{
-    int r;
+static int _command_send(usb_handle* usb, const char* cmd, const void* data, uint32_t size,
+                         char* response) {
     if (size == 0) {
         return -1;
     }
 
-    r = _command_start(usb, cmd, size, response);
+    int r = _command_start(usb, cmd, size, response);
     if (r < 0) {
         return -1;
     }
@@ -178,42 +160,29 @@
     }
 
     r = _command_end(usb);
-    if(r < 0) {
+    if (r < 0) {
         return -1;
     }
 
     return size;
 }
 
-static int _command_send_no_data(usb_handle *usb, const char *cmd,
-                                 char *response)
-{
+static int _command_send_no_data(usb_handle* usb, const char* cmd, char* response) {
     return _command_start(usb, cmd, 0, response);
 }
 
-int fb_command(usb_handle *usb, const char *cmd)
-{
+int fb_command(usb_handle* usb, const char* cmd) {
     return _command_send_no_data(usb, cmd, 0);
 }
 
-int fb_command_response(usb_handle *usb, const char *cmd, char *response)
-{
+int fb_command_response(usb_handle* usb, const char* cmd, char* response) {
     return _command_send_no_data(usb, cmd, response);
 }
 
-int fb_download_data(usb_handle *usb, const void *data, unsigned size)
-{
+int fb_download_data(usb_handle* usb, const void* data, uint32_t size) {
     char cmd[64];
-    int r;
-
     sprintf(cmd, "download:%08x", size);
-    r = _command_send(usb, cmd, data, size, 0);
-
-    if(r < 0) {
-        return -1;
-    } else {
-        return 0;
-    }
+    return _command_send(usb, cmd, data, size, 0) < 0 ? -1 : 0;
 }
 
 #define USB_BUF_SIZE 1024
@@ -228,7 +197,7 @@
     const char* ptr = reinterpret_cast<const char*>(data);
 
     if (usb_buf_len) {
-        to_write = min(USB_BUF_SIZE - usb_buf_len, len);
+        to_write = std::min(USB_BUF_SIZE - usb_buf_len, len);
 
         memcpy(usb_buf + usb_buf_len, ptr, to_write);
         usb_buf_len += to_write;
@@ -270,32 +239,25 @@
     return 0;
 }
 
-static int fb_download_data_sparse_flush(usb_handle *usb)
-{
-    int r;
-
+static int fb_download_data_sparse_flush(usb_handle* usb) {
     if (usb_buf_len > 0) {
-        r = _command_data(usb, usb_buf, usb_buf_len);
-        if (r != usb_buf_len) {
+        if (_command_data(usb, usb_buf, usb_buf_len) != usb_buf_len) {
             return -1;
         }
         usb_buf_len = 0;
     }
-
     return 0;
 }
 
-int fb_download_data_sparse(usb_handle *usb, struct sparse_file *s)
-{
-    char cmd[64];
-    int r;
+int fb_download_data_sparse(usb_handle* usb, struct sparse_file* s) {
     int size = sparse_file_len(s, true, false);
     if (size <= 0) {
         return -1;
     }
 
+    char cmd[64];
     sprintf(cmd, "download:%08x", size);
-    r = _command_start(usb, cmd, size, 0);
+    int r = _command_start(usb, cmd, size, 0);
     if (r < 0) {
         return -1;
     }
diff --git a/fastboot/usb.h b/fastboot/usb.h
index c7b748e..0fda41a 100644
--- a/fastboot/usb.h
+++ b/fastboot/usb.h
@@ -29,16 +29,9 @@
 #ifndef _USB_H_
 #define _USB_H_
 
-#if defined(__cplusplus)
-extern "C" {
-#endif
+struct usb_handle;
 
-typedef struct usb_handle usb_handle;
-
-typedef struct usb_ifc_info usb_ifc_info;
-
-struct usb_ifc_info
-{
+struct usb_ifc_info {
         /* from device descriptor */
     unsigned short dev_vendor;
     unsigned short dev_product;
@@ -68,8 +61,4 @@
 int usb_write(usb_handle *h, const void *_data, int len);
 int usb_wait_for_disconnect(usb_handle *h);
 
-#if defined(__cplusplus)
-}
-#endif
-
 #endif
diff --git a/healthd/BatteryMonitor.cpp b/healthd/BatteryMonitor.cpp
index ed773d0..cb77a8e 100644
--- a/healthd/BatteryMonitor.cpp
+++ b/healthd/BatteryMonitor.cpp
@@ -183,6 +183,7 @@
     props.chargerWirelessOnline = false;
     props.batteryStatus = BATTERY_STATUS_UNKNOWN;
     props.batteryHealth = BATTERY_HEALTH_UNKNOWN;
+    props.maxChargingCurrent = 0;
 
     if (!mHealthdConfig->batteryPresentPath.isEmpty())
         props.batteryPresent = getBooleanField(mHealthdConfig->batteryPresentPath);
@@ -194,6 +195,15 @@
         getIntField(mHealthdConfig->batteryCapacityPath);
     props.batteryVoltage = getIntField(mHealthdConfig->batteryVoltagePath) / 1000;
 
+    if (!mHealthdConfig->batteryCurrentNowPath.isEmpty())
+        props.batteryCurrent = getIntField(mHealthdConfig->batteryCurrentNowPath) / 1000;
+
+    if (!mHealthdConfig->batteryFullChargePath.isEmpty())
+        props.batteryFullCharge = getIntField(mHealthdConfig->batteryFullChargePath);
+
+    if (!mHealthdConfig->batteryCycleCountPath.isEmpty())
+        props.batteryCycleCount = getIntField(mHealthdConfig->batteryCycleCountPath);
+
     props.batteryTemperature = mBatteryFixedTemperature ?
         mBatteryFixedTemperature :
         getIntField(mHealthdConfig->batteryTemperaturePath);
@@ -237,6 +247,15 @@
                     KLOG_WARNING(LOG_TAG, "%s: Unknown power supply type\n",
                                  mChargerNames[i].string());
                 }
+                path.clear();
+                path.appendFormat("%s/%s/current_max", POWER_SUPPLY_SYSFS_PATH,
+                                  mChargerNames[i].string());
+                if (access(path.string(), R_OK) == 0) {
+                    int maxChargingCurrent = getIntField(path);
+                    if (props.maxChargingCurrent < maxChargingCurrent) {
+                        props.maxChargingCurrent = maxChargingCurrent;
+                    }
+                }
             }
         }
     }
@@ -245,7 +264,7 @@
 
     if (logthis) {
         char dmesgline[256];
-
+        size_t len;
         if (props.batteryPresent) {
             snprintf(dmesgline, sizeof(dmesgline),
                  "battery l=%d v=%d t=%s%d.%d h=%d st=%d",
@@ -255,19 +274,27 @@
                  abs(props.batteryTemperature % 10), props.batteryHealth,
                  props.batteryStatus);
 
+            len = strlen(dmesgline);
             if (!mHealthdConfig->batteryCurrentNowPath.isEmpty()) {
-                int c = getIntField(mHealthdConfig->batteryCurrentNowPath);
-                char b[20];
+                len += snprintf(dmesgline + len, sizeof(dmesgline) - len,
+                                " c=%d", props.batteryCurrent);
+            }
 
-                snprintf(b, sizeof(b), " c=%d", c / 1000);
-                strlcat(dmesgline, b, sizeof(dmesgline));
+            if (!mHealthdConfig->batteryFullChargePath.isEmpty()) {
+                len += snprintf(dmesgline + len, sizeof(dmesgline) - len,
+                                " fc=%d", props.batteryFullCharge);
+            }
+
+            if (!mHealthdConfig->batteryCycleCountPath.isEmpty()) {
+                len += snprintf(dmesgline + len, sizeof(dmesgline) - len,
+                                " cc=%d", props.batteryCycleCount);
             }
         } else {
             snprintf(dmesgline, sizeof(dmesgline),
                  "battery none");
         }
 
-        size_t len = strlen(dmesgline);
+        len = strlen(dmesgline);
         snprintf(dmesgline + len, sizeof(dmesgline) - len, " chg=%s%s%s",
                  props.chargerAcOnline ? "a" : "",
                  props.chargerUsbOnline ? "u" : "",
@@ -365,9 +392,9 @@
     int v;
     char vs[128];
 
-    snprintf(vs, sizeof(vs), "ac: %d usb: %d wireless: %d\n",
+    snprintf(vs, sizeof(vs), "ac: %d usb: %d wireless: %d current_max: %d\n",
              props.chargerAcOnline, props.chargerUsbOnline,
-             props.chargerWirelessOnline);
+             props.chargerWirelessOnline, props.maxChargingCurrent);
     write(fd, vs, strlen(vs));
     snprintf(vs, sizeof(vs), "status: %d health: %d present: %d\n",
              props.batteryStatus, props.batteryHealth, props.batteryPresent);
@@ -394,6 +421,21 @@
         snprintf(vs, sizeof(vs), "charge counter: %d\n", v);
         write(fd, vs, strlen(vs));
     }
+
+    if (!mHealthdConfig->batteryCurrentNowPath.isEmpty()) {
+        snprintf(vs, sizeof(vs), "current now: %d\n", props.batteryCurrent);
+        write(fd, vs, strlen(vs));
+    }
+
+    if (!mHealthdConfig->batteryCycleCountPath.isEmpty()) {
+        snprintf(vs, sizeof(vs), "cycle count: %d\n", props.batteryCycleCount);
+        write(fd, vs, strlen(vs));
+    }
+
+    if (!mHealthdConfig->batteryFullChargePath.isEmpty()) {
+        snprintf(vs, sizeof(vs), "Full charge: %d\n", props.batteryFullCharge);
+        write(fd, vs, strlen(vs));
+    }
 }
 
 void BatteryMonitor::init(struct healthd_config *hc) {
@@ -476,6 +518,14 @@
                     }
                 }
 
+                if (mHealthdConfig->batteryFullChargePath.isEmpty()) {
+                    path.clear();
+                    path.appendFormat("%s/%s/charge_full",
+                                      POWER_SUPPLY_SYSFS_PATH, name);
+                    if (access(path, R_OK) == 0)
+                        mHealthdConfig->batteryFullChargePath = path;
+                }
+
                 if (mHealthdConfig->batteryCurrentNowPath.isEmpty()) {
                     path.clear();
                     path.appendFormat("%s/%s/current_now",
@@ -484,6 +534,14 @@
                         mHealthdConfig->batteryCurrentNowPath = path;
                 }
 
+                if (mHealthdConfig->batteryCycleCountPath.isEmpty()) {
+                    path.clear();
+                    path.appendFormat("%s/%s/cycle_count",
+                                      POWER_SUPPLY_SYSFS_PATH, name);
+                    if (access(path, R_OK) == 0)
+                        mHealthdConfig->batteryCycleCountPath = path;
+                }
+
                 if (mHealthdConfig->batteryCurrentAvgPath.isEmpty()) {
                     path.clear();
                     path.appendFormat("%s/%s/current_avg",
@@ -553,6 +611,12 @@
             KLOG_WARNING(LOG_TAG, "BatteryTemperaturePath not found\n");
         if (mHealthdConfig->batteryTechnologyPath.isEmpty())
             KLOG_WARNING(LOG_TAG, "BatteryTechnologyPath not found\n");
+	if (mHealthdConfig->batteryCurrentNowPath.isEmpty())
+            KLOG_WARNING(LOG_TAG, "BatteryCurrentNowPath not found\n");
+        if (mHealthdConfig->batteryFullChargePath.isEmpty())
+            KLOG_WARNING(LOG_TAG, "BatteryFullChargePath not found\n");
+        if (mHealthdConfig->batteryCycleCountPath.isEmpty())
+            KLOG_WARNING(LOG_TAG, "BatteryCycleCountPath not found\n");
     }
 
     if (property_get("ro.boot.fake_battery", pval, NULL) > 0
diff --git a/healthd/healthd.cpp b/healthd/healthd.cpp
index b0002cc..85888c3 100644
--- a/healthd/healthd.cpp
+++ b/healthd/healthd.cpp
@@ -52,6 +52,8 @@
     .batteryCurrentNowPath = String8(String8::kEmptyString),
     .batteryCurrentAvgPath = String8(String8::kEmptyString),
     .batteryChargeCounterPath = String8(String8::kEmptyString),
+    .batteryFullChargePath = String8(String8::kEmptyString),
+    .batteryCycleCountPath = String8(String8::kEmptyString),
     .energyCounter = NULL,
     .boot_min_cap = 0,
     .screen_on = NULL,
diff --git a/healthd/healthd.h b/healthd/healthd.h
index 84b6d76..34ea55f 100644
--- a/healthd/healthd.h
+++ b/healthd/healthd.h
@@ -65,6 +65,8 @@
     android::String8 batteryCurrentNowPath;
     android::String8 batteryCurrentAvgPath;
     android::String8 batteryChargeCounterPath;
+    android::String8 batteryFullChargePath;
+    android::String8 batteryCycleCountPath;
 
     int (*energyCounter)(int64_t *);
     int boot_min_cap;
diff --git a/include/cutils/trace.h b/include/cutils/trace.h
index 6d9b3bc..9c077d6 100644
--- a/include/cutils/trace.h
+++ b/include/cutils/trace.h
@@ -71,7 +71,7 @@
 #define ATRACE_TAG_LAST             ATRACE_TAG_PACKAGE_MANAGER
 
 // Reserved for initialization.
-#define ATRACE_TAG_NOT_READY        (1LL<<63)
+#define ATRACE_TAG_NOT_READY        (1ULL<<63)
 
 #define ATRACE_TAG_VALID_MASK ((ATRACE_TAG_LAST - 1) | ATRACE_TAG_LAST)
 
diff --git a/init/builtins.cpp b/init/builtins.cpp
index 97151c0..7a4f7c1 100644
--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -837,9 +837,9 @@
     return -1;
 }
 
-int do_load_all_props(const std::vector<std::string>& args) {
+int do_load_system_props(const std::vector<std::string>& args) {
     if (args.size() == 1) {
-        load_all_props();
+        load_system_props();
         return 0;
     }
     return -1;
@@ -867,17 +867,30 @@
     return 0;
 }
 
+static bool is_file_crypto() {
+    std::string value = property_get("ro.crypto.type");
+    return value == "file";
+}
+
 int do_installkey(const std::vector<std::string>& args)
 {
     if (args.size() != 2) {
         return -1;
     }
-
-    std::string prop_value = property_get("ro.crypto.type");
-    if (prop_value != "file") {
+    if (!is_file_crypto()) {
         return 0;
     }
-
     return e4crypt_create_device_key(args[1].c_str(),
                                      do_installkeys_ensure_dir_exists);
 }
+
+int do_setusercryptopolicies(const std::vector<std::string>& args)
+{
+    if (args.size() != 2) {
+        return -1;
+    }
+    if (!is_file_crypto()) {
+        return 0;
+    }
+    return e4crypt_set_user_crypto_policies(args[1].c_str());
+}
diff --git a/init/init_parser.cpp b/init/init_parser.cpp
index 12f44f7..983eacd 100644
--- a/init/init_parser.cpp
+++ b/init/init_parser.cpp
@@ -127,7 +127,7 @@
     case 'l':
         if (!strcmp(s, "oglevel")) return K_loglevel;
         if (!strcmp(s, "oad_persist_props")) return K_load_persist_props;
-        if (!strcmp(s, "oad_all_props")) return K_load_all_props;
+        if (!strcmp(s, "oad_system_props")) return K_load_system_props;
         break;
     case 'm':
         if (!strcmp(s, "kdir")) return K_mkdir;
@@ -155,6 +155,7 @@
         if (!strcmp(s, "etenv")) return K_setenv;
         if (!strcmp(s, "etprop")) return K_setprop;
         if (!strcmp(s, "etrlimit")) return K_setrlimit;
+        if (!strcmp(s, "etusercryptopolicies")) return K_setusercryptopolicies;
         if (!strcmp(s, "ocket")) return K_socket;
         if (!strcmp(s, "tart")) return K_start;
         if (!strcmp(s, "top")) return K_stop;
diff --git a/init/keywords.h b/init/keywords.h
index 922feee..ddada58 100644
--- a/init/keywords.h
+++ b/init/keywords.h
@@ -24,6 +24,7 @@
 int do_rmdir(const std::vector<std::string>& args);
 int do_setprop(const std::vector<std::string>& args);
 int do_setrlimit(const std::vector<std::string>& args);
+int do_setusercryptopolicies(const std::vector<std::string>& args);
 int do_start(const std::vector<std::string>& args);
 int do_stop(const std::vector<std::string>& args);
 int do_swapon_all(const std::vector<std::string>& args);
@@ -36,7 +37,7 @@
 int do_chmod(const std::vector<std::string>& args);
 int do_loglevel(const std::vector<std::string>& args);
 int do_load_persist_props(const std::vector<std::string>& args);
-int do_load_all_props(const std::vector<std::string>& args);
+int do_load_system_props(const std::vector<std::string>& args);
 int do_verity_load_state(const std::vector<std::string>& args);
 int do_verity_update_state(const std::vector<std::string>& args);
 int do_wait(const std::vector<std::string>& args);
@@ -68,7 +69,7 @@
     KEYWORD(installkey,  COMMAND, 1, do_installkey)
     KEYWORD(ioprio,      OPTION,  0, 0)
     KEYWORD(keycodes,    OPTION,  0, 0)
-    KEYWORD(load_all_props,        COMMAND, 0, do_load_all_props)
+    KEYWORD(load_system_props,     COMMAND, 0, do_load_system_props)
     KEYWORD(load_persist_props,    COMMAND, 0, do_load_persist_props)
     KEYWORD(loglevel,    COMMAND, 1, do_loglevel)
     KEYWORD(mkdir,       COMMAND, 1, do_mkdir)
@@ -88,6 +89,7 @@
     KEYWORD(setenv,      OPTION,  2, 0)
     KEYWORD(setprop,     COMMAND, 2, do_setprop)
     KEYWORD(setrlimit,   COMMAND, 3, do_setrlimit)
+    KEYWORD(setusercryptopolicies,   COMMAND, 1, do_setusercryptopolicies)
     KEYWORD(socket,      OPTION,  0, 0)
     KEYWORD(start,       COMMAND, 1, do_start)
     KEYWORD(stop,        COMMAND, 1, do_stop)
diff --git a/init/property_service.cpp b/init/property_service.cpp
index 7194820..a37d6f6 100644
--- a/init/property_service.cpp
+++ b/init/property_service.cpp
@@ -555,16 +555,10 @@
     close(fd);
 }
 
-void load_all_props() {
+void load_system_props() {
     load_properties_from_file(PROP_PATH_SYSTEM_BUILD, NULL);
     load_properties_from_file(PROP_PATH_VENDOR_BUILD, NULL);
     load_properties_from_file(PROP_PATH_FACTORY, "ro.*");
-
-    load_override_properties();
-
-    /* Read persistent properties after all default values have been loaded. */
-    load_persistent_properties();
-
     load_recovery_id_prop();
 }
 
diff --git a/init/property_service.h b/init/property_service.h
index 51d7404..f30577b 100644
--- a/init/property_service.h
+++ b/init/property_service.h
@@ -24,7 +24,7 @@
 extern void property_init(void);
 extern void property_load_boot_defaults(void);
 extern void load_persist_props(void);
-extern void load_all_props(void);
+extern void load_system_props(void);
 extern void start_property_service(void);
 void get_property_workspace(int *fd, int *sz);
 std::string property_get(const char* name);
diff --git a/libcutils/Android.mk b/libcutils/Android.mk
index 6fb8c22..2728a05 100644
--- a/libcutils/Android.mk
+++ b/libcutils/Android.mk
@@ -126,6 +126,8 @@
 LOCAL_CFLAGS += -DUSE_CPUSETS
 endif
 LOCAL_CFLAGS += -Werror -Wall -Wextra -std=gnu90
+LOCAL_CLANG := true
+LOCAL_SANITIZE := integer
 include $(BUILD_STATIC_LIBRARY)
 
 include $(CLEAR_VARS)
@@ -139,6 +141,8 @@
 endif
 LOCAL_CFLAGS += -Werror -Wall -Wextra
 LOCAL_C_INCLUDES := $(libcutils_c_includes)
+LOCAL_CLANG := true
+LOCAL_SANITIZE := integer
 include $(BUILD_SHARED_LIBRARY)
 
 include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/libcutils/hashmap.c b/libcutils/hashmap.c
index 65539ea..ede3b98 100644
--- a/libcutils/hashmap.c
+++ b/libcutils/hashmap.c
@@ -77,6 +77,9 @@
 /**
  * Hashes the given key.
  */
+#ifdef __clang__
+__attribute__((no_sanitize("integer")))
+#endif
 static inline int hashKey(Hashmap* map, void* key) {
     int h = map->hash(key);
 
@@ -152,6 +155,10 @@
     free(map);
 }
 
+#ifdef __clang__
+__attribute__((no_sanitize("integer")))
+#endif
+/* FIXME: relies on signed integer overflow, which is undefined behavior */
 int hashmapHash(void* key, size_t keySize) {
     int h = keySize;
     char* data = (char*) key;
diff --git a/libcutils/str_parms.c b/libcutils/str_parms.c
index 924289a..4f23d09 100644
--- a/libcutils/str_parms.c
+++ b/libcutils/str_parms.c
@@ -42,6 +42,9 @@
 }
 
 /* use djb hash unless we find it inadequate */
+#ifdef __clang__
+__attribute__((no_sanitize("integer")))
+#endif
 static int str_hash_fn(void *str)
 {
     uint32_t hash = 5381;
diff --git a/libutils/Android.mk b/libutils/Android.mk
index e81bde6..a299962 100644
--- a/libutils/Android.mk
+++ b/libutils/Android.mk
@@ -112,6 +112,22 @@
 LOCAL_SANITIZE := integer
 include $(BUILD_SHARED_LIBRARY)
 
+# Include subdirectory makefiles
+# ============================================================
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := SharedBufferTest
+LOCAL_STATIC_LIBRARIES := libutils libcutils
+LOCAL_SHARED_LIBRARIES := liblog
+LOCAL_SRC_FILES := SharedBufferTest.cpp
+include $(BUILD_NATIVE_TEST)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := SharedBufferTest
+LOCAL_STATIC_LIBRARIES := libutils libcutils
+LOCAL_SHARED_LIBRARIES := liblog
+LOCAL_SRC_FILES := SharedBufferTest.cpp
+include $(BUILD_HOST_NATIVE_TEST)
 
 # Build the tests in the tests/ subdirectory.
 include $(call first-makefiles-under,$(LOCAL_PATH))
diff --git a/libutils/SharedBuffer.cpp b/libutils/SharedBuffer.cpp
index 3555fb7..947551a 100644
--- a/libutils/SharedBuffer.cpp
+++ b/libutils/SharedBuffer.cpp
@@ -14,9 +14,12 @@
  * limitations under the License.
  */
 
+#define __STDC_LIMIT_MACROS
+#include <stdint.h>
 #include <stdlib.h>
 #include <string.h>
 
+#include <log/log.h>
 #include <utils/SharedBuffer.h>
 #include <utils/Atomic.h>
 
@@ -26,6 +29,11 @@
 
 SharedBuffer* SharedBuffer::alloc(size_t size)
 {
+    // Don't overflow if the combined size of the buffer / header is larger than
+    // size_max.
+    LOG_ALWAYS_FATAL_IF((size >= (SIZE_MAX - sizeof(SharedBuffer))),
+                        "Invalid buffer size %zu", size);
+
     SharedBuffer* sb = static_cast<SharedBuffer *>(malloc(sizeof(SharedBuffer) + size));
     if (sb) {
         sb->mRefs = 1;
@@ -52,7 +60,7 @@
         memcpy(sb->data(), data(), size());
         release();
     }
-    return sb;    
+    return sb;
 }
 
 SharedBuffer* SharedBuffer::editResize(size_t newSize) const
@@ -60,6 +68,11 @@
     if (onlyOwner()) {
         SharedBuffer* buf = const_cast<SharedBuffer*>(this);
         if (buf->mSize == newSize) return buf;
+        // Don't overflow if the combined size of the new buffer / header is larger than
+        // size_max.
+        LOG_ALWAYS_FATAL_IF((newSize >= (SIZE_MAX - sizeof(SharedBuffer))),
+                            "Invalid buffer size %zu", newSize);
+
         buf = (SharedBuffer*)realloc(buf, sizeof(SharedBuffer) + newSize);
         if (buf != NULL) {
             buf->mSize = newSize;
diff --git a/libutils/SharedBufferTest.cpp b/libutils/SharedBufferTest.cpp
new file mode 100644
index 0000000..d88fbf3
--- /dev/null
+++ b/libutils/SharedBufferTest.cpp
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2015 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 __STDC_LIMIT_MACROS
+
+#include <utils/SharedBuffer.h>
+
+#include <gtest/gtest.h>
+
+#include <memory>
+#include <stdint.h>
+
+TEST(SharedBufferTest, TestAlloc) {
+  EXPECT_DEATH(android::SharedBuffer::alloc(SIZE_MAX), "");
+  EXPECT_DEATH(android::SharedBuffer::alloc(SIZE_MAX - sizeof(android::SharedBuffer)), "");
+
+  // Make sure we don't die here.
+  // Check that null is returned, as we are asking for the whole address space.
+  android::SharedBuffer* buf =
+      android::SharedBuffer::alloc(SIZE_MAX - sizeof(android::SharedBuffer) - 1);
+  ASSERT_TRUE(NULL == buf);
+
+  buf = android::SharedBuffer::alloc(0);
+  ASSERT_FALSE(NULL == buf);
+  ASSERT_EQ(0U, buf->size());
+  buf->release();
+}
+
+TEST(SharedBufferTest, TestEditResize) {
+  android::SharedBuffer* buf = android::SharedBuffer::alloc(10);
+  EXPECT_DEATH(buf->editResize(SIZE_MAX - sizeof(android::SharedBuffer)), "");
+  buf = android::SharedBuffer::alloc(10);
+  EXPECT_DEATH(buf->editResize(SIZE_MAX), "");
+
+  buf = android::SharedBuffer::alloc(10);
+  // Make sure we don't die here.
+  // Check that null is returned, as we are asking for the whole address space.
+  buf = buf->editResize(SIZE_MAX - sizeof(android::SharedBuffer) - 1);
+  ASSERT_TRUE(NULL == buf);
+
+  buf = android::SharedBuffer::alloc(10);
+  buf = buf->editResize(0);
+  ASSERT_EQ(0U, buf->size());
+  buf->release();
+}
diff --git a/logd/LogBuffer.cpp b/logd/LogBuffer.cpp
index 6ea4109..c609870 100644
--- a/logd/LogBuffer.cpp
+++ b/logd/LogBuffer.cpp
@@ -467,7 +467,11 @@
             // unmerged drop message
             if (dropped) {
                 last.add(e);
-                mLastWorstUid[id][e->getUid()] = it;
+                if ((e->getUid() == worst)
+                        || (mLastWorstUid[id].find(e->getUid())
+                            == mLastWorstUid[id].end())) {
+                    mLastWorstUid[id][e->getUid()] = it;
+                }
                 ++it;
                 continue;
             }
diff --git a/rootdir/Android.mk b/rootdir/Android.mk
index e1ba2e9..f853fac 100644
--- a/rootdir/Android.mk
+++ b/rootdir/Android.mk
@@ -2,8 +2,6 @@
 
 #######################################
 # init.rc
-# Only copy init.rc if the target doesn't have its own.
-ifneq ($(TARGET_PROVIDES_INIT_RC),true)
 include $(CLEAR_VARS)
 
 LOCAL_MODULE := init.rc
@@ -12,7 +10,6 @@
 LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT)
 
 include $(BUILD_PREBUILT)
-endif
 
 #######################################
 # asan.options
diff --git a/rootdir/init.rc b/rootdir/init.rc
index f91cb2c..5febc60 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -84,10 +84,17 @@
     write /proc/sys/kernel/panic_on_oops 1
     write /proc/sys/kernel/hung_task_timeout_secs 0
     write /proc/cpu/alignment 4
+
+    # scheduler tunables
+    # Disable auto-scaling of scheduler tunables with hotplug. The tunables
+    # will vary across devices in unpredictable ways if allowed to scale with
+    # cpu cores.
+    write /proc/sys/kernel/sched_tunable_scaling 0
     write /proc/sys/kernel/sched_latency_ns 10000000
     write /proc/sys/kernel/sched_wakeup_granularity_ns 2000000
     write /proc/sys/kernel/sched_compat_yield 1
     write /proc/sys/kernel/sched_child_runs_first 0
+
     write /proc/sys/kernel/randomize_va_space 2
     write /proc/sys/kernel/kptr_restrict 2
     write /proc/sys/vm/mmap_min_addr 32768
@@ -178,8 +185,11 @@
     trigger late-init
 
 # Load properties from /system/ + /factory after fs mount.
-on load_all_props_action
-    load_all_props
+on load_system_props_action
+    load_system_props
+
+on load_persist_props_action
+    load_persist_props
     start logd
     start logd-reinit
 
@@ -192,12 +202,16 @@
     trigger early-fs
     trigger fs
     trigger post-fs
-    trigger post-fs-data
 
     # Load properties from /system/ + /factory after fs mount. Place
     # this in another action so that the load will be scheduled after the prior
     # issued fs triggers have completed.
-    trigger load_all_props_action
+    trigger load_system_props_action
+
+    # Now we can mount /data. File encryption requires keymaster to decrypt
+    # /data, which in turn can only be loaded when system properties are present
+    trigger post-fs-data
+    trigger load_persist_props_action
 
     # Remove a file to wake up anything waiting for firmware.
     trigger firmware_mounts_complete
@@ -346,6 +360,8 @@
     mkdir /data/system/heapdump 0700 system system
     mkdir /data/user 0711 system system
 
+    setusercryptopolicies /data/user
+
     # Reload policy from /data/security if present.
     setprop selinux.reload_policy 1
 
diff --git a/rootdir/init.usb.rc b/rootdir/init.usb.rc
index e290ca4..6482230 100644
--- a/rootdir/init.usb.rc
+++ b/rootdir/init.usb.rc
@@ -89,3 +89,34 @@
 # when changing the default configuration
 on property:persist.sys.usb.config=*
     setprop sys.usb.config ${persist.sys.usb.config}
+
+#
+# USB type C
+#
+
+# USB mode changes
+on property:sys.usb.typec.mode=dfp
+    write /sys/class/dual_role_usb/otg_default/mode ${sys.usb.typec.mode}
+    setprop sys.usb.typec.state ${sys.usb.typec.mode}
+
+on property:sys.usb.typec.mode=ufp
+    write /sys/class/dual_role_usb/otg_default/mode ${sys.usb.typec.mode}
+    setprop sys.usb.typec.state ${sys.usb.typec.mode}
+
+# USB data role changes
+on property:sys.usb.typec.data_role=device
+    write /sys/class/dual_role_usb/otg_default/data_role ${sys.usb.typec.data}
+    setprop sys.usb.typec.state ${sys.usb.typec.data_role}
+
+on property:sys.usb.typec.data_role=host
+    write /sys/class/dual_role_usb/otg_default/data_role ${sys.usb.typec.data}
+    setprop sys.usb.typec.state ${sys.usb.typec.data_role}
+
+# USB power role changes
+on property:sys.usb.typec.power_role=source
+    write /sys/class/dual_role_usb/otg_default/power_role ${sys.usb.typec.power}
+    setprop sys.usb.typec.state ${sys.usb.typec.power_role}
+
+on property:sys.usb.typec.power_role=sink
+    write /sys/class/dual_role_usb/otg_default/power_role ${sys.usb.typec.power}
+    setprop sys.usb.typec.state ${sys.usb.typec.power_role}
diff --git a/toolbox/lsof.c b/toolbox/lsof.c
index 982f5aa..198ca52 100644
--- a/toolbox/lsof.c
+++ b/toolbox/lsof.c
@@ -29,6 +29,7 @@
  * SUCH DAMAGE.
  */
 
+#include <ctype.h>
 #include <dirent.h>
 #include <errno.h>
 #include <fcntl.h>
@@ -57,7 +58,7 @@
 
 static void print_header()
 {
-    printf("%-9s %5s %10s %4s %9s %18s %9s %10s %s\n",
+    printf("%-9s %5s %10s %4s   %9s %18s %9s %10s %s\n",
             "COMMAND",
             "PID",
             "USER",
@@ -69,12 +70,12 @@
             "NAME");
 }
 
-static void print_type(char *type, struct pid_info_t* info)
+static void print_symlink(const char* name, const char* path, struct pid_info_t* info)
 {
     static ssize_t link_dest_size;
     static char link_dest[PATH_MAX];
 
-    strlcat(info->path, type, sizeof(info->path));
+    strlcat(info->path, path, sizeof(info->path));
     if ((link_dest_size = readlink(info->path, link_dest, sizeof(link_dest)-1)) < 0) {
         if (errno == ENOENT)
             goto out;
@@ -88,9 +89,53 @@
     if (!strcmp(link_dest, "/"))
         goto out;
 
-    printf("%-9s %5d %10s %4s %9s %18s %9s %10s %s\n",
-            info->cmdline, info->pid, info->user, type,
-            "???", "???", "???", "???", link_dest);
+    const char* fd = name;
+    char rw = ' ';
+    char locks = ' '; // TODO: read /proc/locks
+
+    const char* type = "unknown";
+    char device[32] = "?";
+    char size_off[32] = "?";
+    char node[32] = "?";
+
+    struct stat sb;
+    if (lstat(link_dest, &sb) != -1) {
+        switch ((sb.st_mode & S_IFMT)) {
+          case S_IFSOCK: type = "sock"; break; // TODO: what domain?
+          case S_IFLNK: type = "LINK"; break;
+          case S_IFREG: type = "REG"; break;
+          case S_IFBLK: type = "BLK"; break;
+          case S_IFDIR: type = "DIR"; break;
+          case S_IFCHR: type = "CHR"; break;
+          case S_IFIFO: type = "FIFO"; break;
+        }
+        snprintf(device, sizeof(device), "%d,%d", (int) sb.st_dev, (int) sb.st_rdev);
+        snprintf(node, sizeof(node), "%d", (int) sb.st_ino);
+        snprintf(size_off, sizeof(size_off), "%d", (int) sb.st_size);
+    }
+
+    if (!name) {
+        // We're looking at an fd, so read its flags.
+        fd = path;
+        char fdinfo_path[PATH_MAX];
+        snprintf(fdinfo_path, sizeof(fdinfo_path), "/proc/%d/fdinfo/%s", info->pid, path);
+        FILE* fp = fopen(fdinfo_path, "r");
+        if (fp != NULL) {
+            int pos;
+            unsigned flags;
+
+            if (fscanf(fp, "pos: %d flags: %o", &pos, &flags) == 2) {
+                flags &= O_ACCMODE;
+                if (flags == O_RDONLY) rw = 'r';
+                else if (flags == O_WRONLY) rw = 'w';
+                else rw = 'u';
+            }
+            fclose(fp);
+        }
+    }
+
+    printf("%-9s %5d %10s %4s%c%c %9s %18s %9s %10s %s\n",
+            info->cmdline, info->pid, info->user, fd, rw, locks, type, device, size_off, node, link_dest);
 
 out:
     info->path[info->parent_length] = '\0';
@@ -111,15 +156,14 @@
     if (!maps)
         goto out;
 
-    while (fscanf(maps, "%*x-%*x %*s %zx %s %ld %s\n", &offset, device, &inode,
-            file) == 4) {
+    while (fscanf(maps, "%*x-%*x %*s %zx %s %ld %s\n", &offset, device, &inode, file) == 4) {
         // We don't care about non-file maps
         if (inode == 0 || !strcmp(device, "00:00"))
             continue;
 
-        printf("%-9s %5d %10s %4s %9s %18s %9zd %10ld %s\n",
+        printf("%-9s %5d %10s %4s   %9s %18s %9zd %10ld %s\n",
                 info->cmdline, info->pid, info->user, "mem",
-                "???", device, offset, inode, file);
+                "REG", device, offset, inode, file);
     }
 
     fclose(maps);
@@ -141,7 +185,7 @@
     if (dir == NULL) {
         char msg[BUF_MAX];
         snprintf(msg, sizeof(msg), "%s (opendir: %s)", info->path, strerror(errno));
-        printf("%-9s %5d %10s %4s %9s %18s %9s %10s %s\n",
+        printf("%-9s %5d %10s %4s   %9s %18s %9s %10s %s\n",
                 info->cmdline, info->pid, info->user, "FDS",
                 "", "", "", "", msg);
         goto out;
@@ -152,7 +196,7 @@
         if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, ".."))
             continue;
 
-        print_type(de->d_name, info);
+        print_symlink(NULL, de->d_name, info);
     }
     closedir(dir);
 
@@ -207,10 +251,9 @@
     strlcpy(info.cmdline, basename(cmdline), sizeof(info.cmdline));
 
     // Read each of these symlinks
-    print_type("cwd", &info);
-    print_type("exe", &info);
-    print_type("root", &info);
-
+    print_symlink("cwd", "cwd", &info);
+    print_symlink("txt", "exe", &info);
+    print_symlink("rtd", "root", &info);
     print_fds(&info);
     print_maps(&info);
 }