Merge "ZipWriter: archive disk numbers are 0 index based"
diff --git a/adb/Android.mk b/adb/Android.mk
index 4ee1ced..c507905 100644
--- a/adb/Android.mk
+++ b/adb/Android.mk
@@ -14,6 +14,7 @@
     -Wall -Wextra -Werror \
     -Wno-unused-parameter \
     -Wno-missing-field-initializers \
+    -Wvla \
     -DADB_REVISION='"$(adb_version)"' \
 
 # Define windows.h and tchar.h Unicode preprocessor symbols so that
@@ -294,11 +295,15 @@
     libadbd \
     libbase \
     libfs_mgr \
+    libfec \
+    libfec_rs \
+    libselinux \
     liblog \
     libmincrypt \
-    libselinux \
     libext4_utils_static \
+    libsquashfs_utils \
     libcutils \
     libbase \
+    libcrypto_static
 
 include $(BUILD_EXECUTABLE)
diff --git a/adb/adb_io_test.cpp b/adb/adb_io_test.cpp
index 84e3db6..6928a90 100644
--- a/adb/adb_io_test.cpp
+++ b/adb/adb_io_test.cpp
@@ -43,7 +43,7 @@
   ASSERT_NE(-1, tf.fd);
 
   ASSERT_TRUE(android::base::WriteStringToFd(expected, tf.fd)) << strerror(errno);
-  ASSERT_EQ(0, lseek(tf.fd, SEEK_SET, 0));
+  ASSERT_EQ(0, lseek(tf.fd, 0, SEEK_SET));
 
   // Test reading the whole file.
   char buf[sizeof(expected)] = {};
@@ -57,7 +57,7 @@
   ASSERT_NE(-1, tf.fd);
 
   ASSERT_TRUE(android::base::WriteStringToFd(expected, tf.fd)) << strerror(errno);
-  ASSERT_EQ(0, lseek(tf.fd, SEEK_SET, 0));
+  ASSERT_EQ(0, lseek(tf.fd, 0, SEEK_SET));
 
   // Test that not having enough data will fail.
   char buf[sizeof(expected) + 1] = {};
@@ -71,7 +71,7 @@
   ASSERT_NE(-1, tf.fd);
 
   ASSERT_TRUE(android::base::WriteStringToFd(input, tf.fd)) << strerror(errno);
-  ASSERT_EQ(0, lseek(tf.fd, SEEK_SET, 0));
+  ASSERT_EQ(0, lseek(tf.fd, 0, SEEK_SET));
 
   // Test reading a partial file.
   char buf[sizeof(input) - 1] = {};
@@ -90,7 +90,7 @@
   // Test writing the whole string to the file.
   ASSERT_TRUE(WriteFdExactly(tf.fd, expected, sizeof(expected)))
     << strerror(errno);
-  ASSERT_EQ(0, lseek(tf.fd, SEEK_SET, 0));
+  ASSERT_EQ(0, lseek(tf.fd, 0, SEEK_SET));
 
   std::string s;
   ASSERT_TRUE(android::base::ReadFdToString(tf.fd, &s));
@@ -104,7 +104,7 @@
 
   // Test writing a partial string to the file.
   ASSERT_TRUE(WriteFdExactly(tf.fd, buf, sizeof(buf) - 2)) << strerror(errno);
-  ASSERT_EQ(0, lseek(tf.fd, SEEK_SET, 0));
+  ASSERT_EQ(0, lseek(tf.fd, 0, SEEK_SET));
 
   std::string expected(buf);
   expected.pop_back();
@@ -130,7 +130,7 @@
 
   // Test writing a partial string to the file.
   ASSERT_TRUE(WriteFdExactly(tf.fd, str)) << strerror(errno);
-  ASSERT_EQ(0, lseek(tf.fd, SEEK_SET, 0));
+  ASSERT_EQ(0, lseek(tf.fd, 0, SEEK_SET));
 
   std::string s;
   ASSERT_TRUE(android::base::ReadFdToString(tf.fd, &s));
@@ -143,7 +143,7 @@
 
     // Test writing a partial string to the file.
     ASSERT_TRUE(WriteFdFmt(tf.fd, "Foo%s%d", "bar", 123)) << strerror(errno);
-    ASSERT_EQ(0, lseek(tf.fd, SEEK_SET, 0));
+    ASSERT_EQ(0, lseek(tf.fd, 0, SEEK_SET));
 
     std::string s;
     ASSERT_TRUE(android::base::ReadFdToString(tf.fd, &s));
diff --git a/adb/commandline.cpp b/adb/commandline.cpp
index bc5ba38..2632b1f 100644
--- a/adb/commandline.cpp
+++ b/adb/commandline.cpp
@@ -39,6 +39,7 @@
 #include <base/strings.h>
 
 #if !defined(_WIN32)
+#include <signal.h>
 #include <termios.h>
 #include <unistd.h>
 #endif
@@ -440,6 +441,14 @@
 
     adb_thread_setname("stdin reader");
 
+#ifndef __WIN32
+    // Mask SIGTTIN in case we're in a backgrounded process
+    sigset_t sigset;
+    sigemptyset(&sigset);
+    sigaddset(&sigset, SIGTTIN);
+    pthread_sigmask(SIG_BLOCK, &sigset, nullptr);
+#endif
+
     char raw_buffer[1024];
     char* buffer_ptr = raw_buffer;
     size_t buffer_size = sizeof(raw_buffer);
@@ -478,7 +487,11 @@
                     state = 1;
                     break;
                 case '~':
-                    if(state == 1) state++;
+                    if(state == 1) {
+                        state++;
+                    } else {
+                        state = 0;
+                    }
                     break;
                 case '.':
                     if(state == 2) {
@@ -1342,15 +1355,20 @@
         // argv[0] is always "shell".
         --argc;
         ++argv;
-        std::string shell_type_arg;
+        int t_arg_count = 0;
         while (argc) {
             if (!strcmp(argv[0], "-T") || !strcmp(argv[0], "-t")) {
                 if (!CanUseFeature(features, kFeatureShell2)) {
                     fprintf(stderr, "error: target doesn't support PTY args -Tt\n");
                     return 1;
                 }
-                shell_type_arg = (argv[0][1] == 'T') ? kShellServiceArgRaw
-                                                     : kShellServiceArgPty;
+                // Like ssh, -t arguments are cumulative so that multiple -t's
+                // are needed to force a PTY.
+                if (argv[0][1] == 't') {
+                    ++t_arg_count;
+                } else {
+                    t_arg_count = -1;
+                }
                 --argc;
                 ++argv;
             } else if (!strcmp(argv[0], "-x")) {
@@ -1362,6 +1380,33 @@
             }
         }
 
+        std::string shell_type_arg;
+        if (CanUseFeature(features, kFeatureShell2)) {
+            if (t_arg_count < 0) {
+                shell_type_arg = kShellServiceArgRaw;
+            } else if (t_arg_count == 0) {
+                // If stdin isn't a TTY, default to a raw shell; this lets
+                // things like `adb shell < my_script.sh` work as expected.
+                // Otherwise leave |shell_type_arg| blank which uses PTY for
+                // interactive shells and raw for non-interactive.
+                if (!isatty(STDIN_FILENO)) {
+                    shell_type_arg = kShellServiceArgRaw;
+                }
+            } else if (t_arg_count == 1) {
+                // A single -t arg isn't enough to override implicit -T.
+                if (!isatty(STDIN_FILENO)) {
+                    fprintf(stderr,
+                            "Remote PTY will not be allocated because stdin is not a terminal.\n"
+                            "Use multiple -t options to force remote PTY allocation.\n");
+                    shell_type_arg = kShellServiceArgRaw;
+                } else {
+                    shell_type_arg = kShellServiceArgPty;
+                }
+            } else {
+                shell_type_arg = kShellServiceArgPty;
+            }
+        }
+
         std::string command;
         if (argc) {
             // We don't escape here, just like ssh(1). http://b/20564385.
diff --git a/adb/file_sync_client.cpp b/adb/file_sync_client.cpp
index 5513e8f..1d668bc 100644
--- a/adb/file_sync_client.cpp
+++ b/adb/file_sync_client.cpp
@@ -29,6 +29,7 @@
 #include <utime.h>
 
 #include <memory>
+#include <vector>
 
 #include "sysdeps.h"
 
@@ -77,7 +78,7 @@
         std::string error;
         fd = adb_connect("sync:", &error);
         if (fd < 0) {
-            fprintf(stderr, "error: %s\n", error.c_str());
+            fprintf(stderr, "adb: error: %s\n", error.c_str());
         }
     }
 
@@ -94,21 +95,21 @@
     bool SendRequest(int id, const char* path_and_mode) {
         size_t path_length = strlen(path_and_mode);
         if (path_length > 1024) {
-            fprintf(stderr, "SendRequest failed: path too long: %zu", path_length);
+            fprintf(stderr, "adb: SendRequest failed: path too long: %zu\n", path_length);
             errno = ENAMETOOLONG;
             return false;
         }
 
         // Sending header and payload in a single write makes a noticeable
         // difference to "adb sync" performance.
-        char buf[sizeof(SyncRequest) + path_length];
-        SyncRequest* req = reinterpret_cast<SyncRequest*>(buf);
+        std::vector<char> buf(sizeof(SyncRequest) + path_length);
+        SyncRequest* req = reinterpret_cast<SyncRequest*>(&buf[0]);
         req->id = id;
         req->path_length = path_length;
         char* data = reinterpret_cast<char*>(req + 1);
         memcpy(data, path_and_mode, path_length);
 
-        return WriteFdExactly(fd, buf, sizeof(buf));
+        return WriteFdExactly(fd, &buf[0], buf.size());
     }
 
     // Sending header, payload, and footer in a single write makes a huge
@@ -118,15 +119,15 @@
                        unsigned mtime) {
         size_t path_length = strlen(path_and_mode);
         if (path_length > 1024) {
-            fprintf(stderr, "SendSmallFile failed: path too long: %zu", path_length);
+            fprintf(stderr, "adb: SendSmallFile failed: path too long: %zu\n", path_length);
             errno = ENAMETOOLONG;
             return false;
         }
 
-        char buf[sizeof(SyncRequest) + path_length +
+        std::vector<char> buf(sizeof(SyncRequest) + path_length +
                  sizeof(SyncRequest) + data_length +
-                 sizeof(SyncRequest)];
-        char* p = buf;
+                 sizeof(SyncRequest));
+        char* p = &buf[0];
 
         SyncRequest* req_send = reinterpret_cast<SyncRequest*>(p);
         req_send->id = ID_SEND;
@@ -147,7 +148,7 @@
         req_done->path_length = mtime;
         p += sizeof(SyncRequest);
 
-        if (!WriteFdExactly(fd, buf, (p-buf))) return false;
+        if (!WriteFdExactly(fd, &buf[0], (p - &buf[0]))) return false;
 
         total_bytes += data_length;
         return true;
@@ -156,7 +157,7 @@
     bool CopyDone(const char* from, const char* to) {
         syncmsg msg;
         if (!ReadFdExactly(fd, &msg.status, sizeof(msg.status))) {
-            fprintf(stderr, "failed to copy '%s' to '%s': no ID_DONE: %s\n",
+            fprintf(stderr, "adb: failed to copy '%s' to '%s': no ID_DONE: %s\n",
                     from, to, strerror(errno));
             return false;
         }
@@ -164,17 +165,22 @@
             return true;
         }
         if (msg.status.id != ID_FAIL) {
-            fprintf(stderr, "failed to copy '%s' to '%s': unknown reason\n", from, to);
+            fprintf(stderr, "adb: failed to copy '%s' to '%s': unknown reason %d\n",
+                    from, to, msg.status.id);
             return false;
         }
-        char buffer[msg.status.msglen + 1];
-        if (!ReadFdExactly(fd, buffer, msg.status.msglen)) {
-            fprintf(stderr, "failed to copy '%s' to '%s'; failed to read reason (!): %s\n",
+        return ReportCopyFailure(from, to, msg);
+    }
+
+    bool ReportCopyFailure(const char* from, const char* to, const syncmsg& msg) {
+        std::vector<char> buf(msg.status.msglen + 1);
+        if (!ReadFdExactly(fd, &buf[0], msg.status.msglen)) {
+            fprintf(stderr, "adb: failed to copy '%s' to '%s'; failed to read reason (!): %s\n",
                     from, to, strerror(errno));
             return false;
         }
-        buffer[msg.status.msglen] = 0;
-        fprintf(stderr, "failed to copy '%s' to '%s': %s\n", from, to, buffer);
+        buf[msg.status.msglen] = 0;
+        fprintf(stderr, "adb: failed to copy '%s' to '%s': %s\n", from, to, &buf[0]);
         return false;
     }
 
@@ -246,7 +252,7 @@
 static bool SendLargeFile(SyncConnection& sc, const char* path_and_mode, const char* path,
                           unsigned mtime, bool show_progress) {
     if (!sc.SendRequest(ID_SEND, path_and_mode)) {
-        fprintf(stderr, "failed to send ID_SEND message '%s': %s\n",
+        fprintf(stderr, "adb: failed to send ID_SEND message '%s': %s\n",
                 path_and_mode, strerror(errno));
         return false;
     }
@@ -256,7 +262,7 @@
         // Determine local file size.
         struct stat st;
         if (stat(path, &st) == -1) {
-            fprintf(stderr, "cannot stat '%s': %s\n", path, strerror(errno));
+            fprintf(stderr, "adb: cannot stat '%s': %s\n", path, strerror(errno));
             return false;
         }
 
@@ -265,7 +271,7 @@
 
     int lfd = adb_open(path, O_RDONLY);
     if (lfd < 0) {
-        fprintf(stderr, "cannot open '%s': %s\n", path, strerror(errno));
+        fprintf(stderr, "adb: cannot open '%s': %s\n", path, strerror(errno));
         return false;
     }
 
@@ -275,7 +281,7 @@
         int ret = adb_read(lfd, sbuf.data, sc.max);
         if (ret <= 0) {
             if (ret < 0) {
-                fprintf(stderr, "cannot read '%s': %s\n", path, strerror(errno));
+                fprintf(stderr, "adb: cannot read '%s': %s\n", path, strerror(errno));
                 adb_close(lfd);
                 return false;
             }
@@ -300,7 +306,8 @@
     msg.data.id = ID_DONE;
     msg.data.size = mtime;
     if (!WriteFdExactly(sc.fd, &msg.data, sizeof(msg.data))) {
-        fprintf(stderr, "failed to send ID_DONE message for '%s': %s\n", path, strerror(errno));
+        fprintf(stderr, "adb: failed to send ID_DONE message for '%s': %s\n",
+                path, strerror(errno));
         return false;
     }
 
@@ -317,7 +324,7 @@
         char buf[PATH_MAX];
         ssize_t data_length = readlink(lpath, buf, PATH_MAX - 1);
         if (data_length == -1) {
-            fprintf(stderr, "readlink '%s' failed: %s\n", lpath, strerror(errno));
+            fprintf(stderr, "adb: readlink '%s' failed: %s\n", lpath, strerror(errno));
             return false;
         }
         buf[data_length++] = '\0';
@@ -328,19 +335,19 @@
     }
 
     if (!S_ISREG(mode)) {
-        fprintf(stderr, "local file '%s' has unsupported mode: 0o%o\n", lpath, mode);
+        fprintf(stderr, "adb: local file '%s' has unsupported mode: 0o%o\n", lpath, mode);
         return false;
     }
 
     struct stat st;
     if (stat(lpath, &st) == -1) {
-        fprintf(stderr, "stat '%s' failed: %s\n", lpath, strerror(errno));
+        fprintf(stderr, "adb: failed to stat local file '%s': %s\n", lpath, strerror(errno));
         return false;
     }
     if (st.st_size < SYNC_DATA_MAX) {
         std::string data;
         if (!android::base::ReadFileToString(lpath, &data)) {
-            fprintf(stderr, "failed to read all of '%s': %s\n", lpath, strerror(errno));
+            fprintf(stderr, "adb: failed to read all of '%s': %s\n", lpath, strerror(errno));
             return false;
         }
         if (!sc.SendSmallFile(path_and_mode.c_str(), data.data(), data.size(), mtime)) return false;
@@ -351,66 +358,60 @@
 }
 
 static bool sync_recv(SyncConnection& sc, const char* rpath, const char* lpath, bool show_progress) {
-    syncmsg msg;
-    int lfd = -1;
-
-    size_t len = strlen(rpath);
-    if (len > 1024) return false;
-
     unsigned size = 0;
     if (show_progress) {
         if (!sync_stat(sc, rpath, nullptr, nullptr, &size)) return false;
     }
 
     if (!sc.SendRequest(ID_RECV, rpath)) return false;
-    if (!ReadFdExactly(sc.fd, &msg.data, sizeof(msg.data))) return false;
 
-    unsigned id = msg.data.id;
-
-    if (id == ID_DATA || id == ID_DONE) {
-        adb_unlink(lpath);
-        mkdirs(lpath);
-        lfd = adb_creat(lpath, 0644);
-        if(lfd < 0) {
-            fprintf(stderr, "cannot create '%s': %s\n", lpath, strerror(errno));
-            return false;
-        }
-        goto handle_data;
-    } else {
-        goto remote_error;
+    adb_unlink(lpath);
+    mkdirs(lpath);
+    int lfd = adb_creat(lpath, 0644);
+    if (lfd < 0) {
+        fprintf(stderr, "adb: cannot create '%s': %s\n", lpath, strerror(errno));
+        return false;
     }
 
     while (true) {
-        char buffer[SYNC_DATA_MAX];
-
+        syncmsg msg;
         if (!ReadFdExactly(sc.fd, &msg.data, sizeof(msg.data))) {
             adb_close(lfd);
+            adb_unlink(lpath);
             return false;
         }
-        id = msg.data.id;
 
-    handle_data:
-        len = msg.data.size;
-        if (id == ID_DONE) break;
-        if (id != ID_DATA) goto remote_error;
-        if (len > sc.max) {
-            fprintf(stderr, "msg.data.size too large: %zu (max %zu)\n", len, sc.max);
+        if (msg.data.id == ID_DONE) break;
+
+        if (msg.data.id != ID_DATA) {
             adb_close(lfd);
+            adb_unlink(lpath);
+            sc.ReportCopyFailure(rpath, lpath, msg);
             return false;
         }
 
-        if (!ReadFdExactly(sc.fd, buffer, len)) {
+        if (msg.data.size > sc.max) {
+            fprintf(stderr, "adb: msg.data.size too large: %u (max %zu)\n", msg.data.size, sc.max);
             adb_close(lfd);
+            adb_unlink(lpath);
             return false;
         }
 
-        if (!WriteFdExactly(lfd, buffer, len)) {
-            fprintf(stderr, "cannot write '%s': %s\n", rpath, strerror(errno));
+        char buffer[SYNC_DATA_MAX];
+        if (!ReadFdExactly(sc.fd, buffer, msg.data.size)) {
             adb_close(lfd);
+            adb_unlink(lpath);
             return false;
         }
 
-        sc.total_bytes += len;
+        if (!WriteFdExactly(lfd, buffer, msg.data.size)) {
+            fprintf(stderr, "adb: cannot write '%s': %s\n", lpath, strerror(errno));
+            adb_close(lfd);
+            adb_unlink(lpath);
+            return false;
+        }
+
+        sc.total_bytes += msg.data.size;
 
         if (show_progress) {
             print_transfer_progress(sc.total_bytes, size);
@@ -419,12 +420,6 @@
 
     adb_close(lfd);
     return true;
-
-remote_error:
-    adb_close(lfd);
-    adb_unlink(lpath);
-    sc.CopyDone(rpath, lpath);
-    return false;
 }
 
 static void do_sync_ls_cb(unsigned mode, unsigned size, unsigned time,
@@ -486,7 +481,7 @@
 
     std::unique_ptr<DIR, int(*)(DIR*)> dir(opendir(lpath), closedir);
     if (!dir) {
-        fprintf(stderr, "cannot open '%s': %s\n", lpath, strerror(errno));
+        fprintf(stderr, "adb: cannot open '%s': %s\n", lpath, strerror(errno));
         return -1;
     }
 
@@ -496,7 +491,7 @@
 
         char stat_path[PATH_MAX];
         if (strlen(lpath) + strlen(de->d_name) + 1 > sizeof(stat_path)) {
-            fprintf(stderr, "skipping long path '%s%s'\n", lpath, de->d_name);
+            fprintf(stderr, "adb: skipping long path '%s%s'\n", lpath, de->d_name);
             continue;
         }
         strcpy(stat_path, lpath);
@@ -511,7 +506,7 @@
             } else {
                 ci = mkcopyinfo(lpath, rpath, de->d_name, 0);
                 if (!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode)) {
-                    fprintf(stderr, "skipping special file '%s'\n", ci->src);
+                    fprintf(stderr, "adb: skipping special file '%s'\n", ci->src);
                     free(ci);
                 } else {
                     ci->time = st.st_mtime;
@@ -522,7 +517,7 @@
                 }
             }
         } else {
-            fprintf(stderr, "cannot lstat '%s': %s\n",stat_path , strerror(errno));
+            fprintf(stderr, "adb: cannot lstat '%s': %s\n",stat_path , strerror(errno));
         }
     }
 
@@ -607,7 +602,7 @@
 
     struct stat st;
     if (stat(lpath, &st)) {
-        fprintf(stderr, "cannot stat '%s': %s\n", lpath, strerror(errno));
+        fprintf(stderr, "adb: cannot stat '%s': %s\n", lpath, strerror(errno));
         return false;
     }
 
@@ -660,7 +655,7 @@
         ci->next = *filelist;
         *filelist = ci;
     } else {
-        fprintf(stderr, "skipping special file '%s'\n", name);
+        fprintf(stderr, "adb: skipping special file '%s'\n", name);
     }
 }
 
@@ -754,7 +749,7 @@
     unsigned mode, time;
     if (!sync_stat(sc, rpath, &time, &mode, nullptr)) return false;
     if (mode == 0) {
-        fprintf(stderr, "remote object '%s' does not exist\n", rpath);
+        fprintf(stderr, "adb: remote object '%s' does not exist\n", rpath);
         return false;
     }
 
@@ -781,7 +776,7 @@
         return copy_remote_dir_local(sc, rpath, lpath, copy_attrs);
     }
 
-    fprintf(stderr, "remote object '%s' not a file or directory\n", rpath);
+    fprintf(stderr, "adb: remote object '%s' not a file or directory\n", rpath);
     return false;
 }
 
diff --git a/adb/set_verity_enable_state_service.cpp b/adb/set_verity_enable_state_service.cpp
index fd1740d..f5188e9 100644
--- a/adb/set_verity_enable_state_service.cpp
+++ b/adb/set_verity_enable_state_service.cpp
@@ -28,10 +28,11 @@
 
 #include "adb.h"
 #include "adb_io.h"
-#include "ext4_sb.h"
 #include "fs_mgr.h"
 #include "remount_service.h"
 
+#include "fec/io.h"
+
 #define FSTAB_PREFIX "/fstab."
 struct fstab *fstab;
 
@@ -41,115 +42,50 @@
 static const bool kAllowDisableVerity = false;
 #endif
 
-static int get_target_device_size(int fd, const char *blk_device,
-                                  uint64_t *device_size)
-{
-    int data_device;
-    struct ext4_super_block sb;
-    struct fs_info info;
-
-    info.len = 0;  /* Only len is set to 0 to ask the device for real size. */
-
-    data_device = adb_open(blk_device, O_RDONLY | O_CLOEXEC);
-    if (data_device < 0) {
-        WriteFdFmt(fd, "Error opening block device (%s)\n", strerror(errno));
-        return -1;
-    }
-
-    if (lseek64(data_device, 1024, SEEK_SET) < 0) {
-        WriteFdFmt(fd, "Error seeking to superblock\n");
-        adb_close(data_device);
-        return -1;
-    }
-
-    if (adb_read(data_device, &sb, sizeof(sb)) != sizeof(sb)) {
-        WriteFdFmt(fd, "Error reading superblock\n");
-        adb_close(data_device);
-        return -1;
-    }
-
-    ext4_parse_sb(&sb, &info);
-    *device_size = info.len;
-
-    adb_close(data_device);
-    return 0;
-}
-
 /* Turn verity on/off */
 static int set_verity_enabled_state(int fd, const char *block_device,
                                     const char* mount_point, bool enable)
 {
-    uint32_t magic_number;
-    const uint32_t new_magic = enable ? VERITY_METADATA_MAGIC_NUMBER
-                                      : VERITY_METADATA_MAGIC_DISABLE;
-    uint64_t device_length = 0;
-    int device = -1;
-    int retval = -1;
-
     if (!make_block_device_writable(block_device)) {
         WriteFdFmt(fd, "Could not make block device %s writable (%s).\n",
                    block_device, strerror(errno));
-        goto errout;
+        return -1;
     }
 
-    device = adb_open(block_device, O_RDWR | O_CLOEXEC);
-    if (device == -1) {
+    fec::io fh(block_device, O_RDWR);
+
+    if (!fh) {
         WriteFdFmt(fd, "Could not open block device %s (%s).\n", block_device, strerror(errno));
-        WriteFdFmt(fd, "Maybe run adb remount?\n");
-        goto errout;
+        WriteFdFmt(fd, "Maybe run adb root?\n");
+        return -1;
     }
 
-    // find the start of the verity metadata
-    if (get_target_device_size(fd, (char*)block_device, &device_length) < 0) {
-        WriteFdFmt(fd, "Could not get target device size.\n");
-        goto errout;
+    fec_verity_metadata metadata;
+
+    if (!fh.get_verity_metadata(metadata)) {
+        WriteFdFmt(fd, "Couldn't find verity metadata!\n");
+        return -1;
     }
 
-    if (lseek64(device, device_length, SEEK_SET) < 0) {
-        WriteFdFmt(fd, "Could not seek to start of verity metadata block.\n");
-        goto errout;
-    }
-
-    // check the magic number
-    if (adb_read(device, &magic_number, sizeof(magic_number)) != sizeof(magic_number)) {
-        WriteFdFmt(fd, "Couldn't read magic number!\n");
-        goto errout;
-    }
-
-    if (!enable && magic_number == VERITY_METADATA_MAGIC_DISABLE) {
+    if (!enable && metadata.disabled) {
         WriteFdFmt(fd, "Verity already disabled on %s\n", mount_point);
-        goto errout;
+        return -1;
     }
 
-    if (enable && magic_number == VERITY_METADATA_MAGIC_NUMBER) {
+    if (enable && !metadata.disabled) {
         WriteFdFmt(fd, "Verity already enabled on %s\n", mount_point);
-        goto errout;
+        return -1;
     }
 
-    if (magic_number != VERITY_METADATA_MAGIC_NUMBER
-            && magic_number != VERITY_METADATA_MAGIC_DISABLE) {
-        WriteFdFmt(fd, "Couldn't find verity metadata at offset %" PRIu64 "!\n", device_length);
-        goto errout;
-    }
-
-    if (lseek64(device, device_length, SEEK_SET) < 0) {
-        WriteFdFmt(fd, "Could not seek to start of verity metadata block.\n");
-        goto errout;
-    }
-
-    if (adb_write(device, &new_magic, sizeof(new_magic)) != sizeof(new_magic)) {
+    if (!fh.set_verity_status(enable)) {
         WriteFdFmt(fd, "Could not set verity %s flag on device %s with error %s\n",
                    enable ? "enabled" : "disabled",
                    block_device, strerror(errno));
-        goto errout;
+        return -1;
     }
 
     WriteFdFmt(fd, "Verity %s on %s\n", enable ? "enabled" : "disabled", mount_point);
-    retval = 0;
-errout:
-    if (device != -1)
-        adb_close(device);
-    return retval;
+    return 0;
 }
 
 void set_verity_enabled_state_service(int fd, void* cookie)
diff --git a/adb/sysdeps.h b/adb/sysdeps.h
index 501a75a..51d09a6 100644
--- a/adb/sysdeps.h
+++ b/adb/sysdeps.h
@@ -319,6 +319,9 @@
 
 #define getcwd adb_getcwd
 
+char* adb_strerror(int err);
+#define strerror adb_strerror
+
 // Convert from UTF-8 to UTF-16, typically used to convert char strings into
 // wchar_t strings that can be passed to wchar_t-based OS and C Runtime APIs
 // on Windows.
diff --git a/adb/sysdeps_win32.cpp b/adb/sysdeps_win32.cpp
index 994b851..14d1375 100644
--- a/adb/sysdeps_win32.cpp
+++ b/adb/sysdeps_win32.cpp
@@ -556,6 +556,81 @@
     return 0;
 }
 
+// Overrides strerror() to handle error codes not supported by the Windows C
+// Runtime (MSVCRT.DLL).
+char* adb_strerror(int err) {
+    // sysdeps.h defines strerror to adb_strerror, but in this function, we
+    // want to call the real C Runtime strerror().
+#pragma push_macro("strerror")
+#undef strerror
+    const int saved_err = errno;      // Save because we overwrite it later.
+
+    // Lookup the string for an unknown error.
+    char* errmsg = strerror(-1);
+    const std::string unknown_error = (errmsg == nullptr) ? "" : errmsg;
+
+    // Lookup the string for this error to see if the C Runtime has it.
+    errmsg = strerror(err);
+    if (errmsg != nullptr && unknown_error != errmsg) {
+        // The CRT returned an error message and it is different than the error
+        // message for an unknown error, so it is probably valid, so use it.
+    } else {
+        // Check if we have a string for this error code.
+        const char* custom_msg = nullptr;
+        switch (err) {
+#pragma push_macro("ERR")
+#undef ERR
+#define ERR(errnum, desc) case errnum: custom_msg = desc; break
+            // These error strings are from AOSP bionic/libc/include/sys/_errdefs.h.
+            // Note that these cannot be longer than 94 characters because we
+            // pass this to _strerror() which has that requirement.
+            ERR(ECONNRESET,    "Connection reset by peer");
+            ERR(EHOSTUNREACH,  "No route to host");
+            ERR(ENETDOWN,      "Network is down");
+            ERR(ENETRESET,     "Network dropped connection because of reset");
+            ERR(ENOBUFS,       "No buffer space available");
+            ERR(ENOPROTOOPT,   "Protocol not available");
+            ERR(ENOTCONN,      "Transport endpoint is not connected");
+            ERR(ENOTSOCK,      "Socket operation on non-socket");
+            ERR(EOPNOTSUPP,    "Operation not supported on transport endpoint");
+#pragma pop_macro("ERR")
+        }
+
+        if (custom_msg != nullptr) {
+            // Use _strerror() to write our string into the writable per-thread
+            // buffer used by strerror()/_strerror(). _strerror() appends the
+            // msg for the current value of errno, so set errno to a consistent
+            // value for every call so that our code-path is always the same.
+            errno = 0;
+            errmsg = _strerror(custom_msg);
+            const size_t custom_msg_len = strlen(custom_msg);
+            // Just in case _strerror() returned a read-only string, check if
+            // the returned string starts with our custom message because that
+            // implies that the string is not read-only.
+            if ((errmsg != nullptr) &&
+                !strncmp(custom_msg, errmsg, custom_msg_len)) {
+                // _strerror() puts other text after our custom message, so
+                // remove that by terminating after our message.
+                errmsg[custom_msg_len] = '\0';
+            } else {
+                // For some reason nullptr was returned or a pointer to a
+                // read-only string was returned, so fallback to whatever
+                // strerror() can muster (probably "Unknown error" or some
+                // generic CRT error string).
+                errmsg = strerror(err);
+            }
+        } else {
+            // We don't have a custom message, so use whatever strerror(err)
+            // returned earlier.
+        }
+    }
+
+    errno = saved_err;  // restore
+
+    return errmsg;
+#pragma pop_macro("strerror")
+}
+
 /**************************************************************************/
 /**************************************************************************/
 /*****                                                                *****/
@@ -567,18 +642,38 @@
 #undef setsockopt
 
 static void _socket_set_errno( const DWORD err ) {
-    // The Windows C Runtime (MSVCRT.DLL) strerror() does not support a lot of
-    // POSIX and socket error codes, so this can only meaningfully map so much.
+    // Because the Windows C Runtime (MSVCRT.DLL) strerror() does not support a
+    // lot of POSIX and socket error codes, some of the resulting error codes
+    // are mapped to strings by adb_strerror() above.
     switch ( err ) {
     case 0:              errno = 0; break;
+    // Don't map WSAEINTR since that is only for Winsock 1.1 which we don't use.
+    // case WSAEINTR:    errno = EINTR; break;
+    case WSAEFAULT:      errno = EFAULT; break;
+    case WSAEINVAL:      errno = EINVAL; break;
+    case WSAEMFILE:      errno = EMFILE; break;
     // Mapping WSAEWOULDBLOCK to EAGAIN is absolutely critical because
     // non-blocking sockets can cause an error code of WSAEWOULDBLOCK and
     // callers check specifically for EAGAIN.
     case WSAEWOULDBLOCK: errno = EAGAIN; break;
-    case WSAEINTR:       errno = EINTR; break;
-    case WSAEFAULT:      errno = EFAULT; break;
-    case WSAEINVAL:      errno = EINVAL; break;
-    case WSAEMFILE:      errno = EMFILE; break;
+    case WSAENOTSOCK:    errno = ENOTSOCK; break;
+    case WSAENOPROTOOPT: errno = ENOPROTOOPT; break;
+    case WSAEOPNOTSUPP:  errno = EOPNOTSUPP; break;
+    case WSAENETDOWN:    errno = ENETDOWN; break;
+    case WSAENETRESET:   errno = ENETRESET; break;
+    // Map WSAECONNABORTED to EPIPE instead of ECONNABORTED because POSIX seems
+    // to use EPIPE for these situations and there are some callers that look
+    // for EPIPE.
+    case WSAECONNABORTED: errno = EPIPE; break;
+    case WSAECONNRESET:  errno = ECONNRESET; break;
+    case WSAENOBUFS:     errno = ENOBUFS; break;
+    case WSAENOTCONN:    errno = ENOTCONN; break;
+    // Don't map WSAETIMEDOUT because we don't currently use SO_RCVTIMEO or
+    // SO_SNDTIMEO which would cause WSAETIMEDOUT to be returned. Future
+    // considerations: Reportedly send() can return zero on timeout, and POSIX
+    // code may expect EAGAIN instead of ETIMEDOUT on timeout.
+    // case WSAETIMEDOUT: errno = ETIMEDOUT; break;
+    case WSAEHOSTUNREACH: errno = EHOSTUNREACH; break;
     default:
         errno = EINVAL;
         D( "_socket_set_errno: mapping Windows error code %lu to errno %d",
@@ -655,8 +750,12 @@
     int  result = send(f->fh_socket, reinterpret_cast<const char*>(buf), len, 0);
     if (result == SOCKET_ERROR) {
         const DWORD err = WSAGetLastError();
-        D("send fd %d failed: %s", _fh_to_int(f),
-          SystemErrorCodeToString(err).c_str());
+        // WSAEWOULDBLOCK is normal with a non-blocking socket, so don't trace
+        // that to reduce spam and confusion.
+        if (err != WSAEWOULDBLOCK) {
+            D("send fd %d failed: %s", _fh_to_int(f),
+              SystemErrorCodeToString(err).c_str());
+        }
         _socket_set_errno(err);
         result = -1;
     } else {
diff --git a/adb/sysdeps_win32_test.cpp b/adb/sysdeps_win32_test.cpp
index cc3ac5c..66d1ba8 100755
--- a/adb/sysdeps_win32_test.cpp
+++ b/adb/sysdeps_win32_test.cpp
@@ -67,3 +67,29 @@
         EXPECT_GT(strlen(path_val), 0);
     }
 }
+
+void TestAdbStrError(int err, const char* expected) {
+    errno = 12345;
+    const char* result = adb_strerror(err);
+    // Check that errno is not overwritten.
+    EXPECT_EQ(12345, errno);
+    EXPECT_STREQ(expected, result);
+}
+
+TEST(sysdeps_win32, adb_strerror) {
+    // Test an error code that should not have a mapped string. Use an error
+    // code that is not used by the internal implementation of adb_strerror().
+    TestAdbStrError(-2, "Unknown error");
+    // adb_strerror() uses -1 internally, so test that it can still be passed
+    // as a parameter.
+    TestAdbStrError(-1, "Unknown error");
+    // Test very big, positive unknown error.
+    TestAdbStrError(1000000, "Unknown error");
+    // Test success case.
+    TestAdbStrError(0, "No error");
+    // Test error that regular strerror() should have a string for.
+    TestAdbStrError(EPERM, "Operation not permitted");
+    // Test error that regular strerror() doesn't have a string for, but that
+    // adb_strerror() returns.
+    TestAdbStrError(ECONNRESET, "Connection reset by peer");
+}
diff --git a/base/logging_test.cpp b/base/logging_test.cpp
index 9cf1aad..70f9952 100644
--- a/base/logging_test.cpp
+++ b/base/logging_test.cpp
@@ -139,7 +139,7 @@
   {
     CapturedStderr cap;
     LOG(WARNING) << "foobar";
-    ASSERT_EQ(0, lseek(cap.fd(), SEEK_SET, 0));
+    ASSERT_EQ(0, lseek(cap.fd(), 0, SEEK_SET));
 
     std::string output;
     android::base::ReadFdToString(cap.fd(), &output);
@@ -155,7 +155,7 @@
   {
     CapturedStderr cap;
     LOG(INFO) << "foobar";
-    ASSERT_EQ(0, lseek(cap.fd(), SEEK_SET, 0));
+    ASSERT_EQ(0, lseek(cap.fd(), 0, SEEK_SET));
 
     std::string output;
     android::base::ReadFdToString(cap.fd(), &output);
@@ -171,7 +171,7 @@
   {
     CapturedStderr cap;
     LOG(DEBUG) << "foobar";
-    ASSERT_EQ(0, lseek(cap.fd(), SEEK_SET, 0));
+    ASSERT_EQ(0, lseek(cap.fd(), 0, SEEK_SET));
 
     std::string output;
     android::base::ReadFdToString(cap.fd(), &output);
@@ -182,7 +182,7 @@
     android::base::ScopedLogSeverity severity(android::base::DEBUG);
     CapturedStderr cap;
     LOG(DEBUG) << "foobar";
-    ASSERT_EQ(0, lseek(cap.fd(), SEEK_SET, 0));
+    ASSERT_EQ(0, lseek(cap.fd(), 0, SEEK_SET));
 
     std::string output;
     android::base::ReadFdToString(cap.fd(), &output);
@@ -202,7 +202,7 @@
     LOG(INFO) << (errno = 67890);
     EXPECT_EQ(12345, errno) << "errno was not restored";
 
-    ASSERT_EQ(0, lseek(cap.fd(), SEEK_SET, 0));
+    ASSERT_EQ(0, lseek(cap.fd(), 0, SEEK_SET));
 
     std::string output;
     android::base::ReadFdToString(cap.fd(), &output);
@@ -245,7 +245,7 @@
     CapturedStderr cap;
     errno = ENOENT;
     PLOG(INFO) << "foobar";
-    ASSERT_EQ(0, lseek(cap.fd(), SEEK_SET, 0));
+    ASSERT_EQ(0, lseek(cap.fd(), 0, SEEK_SET));
 
     std::string output;
     android::base::ReadFdToString(cap.fd(), &output);
@@ -264,7 +264,7 @@
     CapturedStderr cap;
     errno = ENOENT;
     UNIMPLEMENTED(ERROR);
-    ASSERT_EQ(0, lseek(cap.fd(), SEEK_SET, 0));
+    ASSERT_EQ(0, lseek(cap.fd(), 0, SEEK_SET));
 
     std::string output;
     android::base::ReadFdToString(cap.fd(), &output);
diff --git a/crash_reporter/Android.mk b/crash_reporter/Android.mk
index 11dfcbc..c5ca4e4 100644
--- a/crash_reporter/Android.mk
+++ b/crash_reporter/Android.mk
@@ -43,7 +43,7 @@
 LOCAL_C_INCLUDES := $(crash_reporter_includes)
 LOCAL_RTTI_FLAG := -frtti
 LOCAL_SHARED_LIBRARIES := libchrome \
-    libchromeos \
+    libbrillo \
     libcutils \
     libdbus \
     libmetrics \
@@ -65,7 +65,7 @@
 LOCAL_INIT_RC := crash_reporter.rc
 LOCAL_RTTI_FLAG := -frtti
 LOCAL_SHARED_LIBRARIES := libchrome \
-    libchromeos \
+    libbrillo \
     libcutils \
     libdbus \
     libmetrics \
@@ -106,6 +106,7 @@
 # will log it as a configuration error.
 $(LOCAL_BUILT_MODULE): BRILLO_CRASH_SERVER ?= ""
 $(LOCAL_BUILT_MODULE):
+	$(hide)mkdir -p $(dir $@)
 	echo $(BRILLO_CRASH_SERVER) > $@
 endif
 
@@ -133,7 +134,7 @@
 LOCAL_MODULE := crash_reporter_tests
 LOCAL_CPP_EXTENSION := $(crash_reporter_cpp_extension)
 LOCAL_SHARED_LIBRARIES := libchrome \
-    libchromeos \
+    libbrillo \
     libcutils \
     libdbus \
     libpcrecpp
diff --git a/crash_reporter/crash_sender b/crash_reporter/crash_sender
index 5b859a8..95204a4 100755
--- a/crash_reporter/crash_sender
+++ b/crash_reporter/crash_sender
@@ -98,6 +98,10 @@
   log -t "${TAG}" "$@"
 }
 
+lwarn() {
+  lecho -psyslog.warn "$@"
+}
+
 # Returns true if mock is enabled.
 is_mock() {
   [ -f "${MOCK_CRASH_SENDING}" ] && return 0
@@ -294,6 +298,11 @@
   fi
 }
 
+# Return the log string filtered with only JSON-safe white-listed characters.
+filter_log_string() {
+  echo "$1" | tr -cd '[:alnum:]_.\-:;'
+}
+
 send_crash() {
   local meta_path="$1"
   local report_payload="$(get_key_value "${meta_path}" "payload")"
@@ -434,8 +443,7 @@
     ret=$?
     if [ ${ret} -ne 0 ]; then
       proxy=''
-      lecho -psyslog.warn \
-        "Listing proxies failed with exit code ${ret}"
+      lwarn "Listing proxies failed with exit code ${ret}"
     else
       proxy=$(echo "${proxy}" | head -1)
     fi
@@ -446,7 +454,7 @@
   local curl_stderr="${TMP_DIR}/curl_stderr"
 
   set +e
-  curl "${url}" -v ${proxy:+--proxy "$proxy"} \
+  curl "${url}" -f -v ${proxy:+--proxy "$proxy"} \
     --capath "${RESTRICTED_CERTIFICATES_PATH}" --ciphers HIGH \
     -F "prod=${product}" \
     -F "ver=${version}" \
@@ -466,22 +474,17 @@
 
   if [ ${curl_result} -eq 0 ]; then
     local id="$(cat "${report_id}")"
-    local product_name
     local timestamp="$(date +%s)"
-    case ${product} in
-    Chrome_ChromeOS)
-      if is_official_image; then
-        product_name="Chrome"
-      else
-        product_name="Chromium"
-      fi
-      ;;
-    *)
-      product_name="Brillo"
-      ;;
-    esac
-    printf '%s,%s,%s\n' \
-      "${timestamp}" "${id}" "${product_name}" >> "${CRASH_LOG}"
+    local filter_prod="$(filter_log_string "${product}")"
+    local filter_exec="$(filter_log_string "${exec_name}")"
+    if [ "${filter_prod}" != "${product}" ]; then
+      lwarn "Product name filtered to: ${filter_prod}."
+    fi
+    if [ "${filter_exec}" != "${exec_name}" ]; then
+      lwarn "Exec name filtered to: ${filter_exec}."
+    fi
+    printf "{'time':%s,'id':'%s','product':'%s','exec_name':'%s'}\n" \
+      "${timestamp}" "${id}" "${filter_prod}" "${filter_exec}" >> "${CRASH_LOG}"
     lecho "Crash report receipt ID ${id}"
   else
     lecho "Crash sending failed with exit code ${curl_result}: " \
diff --git a/debuggerd/debuggerd.cpp b/debuggerd/debuggerd.cpp
index 713638d..1287fb9 100644
--- a/debuggerd/debuggerd.cpp
+++ b/debuggerd/debuggerd.cpp
@@ -528,7 +528,7 @@
     return 1;
   fcntl(s, F_SETFD, FD_CLOEXEC);
 
-  ALOGI("debuggerd: " __DATE__ " " __TIME__ "\n");
+  ALOGI("debuggerd: starting\n");
 
   for (;;) {
     sockaddr addr;
diff --git a/fs_mgr/fs_mgr_verity.cpp b/fs_mgr/fs_mgr_verity.cpp
index c358982..6983b72 100644
--- a/fs_mgr/fs_mgr_verity.cpp
+++ b/fs_mgr/fs_mgr_verity.cpp
@@ -765,8 +765,9 @@
             continue;
         }
 
-        if (current == VERITY_MODE_LOGGING) {
+        if (current != VERITY_MODE_DEFAULT) {
             *mode = current;
+            break;
         }
     }
 
@@ -784,7 +785,6 @@
 {
     alignas(dm_ioctl) char buffer[DM_BUF_SIZE];
     bool use_state = true;
-    bool use_state_for_device = true;
     char fstab_filename[PROPERTY_VALUE_MAX + sizeof(FSTAB_PREFIX)];
     char *mount_point;
     char propbuf[PROPERTY_VALUE_MAX];
@@ -801,12 +801,13 @@
     property_get("ro.boot.veritymode", propbuf, "");
 
     if (*propbuf != '\0') {
-        if (fs_mgr_load_verity_state(&mode) == -1) {
-            return -1;
-        }
         use_state = false; /* state is kept by the bootloader */
     }
 
+    if (fs_mgr_load_verity_state(&mode) == -1) {
+        return -1;
+    }
+
     fd = TEMP_FAILURE_RETRY(open("/dev/device-mapper", O_RDWR | O_CLOEXEC));
 
     if (fd == -1) {
@@ -829,15 +830,6 @@
             continue;
         }
 
-        use_state_for_device = use_state;
-
-        if (use_state) {
-            if (get_verity_state_offset(&fstab->recs[i], &offset) < 0 ||
-                read_verity_state(fstab->recs[i].verity_loc, offset, &mode) < 0) {
-                use_state_for_device = false;
-            }
-        }
-
         mount_point = basename(fstab->recs[i].mount_point);
         verity_ioctl_init(io, mount_point, 0);
 
@@ -849,7 +841,7 @@
 
         status = &buffer[io->data_start + sizeof(struct dm_target_spec)];
 
-        if (use_state_for_device && *status == 'C') {
+        if (use_state && *status == 'C') {
             if (write_verity_state(fstab->recs[i].verity_loc, offset,
                     VERITY_MODE_LOGGING) < 0) {
                 continue;
diff --git a/healthd/Android.mk b/healthd/Android.mk
index 07e1d73..27c985c 100644
--- a/healthd/Android.mk
+++ b/healthd/Android.mk
@@ -35,7 +35,7 @@
 
 LOCAL_C_INCLUDES := bootable/recovery
 
-LOCAL_STATIC_LIBRARIES := libbatteryservice libbinder libminui libpng libz libutils libstdc++ libcutils liblog libm libc
+LOCAL_STATIC_LIBRARIES := libbatteryservice libbinder libminui libpng libz libutils libcutils liblog libm libc
 
 ifeq ($(strip $(BOARD_CHARGER_ENABLE_SUSPEND)),true)
 LOCAL_STATIC_LIBRARIES += libsuspend
diff --git a/include/binderwrapper/binder_wrapper.h b/include/binderwrapper/binder_wrapper.h
index e57cf83..921c4ed 100644
--- a/include/binderwrapper/binder_wrapper.h
+++ b/include/binderwrapper/binder_wrapper.h
@@ -17,6 +17,8 @@
 #ifndef SYSTEM_CORE_INCLUDE_BINDERWRAPPER_BINDER_WRAPPER_H_
 #define SYSTEM_CORE_INCLUDE_BINDERWRAPPER_BINDER_WRAPPER_H_
 
+#include <sys/types.h>
+
 #include <string>
 
 #include <base/callback.h>
@@ -68,6 +70,10 @@
   // Unregisters the callback, if any, for |binder|.
   virtual bool UnregisterForDeathNotifications(const sp<IBinder>& binder) = 0;
 
+  // When called while in a transaction, returns the caller's UID or PID.
+  virtual uid_t GetCallingUid() = 0;
+  virtual pid_t GetCallingPid() = 0;
+
  private:
   static BinderWrapper* instance_;
 };
diff --git a/include/binderwrapper/stub_binder_wrapper.h b/include/binderwrapper/stub_binder_wrapper.h
index 6e198ae..01c9648 100644
--- a/include/binderwrapper/stub_binder_wrapper.h
+++ b/include/binderwrapper/stub_binder_wrapper.h
@@ -77,6 +77,9 @@
   }
   void clear_local_binders() { local_binders_.clear(); }
 
+  void set_calling_uid(uid_t uid) { calling_uid_ = uid; }
+  void set_calling_pid(pid_t pid) { calling_pid_ = pid; }
+
   // Sets the binder to return when |service_name| is passed to GetService() or
   // WaitForService().
   void SetBinderForService(const std::string& service_name,
@@ -97,6 +100,8 @@
   bool RegisterForDeathNotifications(const sp<IBinder>& binder,
                                      const base::Closure& callback) override;
   bool UnregisterForDeathNotifications(const sp<IBinder>& binder) override;
+  uid_t GetCallingUid() override;
+  pid_t GetCallingPid() override;
 
  private:
   using ServiceMap = std::map<std::string, sp<IBinder>>;
@@ -116,6 +121,10 @@
   // death.
   std::map<sp<IBinder>, base::Closure> death_callbacks_;
 
+  // Values to return from GetCallingUid() and GetCallingPid();
+  uid_t calling_uid_;
+  pid_t calling_pid_;
+
   DISALLOW_COPY_AND_ASSIGN(StubBinderWrapper);
 };
 
diff --git a/include/log/logger.h b/include/log/logger.h
index f030dab..c795253 100644
--- a/include/log/logger.h
+++ b/include/log/logger.h
@@ -183,6 +183,8 @@
                                              pid_t pid);
 #define android_logger_list_close android_logger_list_free
 
+char android_log_timestamp();
+
 /*
  * log_id_t helpers
  */
diff --git a/include/log/logprint.h b/include/log/logprint.h
index 26b1ee5..204b3f2 100644
--- a/include/log/logprint.h
+++ b/include/log/logprint.h
@@ -42,6 +42,8 @@
     FORMAT_MODIFIER_PRINTABLE, /* converts non-printable to printable escapes */
     FORMAT_MODIFIER_YEAR,      /* Adds year to date */
     FORMAT_MODIFIER_ZONE,      /* Adds zone to date */
+    FORMAT_MODIFIER_EPOCH,     /* Print time as seconds since Jan 1 1970 */
+    FORMAT_MODIFIER_MONOTONIC, /* Print cpu time as seconds since start */
 } AndroidLogPrintFormat;
 
 typedef struct AndroidLogFormat_t AndroidLogFormat;
diff --git a/init/Android.mk b/init/Android.mk
index 8e45a7a..d6cb4e5 100644
--- a/init/Android.mk
+++ b/init/Android.mk
@@ -92,9 +92,9 @@
     libbase \
     libext4_utils_static \
     libutils \
-    liblog \
     libc \
     libselinux \
+    liblog \
     libmincrypt \
     libcrypto_static \
     libc++_static \
diff --git a/init/bootchart.cpp b/init/bootchart.cpp
index a768762..e1e0c48 100644
--- a/init/bootchart.cpp
+++ b/init/bootchart.cpp
@@ -89,7 +89,7 @@
     if (out == NULL) {
         return;
     }
-    fprintf(out, "version = Android init 0.8 " __TIME__  "\n");
+    fprintf(out, "version = Android init 0.8\n");
     fprintf(out, "title = Boot chart for Android (%s)\n", date);
     fprintf(out, "system.uname = %s %s %s %s\n", uts.sysname, uts.release, uts.version, uts.machine);
     fprintf(out, "system.release = %s\n", fingerprint.c_str());
diff --git a/libbinderwrapper/real_binder_wrapper.cc b/libbinderwrapper/real_binder_wrapper.cc
index adff19b..1c51822 100644
--- a/libbinderwrapper/real_binder_wrapper.cc
+++ b/libbinderwrapper/real_binder_wrapper.cc
@@ -19,6 +19,7 @@
 #include <base/logging.h>
 #include <binder/Binder.h>
 #include <binder/IBinder.h>
+#include <binder/IPCThreadState.h>
 #include <binder/IServiceManager.h>
 
 namespace android {
@@ -111,4 +112,12 @@
   return true;
 }
 
+uid_t RealBinderWrapper::GetCallingUid() {
+  return IPCThreadState::self()->getCallingUid();
+}
+
+pid_t RealBinderWrapper::GetCallingPid() {
+  return IPCThreadState::self()->getCallingPid();
+}
+
 }  // namespace android
diff --git a/libbinderwrapper/real_binder_wrapper.h b/libbinderwrapper/real_binder_wrapper.h
index 8e281f2..ea08371 100644
--- a/libbinderwrapper/real_binder_wrapper.h
+++ b/libbinderwrapper/real_binder_wrapper.h
@@ -38,6 +38,8 @@
   bool RegisterForDeathNotifications(const sp<IBinder>& binder,
                                      const base::Closure& callback) override;
   bool UnregisterForDeathNotifications(const sp<IBinder>& binder) override;
+  uid_t GetCallingUid() override;
+  pid_t GetCallingPid() override;
 
  private:
   class DeathRecipient;
diff --git a/libbinderwrapper/stub_binder_wrapper.cc b/libbinderwrapper/stub_binder_wrapper.cc
index 1d24681..87c6ab7 100644
--- a/libbinderwrapper/stub_binder_wrapper.cc
+++ b/libbinderwrapper/stub_binder_wrapper.cc
@@ -22,7 +22,9 @@
 
 namespace android {
 
-StubBinderWrapper::StubBinderWrapper() = default;
+StubBinderWrapper::StubBinderWrapper()
+    : calling_uid_(-1),
+      calling_pid_(-1) {}
 
 StubBinderWrapper::~StubBinderWrapper() = default;
 
@@ -73,4 +75,12 @@
   return true;
 }
 
+uid_t StubBinderWrapper::GetCallingUid() {
+  return calling_uid_;
+}
+
+pid_t StubBinderWrapper::GetCallingPid() {
+  return calling_pid_;
+}
+
 }  // namespace android
diff --git a/liblog/log_is_loggable.c b/liblog/log_is_loggable.c
index cd85ff6..814d96d 100644
--- a/liblog/log_is_loggable.c
+++ b/liblog/log_is_loggable.c
@@ -176,3 +176,28 @@
     int logLevel = __android_log_level(tag, def);
     return logLevel >= 0 && prio >= logLevel;
 }
+
+char android_log_timestamp()
+{
+    static struct cache r_time_cache = { NULL, -1, 0 };
+    static struct cache p_time_cache = { NULL, -1, 0 };
+    static uint32_t serial;
+    uint32_t current_serial;
+    char retval;
+
+    pthread_mutex_lock(&lock);
+
+    current_serial = __system_property_area_serial();
+    if (current_serial != serial) {
+        refresh_cache(&r_time_cache, "ro.logd.timestamp");
+        refresh_cache(&p_time_cache, "persist.logd.timestamp");
+        serial = current_serial;
+    }
+    if (!(retval = p_time_cache.c)) {
+        retval = r_time_cache.c;
+    }
+
+    pthread_mutex_unlock(&lock);
+
+    return tolower(retval ?: 'r');
+}
diff --git a/liblog/logprint.c b/liblog/logprint.c
index b6dba2e..0ea2269 100644
--- a/liblog/logprint.c
+++ b/liblog/logprint.c
@@ -29,9 +29,13 @@
 #include <inttypes.h>
 #include <sys/param.h>
 
+#include <cutils/list.h>
 #include <log/logd.h>
 #include <log/logprint.h>
 
+#define MS_PER_NSEC 1000000
+#define US_PER_NSEC 1000
+
 /* open coded fragment, prevent circular dependencies */
 #define WEAK static
 
@@ -50,6 +54,8 @@
     bool printable_output;
     bool year_output;
     bool zone_output;
+    bool epoch_output;
+    bool monotonic_output;
 };
 
 /*
@@ -196,10 +202,14 @@
     p_ret->printable_output = false;
     p_ret->year_output = false;
     p_ret->zone_output = false;
+    p_ret->epoch_output = false;
+    p_ret->monotonic_output = false;
 
     return p_ret;
 }
 
+static list_declare(convertHead);
+
 void android_log_format_free(AndroidLogFormat *p_format)
 {
     FilterInfo *p_info, *p_info_old;
@@ -214,10 +224,15 @@
     }
 
     free(p_format);
+
+    /* Free conversion resource, can always be reconstructed */
+    while (!list_empty(&convertHead)) {
+        struct listnode *node = list_head(&convertHead);
+        list_remove(node);
+        free(node);
+    }
 }
 
-
-
 int android_log_setPrintFormat(AndroidLogFormat *p_format,
         AndroidLogPrintFormat format)
 {
@@ -237,6 +252,12 @@
     case FORMAT_MODIFIER_ZONE:
         p_format->zone_output = !p_format->zone_output;
         return 0;
+    case FORMAT_MODIFIER_EPOCH:
+        p_format->epoch_output = true;
+        return 0;
+    case FORMAT_MODIFIER_MONOTONIC:
+        p_format->monotonic_output = true;
+        return 0;
     default:
         break;
     }
@@ -267,6 +288,8 @@
     else if (strcmp(formatString, "printable") == 0) format = FORMAT_MODIFIER_PRINTABLE;
     else if (strcmp(formatString, "year") == 0) format = FORMAT_MODIFIER_YEAR;
     else if (strcmp(formatString, "zone") == 0) format = FORMAT_MODIFIER_ZONE;
+    else if (strcmp(formatString, "epoch") == 0) format = FORMAT_MODIFIER_EPOCH;
+    else if (strcmp(formatString, "monotonic") == 0) format = FORMAT_MODIFIER_MONOTONIC;
     else {
         extern char *tzname[2];
         static const char gmt[] = "GMT";
@@ -913,6 +936,285 @@
     return p - begin;
 }
 
+char *readSeconds(char *e, struct timespec *t)
+{
+    unsigned long multiplier;
+    char *p;
+    t->tv_sec = strtoul(e, &p, 10);
+    if (*p != '.') {
+        return NULL;
+    }
+    t->tv_nsec = 0;
+    multiplier = NS_PER_SEC;
+    while (isdigit(*++p) && (multiplier /= 10)) {
+        t->tv_nsec += (*p - '0') * multiplier;
+    }
+    return p;
+}
+
+static struct timespec *sumTimespec(struct timespec *left,
+                                    struct timespec *right)
+{
+    left->tv_nsec += right->tv_nsec;
+    left->tv_sec += right->tv_sec;
+    if (left->tv_nsec >= (long)NS_PER_SEC) {
+        left->tv_nsec -= NS_PER_SEC;
+        left->tv_sec += 1;
+    }
+    return left;
+}
+
+static struct timespec *subTimespec(struct timespec *result,
+                                    struct timespec *left,
+                                    struct timespec *right)
+{
+    result->tv_nsec = left->tv_nsec - right->tv_nsec;
+    result->tv_sec = left->tv_sec - right->tv_sec;
+    if (result->tv_nsec < 0) {
+        result->tv_nsec += NS_PER_SEC;
+        result->tv_sec -= 1;
+    }
+    return result;
+}
+
+static long long nsecTimespec(struct timespec *now)
+{
+    return (long long)now->tv_sec * NS_PER_SEC + now->tv_nsec;
+}
+
+static void convertMonotonic(struct timespec *result,
+                             const AndroidLogEntry *entry)
+{
+    struct listnode *node;
+    struct conversionList {
+        struct listnode node; /* first */
+        struct timespec time;
+        struct timespec convert;
+    } *list, *next;
+    struct timespec time, convert;
+
+    /* If we do not have a conversion list, build one up */
+    if (list_empty(&convertHead)) {
+        bool suspended_pending = false;
+        struct timespec suspended_monotonic = { 0, 0 };
+        struct timespec suspended_diff = { 0, 0 };
+
+        /*
+         * Read dmesg for _some_ synchronization markers and insert
+         * Anything in the Android Logger before the dmesg logging span will
+         * be highly suspect regarding the monotonic time calculations.
+         */
+        FILE *p = popen("/system/bin/dmesg", "r");
+        if (p) {
+            char *line = NULL;
+            size_t len = 0;
+            while (getline(&line, &len, p) > 0) {
+                static const char suspend[] = "PM: suspend entry ";
+                static const char resume[] = "PM: suspend exit ";
+                static const char healthd[] = "healthd";
+                static const char battery[] = ": battery ";
+                static const char suspended[] = "Suspended for ";
+                struct timespec monotonic;
+                struct tm tm;
+                char *cp, *e = line;
+                bool add_entry = true;
+
+                if (*e == '<') {
+                    while (*e && (*e != '>')) {
+                        ++e;
+                    }
+                    if (*e != '>') {
+                        continue;
+                    }
+                }
+                if (*e != '[') {
+                    continue;
+                }
+                while (*++e == ' ') {
+                    ;
+                }
+                e = readSeconds(e, &monotonic);
+                if (!e || (*e != ']')) {
+                    continue;
+                }
+
+                if ((e = strstr(e, suspend))) {
+                    e += sizeof(suspend) - 1;
+                } else if ((e = strstr(line, resume))) {
+                    e += sizeof(resume) - 1;
+                } else if (((e = strstr(line, healthd)))
+                        && ((e = strstr(e + sizeof(healthd) - 1, battery)))) {
+                    /* NB: healthd is roughly 150us late, worth the price to
+                     * deal with ntp-induced or hardware clock drift. */
+                    e += sizeof(battery) - 1;
+                } else if ((e = strstr(line, suspended))) {
+                    e += sizeof(suspended) - 1;
+                    e = readSeconds(e, &time);
+                    if (!e) {
+                        continue;
+                    }
+                    add_entry = false;
+                    suspended_pending = true;
+                    suspended_monotonic = monotonic;
+                    suspended_diff = time;
+                } else {
+                    continue;
+                }
+                if (add_entry) {
+                    /* look for "????-??-?? ??:??:??.????????? UTC" */
+                    cp = strstr(e, " UTC");
+                    if (!cp || ((cp - e) < 29) || (cp[-10] != '.')) {
+                        continue;
+                    }
+                    e = cp - 29;
+                    cp = readSeconds(cp - 10, &time);
+                    if (!cp) {
+                        continue;
+                    }
+                    cp = strptime(e, "%Y-%m-%d %H:%M:%S.", &tm);
+                    if (!cp) {
+                        continue;
+                    }
+                    cp = getenv(tz);
+                    if (cp) {
+                        cp = strdup(cp);
+                    }
+                    setenv(tz, utc, 1);
+                    time.tv_sec = mktime(&tm);
+                    if (cp) {
+                        setenv(tz, cp, 1);
+                        free(cp);
+                    } else {
+                        unsetenv(tz);
+                    }
+                    list = calloc(1, sizeof(struct conversionList));
+                    list_init(&list->node);
+                    list->time = time;
+                    subTimespec(&list->convert, &time, &monotonic);
+                    list_add_tail(&convertHead, &list->node);
+                }
+                if (suspended_pending && !list_empty(&convertHead)) {
+                    list = node_to_item(list_tail(&convertHead),
+                                        struct conversionList, node);
+                    if (subTimespec(&time,
+                                    subTimespec(&time,
+                                                &list->time,
+                                                &list->convert),
+                                    &suspended_monotonic)->tv_sec > 0) {
+                        /* resume, what is convert factor before? */
+                        subTimespec(&convert, &list->convert, &suspended_diff);
+                    } else {
+                        /* suspend */
+                        convert = list->convert;
+                    }
+                    time = suspended_monotonic;
+                    sumTimespec(&time, &convert);
+                    /* breakpoint just before sleep */
+                    list = calloc(1, sizeof(struct conversionList));
+                    list_init(&list->node);
+                    list->time = time;
+                    list->convert = convert;
+                    list_add_tail(&convertHead, &list->node);
+                    /* breakpoint just after sleep */
+                    list = calloc(1, sizeof(struct conversionList));
+                    list_init(&list->node);
+                    list->time = time;
+                    sumTimespec(&list->time, &suspended_diff);
+                    list->convert = convert;
+                    sumTimespec(&list->convert, &suspended_diff);
+                    list_add_tail(&convertHead, &list->node);
+                    suspended_pending = false;
+                }
+            }
+            pclose(p);
+        }
+        /* last entry is our current time conversion */
+        list = calloc(1, sizeof(struct conversionList));
+        list_init(&list->node);
+        clock_gettime(CLOCK_REALTIME, &list->time);
+        clock_gettime(CLOCK_MONOTONIC, &convert);
+        clock_gettime(CLOCK_MONOTONIC, &time);
+        /* Correct for instant clock_gettime latency (syscall or ~30ns) */
+        subTimespec(&time, &convert, subTimespec(&time, &time, &convert));
+        /* Calculate conversion factor */
+        subTimespec(&list->convert, &list->time, &time);
+        list_add_tail(&convertHead, &list->node);
+        if (suspended_pending) {
+            /* manufacture a suspend @ point before */
+            subTimespec(&convert, &list->convert, &suspended_diff);
+            time = suspended_monotonic;
+            sumTimespec(&time, &convert);
+            /* breakpoint just after sleep */
+            list = calloc(1, sizeof(struct conversionList));
+            list_init(&list->node);
+            list->time = time;
+            sumTimespec(&list->time, &suspended_diff);
+            list->convert = convert;
+            sumTimespec(&list->convert, &suspended_diff);
+            list_add_head(&convertHead, &list->node);
+            /* breakpoint just before sleep */
+            list = calloc(1, sizeof(struct conversionList));
+            list_init(&list->node);
+            list->time = time;
+            list->convert = convert;
+            list_add_head(&convertHead, &list->node);
+        }
+    }
+
+    /* Find the breakpoint in the conversion list */
+    list = node_to_item(list_head(&convertHead), struct conversionList, node);
+    next = NULL;
+    list_for_each(node, &convertHead) {
+        next = node_to_item(node, struct conversionList, node);
+        if (entry->tv_sec < next->time.tv_sec) {
+            break;
+        } else if (entry->tv_sec == next->time.tv_sec) {
+            if (entry->tv_nsec < next->time.tv_nsec) {
+                break;
+            }
+        }
+        list = next;
+    }
+
+    /* blend time from one breakpoint to the next */
+    convert = list->convert;
+    if (next) {
+        unsigned long long total, run;
+
+        total = nsecTimespec(subTimespec(&time, &next->time, &list->time));
+        time.tv_sec = entry->tv_sec;
+        time.tv_nsec = entry->tv_nsec;
+        run = nsecTimespec(subTimespec(&time, &time, &list->time));
+        if (run < total) {
+            long long crun;
+
+            float f = nsecTimespec(subTimespec(&time, &next->convert, &convert));
+            f *= run;
+            f /= total;
+            crun = f;
+            convert.tv_sec += crun / (long long)NS_PER_SEC;
+            if (crun < 0) {
+                convert.tv_nsec -= (-crun) % NS_PER_SEC;
+                if (convert.tv_nsec < 0) {
+                    convert.tv_nsec += NS_PER_SEC;
+                    convert.tv_sec -= 1;
+                }
+            } else {
+                convert.tv_nsec += crun % NS_PER_SEC;
+                if (convert.tv_nsec >= (long)NS_PER_SEC) {
+                    convert.tv_nsec -= NS_PER_SEC;
+                    convert.tv_sec += 1;
+                }
+            }
+        }
+    }
+
+    /* Apply the correction factor */
+    result->tv_sec = entry->tv_sec;
+    result->tv_nsec = entry->tv_nsec;
+    subTimespec(result, result, &convert);
+}
+
 /**
  * Formats a log message into a buffer
  *
@@ -936,7 +1238,9 @@
     char prefixBuf[128], suffixBuf[128];
     char priChar;
     int prefixSuffixIsHeaderFooter = 0;
-    char * ret = NULL;
+    char *ret = NULL;
+    time_t now;
+    unsigned long nsec;
 
     priChar = filterPriToChar(entry->priority);
     size_t prefixLen = 0, suffixLen = 0;
@@ -954,23 +1258,41 @@
      * The caller may have affected the timezone environment, this is
      * expected to be sensitive to that.
      */
+    now = entry->tv_sec;
+    nsec = entry->tv_nsec;
+    if (p_format->monotonic_output) {
+        struct timespec time;
+        convertMonotonic(&time, entry);
+        now = time.tv_sec;
+        nsec = time.tv_nsec;
+    }
+    if (now < 0) {
+        nsec = NS_PER_SEC - nsec;
+    }
+    if (p_format->epoch_output || p_format->monotonic_output) {
+        ptm = NULL;
+        snprintf(timeBuf, sizeof(timeBuf),
+                 p_format->monotonic_output ? "%6lld" : "%19lld",
+                 (long long)now);
+    } else {
 #if !defined(_WIN32)
-    ptm = localtime_r(&(entry->tv_sec), &tmBuf);
+        ptm = localtime_r(&now, &tmBuf);
 #else
-    ptm = localtime(&(entry->tv_sec));
+        ptm = localtime(&now);
 #endif
-    strftime(timeBuf, sizeof(timeBuf),
-             &"%Y-%m-%d %H:%M:%S"[p_format->year_output ? 0 : 3],
-             ptm);
+        strftime(timeBuf, sizeof(timeBuf),
+                 &"%Y-%m-%d %H:%M:%S"[p_format->year_output ? 0 : 3],
+                 ptm);
+    }
     len = strlen(timeBuf);
     if (p_format->usec_time_output) {
         len += snprintf(timeBuf + len, sizeof(timeBuf) - len,
-                        ".%06ld", entry->tv_nsec / 1000);
+                        ".%06ld", nsec / US_PER_NSEC);
     } else {
         len += snprintf(timeBuf + len, sizeof(timeBuf) - len,
-                        ".%03ld", entry->tv_nsec / 1000000);
+                        ".%03ld", nsec / MS_PER_NSEC);
     }
-    if (p_format->zone_output) {
+    if (p_format->zone_output && ptm) {
         strftime(timeBuf + len, sizeof(timeBuf) - len, " %z", ptm);
     }
 
diff --git a/libpixelflinger/include/private/pixelflinger/ggl_context.h b/libpixelflinger/include/private/pixelflinger/ggl_context.h
index d43655c..a18b2f7 100644
--- a/libpixelflinger/include/private/pixelflinger/ggl_context.h
+++ b/libpixelflinger/include/private/pixelflinger/ggl_context.h
@@ -234,7 +234,7 @@
 
 // ----------------------------------------------------------------------------
 
-class needs_filter_t;
+struct needs_filter_t;
 struct needs_t {
     inline int match(const needs_filter_t& filter);
     inline bool operator == (const needs_t& rhs) const {
diff --git a/libpixelflinger/trap.cpp b/libpixelflinger/trap.cpp
index 80efeff..ea53625 100644
--- a/libpixelflinger/trap.cpp
+++ b/libpixelflinger/trap.cpp
@@ -563,10 +563,10 @@
     
     c->init_y(c, miny);
     for (int32_t y = miny; y < maxy; y++) {
-        register int32_t ex0 = ey0;
-        register int32_t ex1 = ey1;
-        register int32_t ex2 = ey2;    
-        register int32_t xl, xr;
+        int32_t ex0 = ey0;
+        int32_t ex1 = ey1;
+        int32_t ex2 = ey2;    
+        int32_t xl, xr;
         for (xl=minx ; xl<maxx ; xl++) {
             if (ex0>0 && ex1>0 && ex2>0)
                 break; // all strictly positive
diff --git a/libsparse/simg2img.c b/libsparse/simg2img.c
index 95e9b5b..b9b438e 100644
--- a/libsparse/simg2img.c
+++ b/libsparse/simg2img.c
@@ -40,7 +40,6 @@
 	int in;
 	int out;
 	int i;
-	int ret;
 	struct sparse_file *s;
 
 	if (argc < 3) {
@@ -71,10 +70,12 @@
 			exit(-1);
 		}
 
-		lseek(out, SEEK_SET, 0);
+		if (lseek(out, 0, SEEK_SET) == -1) {
+			perror("lseek failed");
+			exit(EXIT_FAILURE);
+		}
 
-		ret = sparse_file_write(s, out, false, false, false);
-		if (ret < 0) {
+		if (sparse_file_write(s, out, false, false, false) < 0) {
 			fprintf(stderr, "Cannot write output file\n");
 			exit(-1);
 		}
diff --git a/libsparse/sparse_read.c b/libsparse/sparse_read.c
index 9b10293..ec63850 100644
--- a/libsparse/sparse_read.c
+++ b/libsparse/sparse_read.c
@@ -18,6 +18,7 @@
 #define _FILE_OFFSET_BITS 64
 #define _LARGEFILE64_SOURCE 1
 
+#include <inttypes.h>
 #include <fcntl.h>
 #include <stdarg.h>
 #include <stdbool.h>
@@ -233,7 +234,7 @@
 			ret = process_raw_chunk(s, chunk_data_size, fd, offset,
 					chunk_header->chunk_sz, cur_block, crc_ptr);
 			if (ret < 0) {
-				verbose_error(s->verbose, ret, "data block at %lld", offset);
+				verbose_error(s->verbose, ret, "data block at %" PRId64, offset);
 				return ret;
 			}
 			return chunk_header->chunk_sz;
@@ -241,7 +242,7 @@
 			ret = process_fill_chunk(s, chunk_data_size, fd,
 					chunk_header->chunk_sz, cur_block, crc_ptr);
 			if (ret < 0) {
-				verbose_error(s->verbose, ret, "fill block at %lld", offset);
+				verbose_error(s->verbose, ret, "fill block at %" PRId64, offset);
 				return ret;
 			}
 			return chunk_header->chunk_sz;
@@ -250,7 +251,7 @@
 					chunk_header->chunk_sz, cur_block, crc_ptr);
 			if (chunk_data_size != 0) {
 				if (ret < 0) {
-					verbose_error(s->verbose, ret, "skip block at %lld", offset);
+					verbose_error(s->verbose, ret, "skip block at %" PRId64, offset);
 					return ret;
 				}
 			}
@@ -258,13 +259,13 @@
 		case CHUNK_TYPE_CRC32:
 			ret = process_crc32_chunk(fd, chunk_data_size, *crc_ptr);
 			if (ret < 0) {
-				verbose_error(s->verbose, -EINVAL, "crc block at %lld",
+				verbose_error(s->verbose, -EINVAL, "crc block at %" PRId64,
 						offset);
 				return ret;
 			}
 			return 0;
 		default:
-			verbose_error(s->verbose, -EINVAL, "unknown block %04X at %lld",
+			verbose_error(s->verbose, -EINVAL, "unknown block %04X at %" PRId64,
 					chunk_header->chunk_type, offset);
 	}
 
diff --git a/libutils/LinearTransform.cpp b/libutils/LinearTransform.cpp
index b7d28d4..138ce8b 100644
--- a/libutils/LinearTransform.cpp
+++ b/libutils/LinearTransform.cpp
@@ -21,11 +21,24 @@
 
 #include <utils/LinearTransform.h>
 
+// disable sanitize as these functions may intentionally overflow (see comments below).
+// the ifdef can be removed when host builds use clang.
+#if defined(__clang__)
+#define ATTRIBUTE_NO_SANITIZE_INTEGER __attribute__((no_sanitize("integer")))
+#else
+#define ATTRIBUTE_NO_SANITIZE_INTEGER
+#endif
+
 namespace android {
 
-template<class T> static inline T ABS(T x) { return (x < 0) ? -x : x; }
+// sanitize failure with T = int32_t and x = 0x80000000
+template<class T>
+ATTRIBUTE_NO_SANITIZE_INTEGER
+static inline T ABS(T x) { return (x < 0) ? -x : x; }
 
 // Static math methods involving linear transformations
+// remote sanitize failure on overflow case.
+ATTRIBUTE_NO_SANITIZE_INTEGER
 static bool scale_u64_to_u64(
         uint64_t val,
         uint32_t N,
@@ -109,6 +122,8 @@
     return true;
 }
 
+// at least one known sanitize failure (see comment below)
+ATTRIBUTE_NO_SANITIZE_INTEGER
 static bool linear_transform_s64_to_s64(
         int64_t  val,
         int64_t  basis1,
@@ -172,7 +187,7 @@
         // (scaled_signbit XOR res_signbit)
 
         if (is_neg)
-            scaled = -scaled;
+            scaled = -scaled; // known sanitize failure
         res = scaled + basis2;
 
         if ((scaled ^ basis2 ^ INT64_MIN) & (scaled ^ res) & INT64_MIN)
@@ -250,6 +265,8 @@
 template void LinearTransform::reduce<uint64_t>(uint64_t* N, uint64_t* D);
 template void LinearTransform::reduce<uint32_t>(uint32_t* N, uint32_t* D);
 
+// sanitize failure if *N = 0x80000000
+ATTRIBUTE_NO_SANITIZE_INTEGER
 void LinearTransform::reduce(int32_t* N, uint32_t* D) {
     if (N && D && *D) {
         if (*N < 0) {
diff --git a/libziparchive/zip_archive.cc b/libziparchive/zip_archive.cc
index f1e13a7..3d18f7c 100644
--- a/libziparchive/zip_archive.cc
+++ b/libziparchive/zip_archive.cc
@@ -588,7 +588,7 @@
   // and other interesting attributes from the central directory. These
   // will later be compared against values from the local file header.
   data->method = cdr->compression_method;
-  data->mod_time = cdr->last_mod_time;
+  data->mod_time = cdr->last_mod_date << 16 | cdr->last_mod_time;
   data->crc32 = cdr->crc32;
   data->compressed_length = cdr->compressed_size;
   data->uncompressed_length = cdr->uncompressed_size;
diff --git a/libziparchive/zip_archive_test.cc b/libziparchive/zip_archive_test.cc
index 9a3cdb4..32b1a38 100644
--- a/libziparchive/zip_archive_test.cc
+++ b/libziparchive/zip_archive_test.cc
@@ -272,6 +272,7 @@
   ASSERT_EQ(static_cast<uint32_t>(17), data.uncompressed_length);
   ASSERT_EQ(static_cast<uint32_t>(13), data.compressed_length);
   ASSERT_EQ(0x950821c5, data.crc32);
+  ASSERT_EQ(static_cast<uint32_t>(0x438a8005), data.mod_time);
 
   // An entry that doesn't exist. Should be a negative return code.
   ZipString absent_name;
diff --git a/logcat/logcat.cpp b/logcat/logcat.cpp
index ddbfb3e..cb9a85b 100644
--- a/logcat/logcat.cpp
+++ b/logcat/logcat.cpp
@@ -259,8 +259,8 @@
                     "  -r <kbytes>     Rotate log every kbytes. Requires -f\n"
                     "  -n <count>      Sets max number of rotated logs to <count>, default 4\n"
                     "  -v <format>     Sets the log print format, where <format> is:\n\n"
-                    "                      brief color long printable process raw tag thread\n"
-                    "                      threadtime time usec UTC year zone\n\n"
+                    "                      brief color epoch long monotonic printable process raw\n"
+                    "                      tag thread threadtime time usec UTC year zone\n\n"
                     "  -D              print dividers between each log buffer\n"
                     "  -c              clear (flush) the entire log and exit\n"
                     "  -d              dump the log and then exit (don't block)\n"
@@ -269,7 +269,7 @@
                     "  -T <count>      print only the most recent <count> lines (does not imply -d)\n"
                     "  -T '<time>'     print most recent lines since specified time (not imply -d)\n"
                     "                  count is pure numerical, time is 'MM-DD hh:mm:ss.mmm...'\n"
-                    "                  or 'YYYY-MM-DD hh:mm:ss.mmm...' format\n"
+                    "                  'YYYY-MM-DD hh:mm:ss.mmm...' or 'sssss.mmm...' format\n"
                     "  -g              get the size of the log's ring buffer and exit\n"
                     "  -L              dump logs from prior to last reboot\n"
                     "  -b <buffer>     Request alternate ring buffer, 'main', 'system', 'radio',\n"
@@ -384,7 +384,11 @@
     if (ep) {
         return ep;
     }
-    return t.strptime(cp, "%Y-%m-%d %H:%M:%S.%q");
+    ep = t.strptime(cp, "%Y-%m-%d %H:%M:%S.%q");
+    if (ep) {
+        return ep;
+    }
+    return t.strptime(cp, "%s.%q");
 }
 
 // Find last logged line in gestalt of all matching existing output files
diff --git a/logd/Android.mk b/logd/Android.mk
index c00061b..feca8d5 100644
--- a/logd/Android.mk
+++ b/logd/Android.mk
@@ -27,7 +27,8 @@
     libsysutils \
     liblog \
     libcutils \
-    libbase
+    libbase \
+    libpackagelistparser
 
 # This is what we want to do:
 #  event_logtags = $(shell \
diff --git a/logd/main.cpp b/logd/main.cpp
index 60262e9..13dda78 100644
--- a/logd/main.cpp
+++ b/logd/main.cpp
@@ -33,12 +33,14 @@
 #include <syslog.h>
 #include <unistd.h>
 
+#include <cstdbool>
 #include <memory>
 
 #include <cutils/properties.h>
 #include <cutils/sched_policy.h>
 #include <cutils/sockets.h>
 #include <log/event_tag_map.h>
+#include <packagelistparser/packagelistparser.h>
 #include <private/android_filesystem_config.h>
 #include <utils/threads.h>
 
@@ -166,6 +168,19 @@
 static bool reinit_running = false;
 static LogBuffer *logBuf = NULL;
 
+static bool package_list_parser_cb(pkg_info *info, void * /* userdata */) {
+
+    bool rc = true;
+    if (info->uid == uid) {
+        name = strdup(info->name);
+        // false to stop processing
+        rc = false;
+    }
+
+    packagelist_free(info);
+    return rc;
+}
+
 static void *reinit_thread_start(void * /*obj*/) {
     prctl(PR_SET_NAME, "logd.daemon");
     set_sched_policy(0, SP_BACKGROUND);
@@ -180,31 +195,8 @@
         if (uid) {
             name = NULL;
 
-            FILE *fp = fopen("/data/system/packages.list", "r");
-            if (fp) {
-                // This simple parser is sensitive to format changes in
-                // frameworks/base/services/core/java/com/android/server/pm/Settings.java
-                // A dependency note has been added to that file to correct
-                // this parser.
+            packagelist_parse(package_list_parser_cb, NULL);
 
-                char *buffer = NULL;
-                size_t len;
-                while (getline(&buffer, &len, fp) > 0) {
-                    char *userId = strchr(buffer, ' ');
-                    if (!userId) {
-                        continue;
-                    }
-                    *userId = '\0';
-                    unsigned long value = strtoul(userId + 1, NULL, 10);
-                    if (value != uid) {
-                        continue;
-                    }
-                    name = strdup(buffer);
-                    break;
-                }
-                free(buffer);
-                fclose(fp);
-            }
             uid = 0;
             sem_post(&uidName);
             continue;
diff --git a/metricsd/Android.mk b/metricsd/Android.mk
index 8dbaad9..b08c153 100644
--- a/metricsd/Android.mk
+++ b/metricsd/Android.mk
@@ -64,11 +64,11 @@
   -fvisibility=default
 metrics_includes := external/gtest/include \
   $(LOCAL_PATH)/include
-libmetrics_shared_libraries := libchrome libchromeos
+libmetrics_shared_libraries := libchrome libbrillo
 metrics_daemon_shared_libraries := $(libmetrics_shared_libraries) \
+  libbrillo-http \
+  libbrillo-dbus \
   libchrome-dbus \
-  libchromeos-http \
-  libchromeos-dbus \
   libdbus \
   libmetrics \
   libprotobuf-cpp-lite \
@@ -120,8 +120,7 @@
 # ========================================================
 include $(CLEAR_VARS)
 LOCAL_MODULE := metrics_daemon
-LOCAL_C_INCLUDES := $(metrics_includes) \
-  external/libchromeos
+LOCAL_C_INCLUDES := $(metrics_includes)
 LOCAL_CFLAGS := $(metrics_CFLAGS)
 LOCAL_CPP_EXTENSION := $(metrics_cpp_extension)
 LOCAL_CPPFLAGS := $(metrics_CPPFLAGS)
diff --git a/metricsd/libmetrics.gypi b/metricsd/libmetrics.gypi
index 5b90a55..3c8fc7c 100644
--- a/metricsd/libmetrics.gypi
+++ b/metricsd/libmetrics.gypi
@@ -2,8 +2,8 @@
   'target_defaults': {
     'variables': {
       'deps': [
+        'libbrillo-<(libbase_ver)',
         'libchrome-<(libbase_ver)',
-        'libchromeos-<(libbase_ver)',
       ]
     },
     'cflags_cc': [
diff --git a/metricsd/metrics.gyp b/metricsd/metrics.gyp
index 276ec78..c9c02d7 100644
--- a/metricsd/metrics.gyp
+++ b/metricsd/metrics.gyp
@@ -3,8 +3,8 @@
     'variables': {
       'deps': [
         'dbus-1',
+        'libbrillo-<(libbase_ver)',
         'libchrome-<(libbase_ver)',
-        'libchromeos-<(libbase_ver)',
       ]
     },
     'cflags_cc': [
diff --git a/metricsd/uploader/metrics_log_base.cc b/metricsd/uploader/metrics_log_base.cc
index 311e43a..1a60b4f 100644
--- a/metricsd/uploader/metrics_log_base.cc
+++ b/metricsd/uploader/metrics_log_base.cc
@@ -16,6 +16,7 @@
 
 #include "uploader/metrics_log_base.h"
 
+#include "base/build_time.h"
 #include "base/metrics/histogram_base.h"
 #include "base/metrics/histogram_samples.h"
 #include "uploader/metrics_hashes.h"
@@ -82,10 +83,7 @@
 int64_t MetricsLogBase::GetBuildTime() {
   static int64_t integral_build_time = 0;
   if (!integral_build_time) {
-    Time time;
-    const char* kDateTime = __DATE__ " " __TIME__ " GMT";
-    bool result = Time::FromString(kDateTime, &time);
-    DCHECK(result);
+    Time time = base::GetBuildTime();
     integral_build_time = static_cast<int64_t>(time.ToTimeT());
   }
   return integral_build_time;
diff --git a/metricsd/uploader/sender_http.h b/metricsd/uploader/sender_http.h
index 6249d90..4f1c08f 100644
--- a/metricsd/uploader/sender_http.h
+++ b/metricsd/uploader/sender_http.h
@@ -23,7 +23,7 @@
 
 #include "uploader/sender.h"
 
-// Sender implemented using http_utils from libchromeos
+// Sender implemented using http_utils from libbrillo
 class HttpSender : public Sender {
  public:
   explicit HttpSender(std::string server_url);
diff --git a/packagelistparser/Android.mk b/packagelistparser/Android.mk
new file mode 100644
index 0000000..802a3cb
--- /dev/null
+++ b/packagelistparser/Android.mk
@@ -0,0 +1,32 @@
+LOCAL_PATH:= $(call my-dir)
+
+#########################
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := libpackagelistparser
+LOCAL_MODULE_TAGS := optional
+LOCAL_SRC_FILES := packagelistparser.c
+LOCAL_COPY_HEADERS_TO := packagelistparser
+LOCAL_COPY_HEADERS := packagelistparser.h
+LOCAL_SHARED_LIBRARIES := liblog
+
+LOCAL_CLANG := true
+LOCAL_SANITIZE := integer
+
+include $(BUILD_SHARED_LIBRARY)
+
+#########################
+include $(CLEAR_VARS)
+
+
+LOCAL_MODULE := libpackagelistparser
+LOCAL_MODULE_TAGS := optional
+LOCAL_SRC_FILES := packagelistparser.c
+LOCAL_COPY_HEADERS_TO := packagelistparser
+LOCAL_COPY_HEADERS := packagelistparser.h
+LOCAL_STATIC_LIBRARIES := liblog
+
+LOCAL_CLANG := true
+LOCAL_SANITIZE := integer
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/packagelistparser/packagelistparser.c b/packagelistparser/packagelistparser.c
new file mode 100644
index 0000000..3e2539c
--- /dev/null
+++ b/packagelistparser/packagelistparser.c
@@ -0,0 +1,266 @@
+/*
+ * Copyright 2015, Intel Corporation
+ * 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.
+ *
+ * Written by William Roberts <william.c.roberts@intel.com>
+ *
+ */
+
+#include <errno.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <sys/limits.h>
+
+#define LOG_TAG "packagelistparser"
+#include <utils/Log.h>
+
+#include "packagelistparser.h"
+
+#define CLOGE(fmt, ...) \
+    do {\
+        IF_ALOGE() {\
+            ALOGE(fmt, ##__VA_ARGS__);\
+        }\
+    } while(0)
+
+static size_t get_gid_cnt(const char *gids)
+{
+    size_t cnt;
+
+    if (*gids == '\0') {
+        return 0;
+    }
+
+    if (!strcmp(gids, "none")) {
+        return 0;
+    }
+
+    for (cnt = 1; gids[cnt]; gids[cnt] == ',' ? cnt++ : *gids++)
+        ;
+
+    return cnt;
+}
+
+static bool parse_gids(char *gids, gid_t *gid_list, size_t *cnt)
+{
+    gid_t gid;
+    char* token;
+    char *endptr;
+    size_t cmp = 0;
+
+    while ((token = strsep(&gids, ",\r\n"))) {
+
+        if (cmp > *cnt) {
+            return false;
+        }
+
+        gid = strtoul(token, &endptr, 10);
+        if (*endptr != '\0') {
+            return false;
+        }
+
+        /*
+         * if unsigned long is greater than size of gid_t,
+         * prevent a truncation based roll-over
+         */
+        if (gid > GID_MAX) {
+            CLOGE("A gid in field \"gid list\" greater than GID_MAX");
+            return false;
+        }
+
+        gid_list[cmp++] = gid;
+    }
+    return true;
+}
+
+extern bool packagelist_parse(pfn_on_package callback, void *userdata)
+{
+
+    FILE *fp;
+    char *cur;
+    char *next;
+    char *endptr;
+    unsigned long tmp;
+    ssize_t bytesread;
+
+    bool rc = false;
+    char *buf = NULL;
+    size_t buflen = 0;
+    unsigned long lineno = 1;
+    const char *errmsg = NULL;
+    struct pkg_info *pkg_info = NULL;
+
+    fp = fopen(PACKAGES_LIST_FILE, "re");
+    if (!fp) {
+        CLOGE("Could not open: \"%s\", error: \"%s\"\n", PACKAGES_LIST_FILE,
+                strerror(errno));
+        return false;
+    }
+
+    while ((bytesread = getline(&buf, &buflen, fp)) > 0) {
+
+        pkg_info = calloc(1, sizeof(*pkg_info));
+        if (!pkg_info) {
+            goto err;
+        }
+
+        next = buf;
+
+        cur = strsep(&next, " \t\r\n");
+        if (!cur) {
+            errmsg = "Could not get next token for \"package name\"";
+            goto err;
+        }
+
+        pkg_info->name = strdup(cur);
+        if (!pkg_info->name) {
+            goto err;
+        }
+
+        cur = strsep(&next, " \t\r\n");
+        if (!cur) {
+            errmsg = "Could not get next token for field \"uid\"";
+            goto err;
+        }
+
+        tmp = strtoul(cur, &endptr, 10);
+        if (*endptr != '\0') {
+            errmsg = "Could not convert field \"uid\" to integer value";
+            goto err;
+        }
+
+        /*
+         * if unsigned long is greater than size of uid_t,
+         * prevent a truncation based roll-over
+         */
+        if (tmp > UID_MAX) {
+            errmsg = "Field \"uid\" greater than UID_MAX";
+            goto err;
+        }
+
+        pkg_info->uid = (uid_t) tmp;
+
+        cur = strsep(&next, " \t\r\n");
+        if (!cur) {
+            errmsg = "Could not get next token for field \"debuggable\"";
+            goto err;
+        }
+
+        tmp = strtoul(cur, &endptr, 10);
+        if (*endptr != '\0') {
+            errmsg = "Could not convert field \"debuggable\" to integer value";
+            goto err;
+        }
+
+        /* should be a valid boolean of 1 or 0 */
+        if (!(tmp == 0 || tmp == 1)) {
+            errmsg = "Field \"debuggable\" is not 0 or 1 boolean value";
+            goto err;
+        }
+
+        pkg_info->debuggable = (bool) tmp;
+
+        cur = strsep(&next, " \t\r\n");
+        if (!cur) {
+            errmsg = "Could not get next token for field \"data dir\"";
+            goto err;
+        }
+
+        pkg_info->data_dir = strdup(cur);
+        if (!pkg_info->data_dir) {
+            goto err;
+        }
+
+        cur = strsep(&next, " \t\r\n");
+        if (!cur) {
+            errmsg = "Could not get next token for field \"seinfo\"";
+            goto err;
+        }
+
+        pkg_info->seinfo = strdup(cur);
+        if (!pkg_info->seinfo) {
+            goto err;
+        }
+
+        cur = strsep(&next, " \t\r\n");
+        if (!cur) {
+            errmsg = "Could not get next token for field \"gid(s)\"";
+            goto err;
+        }
+
+        /*
+         * Parse the gid list, could be in the form of none, single gid or list:
+         * none
+         * gid
+         * gid, gid ...
+         */
+        pkg_info->gids.cnt = get_gid_cnt(cur);
+        if (pkg_info->gids.cnt > 0) {
+
+            pkg_info->gids.gids = calloc(pkg_info->gids.cnt, sizeof(gid_t));
+            if (!pkg_info->gids.gids) {
+                goto err;
+            }
+
+            rc = parse_gids(cur, pkg_info->gids.gids, &pkg_info->gids.cnt);
+            if (!rc) {
+                errmsg = "Could not parse field \"gid list\"";
+                goto err;
+            }
+        }
+
+        rc = callback(pkg_info, userdata);
+        if (rc == false) {
+            /*
+             * We do not log this as this can be intentional from
+             * callback to abort processing. We go to out to not
+             * free the pkg_info
+             */
+            rc = true;
+            goto out;
+        }
+        lineno++;
+    }
+
+    rc = true;
+
+out:
+    free(buf);
+    fclose(fp);
+    return rc;
+
+err:
+    if (errmsg) {
+        CLOGE("Error Parsing \"%s\" on line: %lu for reason: %s",
+                PACKAGES_LIST_FILE, lineno, errmsg);
+    }
+    rc = false;
+    packagelist_free(pkg_info);
+    goto out;
+}
+
+void packagelist_free(pkg_info *info)
+{
+    if (info) {
+        free(info->name);
+        free(info->data_dir);
+        free(info->seinfo);
+        free(info->gids.gids);
+        free(info);
+    }
+}
diff --git a/packagelistparser/packagelistparser.h b/packagelistparser/packagelistparser.h
new file mode 100644
index 0000000..d602c26
--- /dev/null
+++ b/packagelistparser/packagelistparser.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2015, Intel Corporation
+ * 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.
+ *
+ * Written by William Roberts <william.c.roberts@intel.com>
+ *
+ * This is a parser library for parsing the packages.list file generated
+ * by PackageManager service.
+ *
+ * This simple parser is sensitive to format changes in
+ * frameworks/base/services/core/java/com/android/server/pm/Settings.java
+ * A dependency note has been added to that file to correct
+ * this parser.
+ */
+
+#ifndef PACKAGELISTPARSER_H_
+#define PACKAGELISTPARSER_H_
+
+#include <stdbool.h>
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+__BEGIN_DECLS
+
+/** The file containing the list of installed packages on the system */
+#define PACKAGES_LIST_FILE  "/data/system/packages.list"
+
+typedef struct pkg_info pkg_info;
+typedef struct gid_list gid_list;
+
+struct gid_list {
+    size_t cnt;
+    gid_t *gids;
+};
+
+struct pkg_info {
+    char *name;
+    uid_t uid;
+    bool debuggable;
+    char *data_dir;
+    char *seinfo;
+    gid_list gids;
+    void *private_data;
+};
+
+/**
+ * Callback function to be used by packagelist_parse() routine.
+ * @param info
+ *  The parsed package information
+ * @param userdata
+ *  The supplied userdata pointer to packagelist_parse()
+ * @return
+ *  true to keep processing, false to stop.
+ */
+typedef bool (*pfn_on_package)(pkg_info *info, void *userdata);
+
+/**
+ * Parses the file specified by PACKAGES_LIST_FILE and invokes the callback on
+ * each entry found. Once the callback is invoked, ownership of the pkg_info pointer
+ * is passed to the callback routine, thus they are required to perform any cleanup
+ * desired.
+ * @param callback
+ *  The callback function called on each parsed line of the packages list.
+ * @param userdata
+ *  An optional userdata supplied pointer to pass to the callback function.
+ * @return
+ *  true on success false on failure.
+ */
+extern bool packagelist_parse(pfn_on_package callback, void *userdata);
+
+/**
+ * Frees a pkg_info structure.
+ * @param info
+ *  The struct to free
+ */
+extern void packagelist_free(pkg_info *info);
+
+__END_DECLS
+
+#endif /* PACKAGELISTPARSER_H_ */
diff --git a/rootdir/asan.options b/rootdir/asan.options
index 2f12341..43896a1 100644
--- a/rootdir/asan.options
+++ b/rootdir/asan.options
@@ -1 +1,5 @@
-allow_user_segv_handler=1:detect_odr_violation=0:alloc_dealloc_mismatch=0:allocator_may_return_null=1
+allow_user_segv_handler=1
+detect_odr_violation=0
+alloc_dealloc_mismatch=0
+allocator_may_return_null=1
+detect_container_overflow=0
diff --git a/sdcard/Android.mk b/sdcard/Android.mk
index cb3a8fb..c5f3d1d 100644
--- a/sdcard/Android.mk
+++ b/sdcard/Android.mk
@@ -5,7 +5,6 @@
 LOCAL_SRC_FILES := sdcard.c
 LOCAL_MODULE := sdcard
 LOCAL_CFLAGS := -Wall -Wno-unused-parameter -Werror
-
-LOCAL_SHARED_LIBRARIES := libcutils
+LOCAL_SHARED_LIBRARIES := libcutils libpackagelistparser
 
 include $(BUILD_EXECUTABLE)
diff --git a/sdcard/sdcard.c b/sdcard/sdcard.c
index d2d2315..b6bbe7e 100644
--- a/sdcard/sdcard.c
+++ b/sdcard/sdcard.c
@@ -24,6 +24,7 @@
 #include <limits.h>
 #include <linux/fuse.h>
 #include <pthread.h>
+#include <stdbool.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -34,6 +35,7 @@
 #include <sys/stat.h>
 #include <sys/statfs.h>
 #include <sys/time.h>
+#include <sys/types.h>
 #include <sys/uio.h>
 #include <unistd.h>
 
@@ -41,6 +43,7 @@
 #include <cutils/hashmap.h>
 #include <cutils/log.h>
 #include <cutils/multiuser.h>
+#include <packagelistparser/packagelistparser.h>
 
 #include <private/android_filesystem_config.h>
 
@@ -103,9 +106,6 @@
  * or that a reply has already been written. */
 #define NO_STATUS 1
 
-/* Path to system-provided mapping of package name to appIds */
-static const char* const kPackagesListFile = "/data/system/packages.list";
-
 /* Supplementary groups to execute with */
 static const gid_t kGroups[1] = { AID_PACKAGE_INFO };
 
@@ -1636,35 +1636,27 @@
     return true;
 }
 
-static int read_package_list(struct fuse_global* global) {
+static bool package_parse_callback(pkg_info *info, void *userdata) {
+    struct fuse_global *global = (struct fuse_global *)userdata;
+
+    char* name = strdup(info->name);
+    hashmapPut(global->package_to_appid, name, (void*) (uintptr_t) info->uid);
+    packagelist_free(info);
+    return true;
+}
+
+static bool read_package_list(struct fuse_global* global) {
     pthread_mutex_lock(&global->lock);
 
     hashmapForEach(global->package_to_appid, remove_str_to_int, global->package_to_appid);
 
-    FILE* file = fopen(kPackagesListFile, "r");
-    if (!file) {
-        ERROR("failed to open package list: %s\n", strerror(errno));
-        pthread_mutex_unlock(&global->lock);
-        return -1;
-    }
-
-    char buf[512];
-    while (fgets(buf, sizeof(buf), file) != NULL) {
-        char package_name[512];
-        int appid;
-        char gids[512];
-
-        if (sscanf(buf, "%s %d %*d %*s %*s %s", package_name, &appid, gids) == 3) {
-            char* package_name_dup = strdup(package_name);
-            hashmapPut(global->package_to_appid, package_name_dup, (void*) (uintptr_t) appid);
-        }
-    }
-
+    bool rc = packagelist_parse(package_parse_callback, global);
     TRACE("read_package_list: found %zu packages\n",
             hashmapSize(global->package_to_appid));
-    fclose(file);
+
     pthread_mutex_unlock(&global->lock);
-    return 0;
+
+    return rc;
 }
 
 static void watch_package_list(struct fuse_global* global) {
@@ -1680,11 +1672,11 @@
     bool active = false;
     while (1) {
         if (!active) {
-            int res = inotify_add_watch(nfd, kPackagesListFile, IN_DELETE_SELF);
+            int res = inotify_add_watch(nfd, PACKAGES_LIST_FILE, IN_DELETE_SELF);
             if (res == -1) {
                 if (errno == ENOENT || errno == EACCES) {
                     /* Framework may not have created yet, sleep and retry */
-                    ERROR("missing packages.list; retrying\n");
+                    ERROR("missing \"%s\"; retrying\n", PACKAGES_LIST_FILE);
                     sleep(3);
                     continue;
                 } else {
@@ -1695,8 +1687,8 @@
 
             /* Watch above will tell us about any future changes, so
              * read the current state. */
-            if (read_package_list(global) == -1) {
-                ERROR("read_package_list failed: %s\n", strerror(errno));
+            if (read_package_list(global) == false) {
+                ERROR("read_package_list failed\n");
                 return;
             }
             active = true;
diff --git a/toolbox/Android.mk b/toolbox/Android.mk
index 579d26e..52716e9 100644
--- a/toolbox/Android.mk
+++ b/toolbox/Android.mk
@@ -31,7 +31,6 @@
     dd \
 
 OUR_TOOLS := \
-    df \
     getevent \
     iftop \
     ioctl \
diff --git a/toolbox/df.c b/toolbox/df.c
deleted file mode 100644
index 9cd0743..0000000
--- a/toolbox/df.c
+++ /dev/null
@@ -1,85 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <sys/statfs.h>
-
-static int ok = EXIT_SUCCESS;
-
-static void printsize(long long n)
-{
-    char unit = 'K';
-    long long t;
-
-    n *= 10;
-
-    if (n > 1024*1024*10) {
-        n /= 1024;
-        unit = 'M';
-    }
-
-    if (n > 1024*1024*10) {
-        n /= 1024;
-        unit = 'G';
-    }
-
-    t = (n + 512) / 1024;
-    printf("%4lld.%1lld%c", t/10, t%10, unit);
-}
-
-static void df(char *s, int always) {
-    struct statfs st;
-
-    if (statfs(s, &st) < 0) {
-        fprintf(stderr, "%s: %s\n", s, strerror(errno));
-        ok = EXIT_FAILURE;
-    } else {
-        if (st.f_blocks == 0 && !always)
-            return;        
-        printf("%-20s  ", s);
-        printsize((long long)st.f_blocks * (long long)st.f_bsize);
-        printf("  ");
-        printsize((long long)(st.f_blocks - (long long)st.f_bfree) * st.f_bsize);
-        printf("  ");
-        printsize((long long)st.f_bfree * (long long)st.f_bsize);
-        printf("   %d\n", (int) st.f_bsize);
-    }
-}
-
-int df_main(int argc, char *argv[]) {
-    printf("Filesystem               Size     Used     Free   Blksize\n");
-    if (argc == 1) {
-        char s[2000];
-        FILE *f = fopen("/proc/mounts", "r");
-
-        while (fgets(s, 2000, f)) {
-            char *c, *e = s;
-
-            for (c = s; *c; c++) {
-                if (*c == ' ') {
-                    e = c + 1;
-                    break;
-                }
-            }
-
-            for (c = e; *c; c++) {
-                if (*c == ' ') {
-                    *c = '\0';
-                    break;
-                }
-            }
-
-            df(e, 0);
-        }
-
-        fclose(f);
-    } else {
-        int i;
-
-        for (i = 1; i < argc; i++) {
-            df(argv[i], 1);
-        }
-    }
-
-    exit(ok);
-}