Merge "Move to .md files for even trivial documentation."
diff --git a/adb/Android.mk b/adb/Android.mk
index 16ed991..49e492c 100644
--- a/adb/Android.mk
+++ b/adb/Android.mk
@@ -330,12 +330,13 @@
 LOCAL_STATIC_LIBRARIES := \
     libadbd \
     libbase \
+    libbootloader_message \
     libfs_mgr \
     libfec \
     libfec_rs \
     libselinux \
     liblog \
-    libext4_utils_static \
+    libext4_utils \
     libsquashfs_utils \
     libcutils \
     libbase \
diff --git a/adb/adb.h b/adb/adb.h
index 19f09a3..7db3b15 100644
--- a/adb/adb.h
+++ b/adb/adb.h
@@ -218,8 +218,6 @@
 #define CHUNK_SIZE (64*1024)
 
 #if !ADB_HOST
-#define USB_ADB_PATH     "/dev/android_adb"
-
 #define USB_FFS_ADB_PATH  "/dev/usb-ffs/adb/"
 #define USB_FFS_ADB_EP(x) USB_FFS_ADB_PATH#x
 
diff --git a/adb/daemon/main.cpp b/adb/daemon/main.cpp
index 78434a0..1a39f6a 100644
--- a/adb/daemon/main.cpp
+++ b/adb/daemon/main.cpp
@@ -170,7 +170,7 @@
     drop_privileges(server_port);
 
     bool is_usb = false;
-    if (access(USB_ADB_PATH, F_OK) == 0 || access(USB_FFS_ADB_EP0, F_OK) == 0) {
+    if (access(USB_FFS_ADB_EP0, F_OK) == 0) {
         // Listen on USB.
         usb_init();
         is_usb = true;
diff --git a/adb/services.cpp b/adb/services.cpp
index 2fbc15a..df1b134 100644
--- a/adb/services.cpp
+++ b/adb/services.cpp
@@ -39,6 +39,7 @@
 
 #if !ADB_HOST
 #include <android-base/properties.h>
+#include <bootloader_message/bootloader_message.h>
 #include <cutils/android_reboot.h>
 #include <private/android_logger.h>
 #endif
@@ -133,17 +134,12 @@
             return false;
         }
 
-        const char* const recovery_dir = "/cache/recovery";
-        const char* const command_file = "/cache/recovery/command";
-        // Ensure /cache/recovery exists.
-        if (adb_mkdir(recovery_dir, 0770) == -1 && errno != EEXIST) {
-            D("Failed to create directory '%s': %s", recovery_dir, strerror(errno));
-            return false;
-        }
-
-        bool write_status = android::base::WriteStringToFile(
-                auto_reboot ? "--sideload_auto_reboot" : "--sideload", command_file);
-        if (!write_status) {
+        const std::vector<std::string> options = {
+            auto_reboot ? "--sideload_auto_reboot" : "--sideload"
+        };
+        std::string err;
+        if (!write_bootloader_message(options, &err)) {
+            D("Failed to set bootloader message: %s", err.c_str());
             return false;
         }
 
diff --git a/adb/usb_linux_client.cpp b/adb/usb_linux_client.cpp
index 1cc7f68..a21a193 100644
--- a/adb/usb_linux_client.cpp
+++ b/adb/usb_linux_client.cpp
@@ -74,9 +74,6 @@
     void (*kick)(usb_handle *h);
     void (*close)(usb_handle *h);
 
-    // Legacy f_adb
-    int fd = -1;
-
     // FunctionFS
     int control = -1;
     int bulk_out = -1; /* "out" from the host's perspective => source for adbd */
@@ -248,141 +245,7 @@
     },
 };
 
-static void usb_adb_open_thread(void* x) {
-    struct usb_handle *usb = (struct usb_handle *)x;
-    int fd;
-
-    adb_thread_setname("usb open");
-
-    while (true) {
-        // wait until the USB device needs opening
-        std::unique_lock<std::mutex> lock(usb->lock);
-        while (!usb->open_new_connection) {
-            usb->notify.wait(lock);
-        }
-        usb->open_new_connection = false;
-        lock.unlock();
-
-        D("[ usb_thread - opening device ]");
-        do {
-            /* XXX use inotify? */
-            fd = unix_open("/dev/android_adb", O_RDWR);
-            if (fd < 0) {
-                // to support older kernels
-                fd = unix_open("/dev/android", O_RDWR);
-            }
-            if (fd < 0) {
-                std::this_thread::sleep_for(1s);
-            }
-        } while (fd < 0);
-        D("[ opening device succeeded ]");
-
-        close_on_exec(fd);
-        usb->fd = fd;
-
-        D("[ usb_thread - registering device ]");
-        register_usb_transport(usb, 0, 0, 1);
-    }
-
-    // never gets here
-    abort();
-}
-
-static int usb_adb_write(usb_handle *h, const void *data, int len)
-{
-    int n;
-
-    D("about to write (fd=%d, len=%d)", h->fd, len);
-    n = unix_write(h->fd, data, len);
-    if(n != len) {
-        D("ERROR: fd = %d, n = %d, errno = %d (%s)",
-            h->fd, n, errno, strerror(errno));
-        return -1;
-    }
-    if (h->kicked) {
-        D("usb_adb_write finished due to kicked");
-        return -1;
-    }
-    D("[ done fd=%d ]", h->fd);
-    return 0;
-}
-
-static int usb_adb_read(usb_handle *h, void *data, int len)
-{
-    D("about to read (fd=%d, len=%d)", h->fd, len);
-    while (len > 0) {
-        // The kernel implementation of adb_read in f_adb.c doesn't support
-        // reads larger then 4096 bytes. Read the data in 4096 byte chunks to
-        // avoid the issue. (The ffs implementation doesn't have this limit.)
-        int bytes_to_read = len < 4096 ? len : 4096;
-        int n = unix_read(h->fd, data, bytes_to_read);
-        if (n != bytes_to_read) {
-            D("ERROR: fd = %d, n = %d, errno = %d (%s)",
-                h->fd, n, errno, strerror(errno));
-            return -1;
-        }
-        if (h->kicked) {
-            D("usb_adb_read finished due to kicked");
-            return -1;
-        }
-        len -= n;
-        data = ((char*)data) + n;
-    }
-    D("[ done fd=%d ]", h->fd);
-    return 0;
-}
-
-static void usb_adb_kick(usb_handle *h) {
-    D("usb_kick");
-    // Other threads may be calling usb_adb_read/usb_adb_write at the same time.
-    // If we close h->fd, the file descriptor will be reused to open other files,
-    // and the read/write thread may operate on the wrong file. So instead
-    // we set the kicked flag and reopen h->fd to a dummy file here. After read/write
-    // threads finish, we close h->fd in usb_adb_close().
-    h->kicked = true;
-    TEMP_FAILURE_RETRY(dup2(dummy_fd, h->fd));
-}
-
-static void usb_adb_close(usb_handle *h) {
-    h->kicked = false;
-    adb_close(h->fd);
-    // Notify usb_adb_open_thread to open a new connection.
-    h->lock.lock();
-    h->open_new_connection = true;
-    h->lock.unlock();
-    h->notify.notify_one();
-}
-
-static void usb_adb_init()
-{
-    usb_handle* h = new usb_handle();
-
-    h->write = usb_adb_write;
-    h->read = usb_adb_read;
-    h->kick = usb_adb_kick;
-    h->close = usb_adb_close;
-
-    // Open the file /dev/android_adb_enable to trigger
-    // the enabling of the adb USB function in the kernel.
-    // We never touch this file again - just leave it open
-    // indefinitely so the kernel will know when we are running
-    // and when we are not.
-    int fd = unix_open("/dev/android_adb_enable", O_RDWR);
-    if (fd < 0) {
-       D("failed to open /dev/android_adb_enable");
-    } else {
-        close_on_exec(fd);
-    }
-
-    D("[ usb_init - starting thread ]");
-    if (!adb_thread_create(usb_adb_open_thread, h)) {
-        fatal_errno("cannot create usb thread");
-    }
-}
-
-
-static bool init_functionfs(struct usb_handle *h)
-{
+static bool init_functionfs(struct usb_handle* h) {
     ssize_t ret;
     struct desc_v1 v1_descriptor;
     struct desc_v2 v2_descriptor;
@@ -463,7 +326,7 @@
 }
 
 static void usb_ffs_open_thread(void* x) {
-    struct usb_handle *usb = (struct usb_handle *)x;
+    struct usb_handle* usb = (struct usb_handle*)x;
 
     adb_thread_setname("usb ffs open");
 
@@ -530,8 +393,7 @@
     return 0;
 }
 
-static void usb_ffs_kick(usb_handle *h)
-{
+static void usb_ffs_kick(usb_handle* h) {
     int err;
 
     err = ioctl(h->bulk_in, FUNCTIONFS_CLEAR_HALT);
@@ -553,7 +415,7 @@
     TEMP_FAILURE_RETRY(dup2(dummy_fd, h->bulk_in));
 }
 
-static void usb_ffs_close(usb_handle *h) {
+static void usb_ffs_close(usb_handle* h) {
     h->kicked = false;
     adb_close(h->bulk_out);
     adb_close(h->bulk_in);
@@ -564,8 +426,7 @@
     h->notify.notify_one();
 }
 
-static void usb_ffs_init()
-{
+static void usb_ffs_init() {
     D("[ usb_init - using FunctionFS ]");
 
     usb_handle* h = new usb_handle();
@@ -581,33 +442,25 @@
     }
 }
 
-void usb_init()
-{
+void usb_init() {
     dummy_fd = adb_open("/dev/null", O_WRONLY);
     CHECK_NE(dummy_fd, -1);
-    if (access(USB_FFS_ADB_EP0, F_OK) == 0)
-        usb_ffs_init();
-    else
-        usb_adb_init();
+    usb_ffs_init();
 }
 
-int usb_write(usb_handle *h, const void *data, int len)
-{
+int usb_write(usb_handle* h, const void* data, int len) {
     return h->write(h, data, len);
 }
 
-int usb_read(usb_handle *h, void *data, int len)
-{
+int usb_read(usb_handle* h, void* data, int len) {
     return h->read(h, data, len);
 }
 
-int usb_close(usb_handle *h)
-{
+int usb_close(usb_handle* h) {
     h->close(h);
     return 0;
 }
 
-void usb_kick(usb_handle *h)
-{
+void usb_kick(usb_handle* h) {
     h->kick(h);
 }
diff --git a/adf/libadfhwc/adfhwc.cpp b/adf/libadfhwc/adfhwc.cpp
index 7d5b555..a97862a 100644
--- a/adf/libadfhwc/adfhwc.cpp
+++ b/adf/libadfhwc/adfhwc.cpp
@@ -20,7 +20,7 @@
 #include <pthread.h>
 #include <sys/resource.h>
 
-#include <android/log.h>
+#include <log/log.h>
 #include <utils/Vector.h>
 
 #include <adf/adf.h>
diff --git a/bootstat/bootstat.cpp b/bootstat/bootstat.cpp
index 7c0e85d..483c01d 100644
--- a/bootstat/bootstat.cpp
+++ b/bootstat/bootstat.cpp
@@ -207,6 +207,19 @@
   return boot_complete_prefix;
 }
 
+// Records the value of a given ro.boottime.init property in milliseconds.
+void RecordInitBootTimeProp(
+    BootEventRecordStore* boot_event_store, const char* property) {
+  std::string value = GetProperty(property);
+
+  int32_t time_in_ns;
+  if (android::base::ParseInt(value, &time_in_ns)) {
+    static constexpr int32_t kNanosecondsPerMillisecond = 1e6;
+    int32_t time_in_ms = static_cast<int32_t>(time_in_ns / kNanosecondsPerMillisecond);
+    boot_event_store->AddBootEventWithValue(property, time_in_ms);
+  }
+}
+
 // Records several metrics related to the time it takes to boot the device,
 // including disambiguating boot time on encrypted or non-encrypted devices.
 void RecordBootComplete() {
@@ -256,6 +269,10 @@
   // Record the total time from device startup to boot complete, regardless of
   // encryption state.
   boot_event_store.AddBootEventWithValue(boot_complete_prefix, uptime);
+
+  RecordInitBootTimeProp(&boot_event_store, "ro.boottime.init");
+  RecordInitBootTimeProp(&boot_event_store, "ro.boottime.init.selinux");
+  RecordInitBootTimeProp(&boot_event_store, "ro.boottime.init.cold_boot_wait");
 }
 
 // Records the boot_reason metric by querying the ro.boot.bootreason system
diff --git a/debuggerd/arm/machine.cpp b/debuggerd/arm/machine.cpp
index 292edcb..78c2306 100644
--- a/debuggerd/arm/machine.cpp
+++ b/debuggerd/arm/machine.cpp
@@ -22,8 +22,8 @@
 #include <string.h>
 #include <sys/ptrace.h>
 
-#include <android/log.h>
 #include <backtrace/Backtrace.h>
+#include <log/log.h>
 
 #include "machine.h"
 #include "utility.h"
diff --git a/debuggerd/arm64/machine.cpp b/debuggerd/arm64/machine.cpp
index cd1bd52..e7bf79a 100644
--- a/debuggerd/arm64/machine.cpp
+++ b/debuggerd/arm64/machine.cpp
@@ -24,8 +24,8 @@
 #include <sys/ptrace.h>
 #include <sys/uio.h>
 
-#include <android/log.h>
 #include <backtrace/Backtrace.h>
+#include <log/log.h>
 
 #include "machine.h"
 #include "utility.h"
diff --git a/debuggerd/backtrace.cpp b/debuggerd/backtrace.cpp
index 06c1efe..0664442 100644
--- a/debuggerd/backtrace.cpp
+++ b/debuggerd/backtrace.cpp
@@ -31,8 +31,8 @@
 #include <memory>
 #include <string>
 
-#include <android/log.h>
 #include <backtrace/Backtrace.h>
+#include <log/log.h>
 
 #include "backtrace.h"
 
diff --git a/debuggerd/crasher.cpp b/debuggerd/crasher.cpp
index e650f22..689f4d4 100644
--- a/debuggerd/crasher.cpp
+++ b/debuggerd/crasher.cpp
@@ -29,8 +29,8 @@
 #include <unistd.h>
 
 // We test both kinds of logging.
-#include <android/log.h>
 #include <android-base/logging.h>
+#include <log/log.h>
 
 #if defined(STATIC_CRASHER)
 #include "debuggerd/client.h"
diff --git a/debuggerd/debuggerd.cpp b/debuggerd/debuggerd.cpp
index 9b82f64..893adc8 100644
--- a/debuggerd/debuggerd.cpp
+++ b/debuggerd/debuggerd.cpp
@@ -42,12 +42,12 @@
 
 #include <selinux/android.h>
 
-#include <android/log.h>
 #include <android-base/file.h>
 #include <android-base/unique_fd.h>
 #include <cutils/debugger.h>
 #include <cutils/properties.h>
 #include <cutils/sockets.h>
+#include <log/log.h>
 
 #include <private/android_filesystem_config.h>
 
diff --git a/debuggerd/elf_utils.cpp b/debuggerd/elf_utils.cpp
index d760a37..4e798e2 100644
--- a/debuggerd/elf_utils.cpp
+++ b/debuggerd/elf_utils.cpp
@@ -23,9 +23,9 @@
 
 #include <string>
 
-#include <android/log.h>
 #include <android-base/stringprintf.h>
 #include <backtrace/Backtrace.h>
+#include <log/log.h>
 
 #include "elf_utils.h"
 
diff --git a/debuggerd/mips/machine.cpp b/debuggerd/mips/machine.cpp
index 99a9d65..cbf272a 100644
--- a/debuggerd/mips/machine.cpp
+++ b/debuggerd/mips/machine.cpp
@@ -22,8 +22,8 @@
 #include <string.h>
 #include <sys/ptrace.h>
 
-#include <android/log.h>
 #include <backtrace/Backtrace.h>
+#include <log/log.h>
 
 #include "machine.h"
 #include "utility.h"
diff --git a/debuggerd/mips64/machine.cpp b/debuggerd/mips64/machine.cpp
index ecd1ca2..0a8d532 100644
--- a/debuggerd/mips64/machine.cpp
+++ b/debuggerd/mips64/machine.cpp
@@ -22,8 +22,8 @@
 #include <string.h>
 #include <sys/ptrace.h>
 
-#include <android/log.h>
 #include <backtrace/Backtrace.h>
+#include <log/log.h>
 
 #include "machine.h"
 #include "utility.h"
diff --git a/debuggerd/open_files_list.cpp b/debuggerd/open_files_list.cpp
index 5ef2abc..5c7ea70 100644
--- a/debuggerd/open_files_list.cpp
+++ b/debuggerd/open_files_list.cpp
@@ -29,7 +29,7 @@
 #include <vector>
 
 #include <android-base/file.h>
-#include <android/log.h>
+#include <log/log.h>
 
 #include "open_files_list.h"
 
diff --git a/debuggerd/signal_sender.cpp b/debuggerd/signal_sender.cpp
index 7fe4dee..42a8e77 100644
--- a/debuggerd/signal_sender.cpp
+++ b/debuggerd/signal_sender.cpp
@@ -27,7 +27,7 @@
 #include <sys/wait.h>
 #include <unistd.h>
 
-#include <android/log.h>
+#include <log/log.h>
 
 #include "signal_sender.h"
 
diff --git a/debuggerd/x86/machine.cpp b/debuggerd/x86/machine.cpp
index a6f21e1..af10817 100644
--- a/debuggerd/x86/machine.cpp
+++ b/debuggerd/x86/machine.cpp
@@ -21,8 +21,8 @@
 #include <string.h>
 #include <sys/ptrace.h>
 
-#include <android/log.h>
 #include <backtrace/Backtrace.h>
+#include <log/log.h>
 
 #include "machine.h"
 #include "utility.h"
diff --git a/debuggerd/x86_64/machine.cpp b/debuggerd/x86_64/machine.cpp
index 705e12d..bf2c2b4 100644
--- a/debuggerd/x86_64/machine.cpp
+++ b/debuggerd/x86_64/machine.cpp
@@ -18,12 +18,12 @@
 
 #include <errno.h>
 #include <stdint.h>
-#include <sys/ptrace.h>
 #include <string.h>
+#include <sys/ptrace.h>
 #include <sys/user.h>
 
-#include <android/log.h>
 #include <backtrace/Backtrace.h>
+#include <log/log.h>
 
 #include "machine.h"
 #include "utility.h"
diff --git a/fastboot/Android.mk b/fastboot/Android.mk
index 286de5b..5610cc0 100644
--- a/fastboot/Android.mk
+++ b/fastboot/Android.mk
@@ -57,8 +57,8 @@
 
 LOCAL_STATIC_LIBRARIES := \
     libziparchive \
-    libext4_utils_host \
-    libsparse_host \
+    libext4_utils \
+    libsparse \
     libutils \
     liblog \
     libz \
diff --git a/fingerprintd/fingerprintd.cpp b/fingerprintd/fingerprintd.cpp
index 05109b7..2fc2d0a 100644
--- a/fingerprintd/fingerprintd.cpp
+++ b/fingerprintd/fingerprintd.cpp
@@ -16,7 +16,6 @@
 
 #define LOG_TAG "fingerprintd"
 
-#include <android/log.h>
 #include <binder/IPCThreadState.h>
 #include <binder/IServiceManager.h>
 #include <binder/PermissionCache.h>
@@ -25,6 +24,7 @@
 #include <hardware/hw_auth_token.h>
 #include <keystore/IKeystoreService.h>
 #include <keystore/keystore.h> // for error codes
+#include <log/log.h>
 #include <utils/Log.h>
 #include <utils/String16.h>
 
diff --git a/fs_mgr/Android.mk b/fs_mgr/Android.mk
index d6b699b..051acfa 100644
--- a/fs_mgr/Android.mk
+++ b/fs_mgr/Android.mk
@@ -9,7 +9,7 @@
     libbase \
     libcrypto_utils \
     libcrypto \
-    libext4_utils_static \
+    libext4_utils \
     libsquashfs_utils \
     libselinux
 
@@ -18,6 +18,7 @@
 LOCAL_SANITIZE := integer
 LOCAL_SRC_FILES:= \
     fs_mgr.c \
+    fs_mgr_dm_ioctl.cpp \
     fs_mgr_format.c \
     fs_mgr_fstab.c \
     fs_mgr_slotselect.c \
@@ -32,6 +33,11 @@
 LOCAL_STATIC_LIBRARIES := $(common_static_libraries)
 LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
 LOCAL_CFLAGS := -Werror
+ifeq ($(TARGET_USERIMAGES_USE_EXT4), true)
+  ifeq ($(TARGET_USES_MKE2FS), true)
+    LOCAL_CFLAGS += -DTARGET_USES_MKE2FS
+  endif
+endif
 ifneq (,$(filter userdebug,$(TARGET_BUILD_VARIANT)))
 LOCAL_CFLAGS += -DALLOW_ADBD_DISABLE_VERITY=1
 endif
@@ -52,7 +58,7 @@
     libcutils \
     liblog \
     libc \
-    libsparse_static \
+    libsparse \
     libz \
     libselinux
 LOCAL_CXX_STL := libc++_static
diff --git a/fs_mgr/fs_mgr.c b/fs_mgr/fs_mgr.c
index ba44a5a..9a53d62 100644
--- a/fs_mgr/fs_mgr.c
+++ b/fs_mgr/fs_mgr.c
@@ -101,7 +101,9 @@
     char tmpmnt_opts[64] = "errors=remount-ro";
     char *e2fsck_argv[] = {
         E2FSCK_BIN,
+#ifndef TARGET_USES_MKE2FS // "-f" only for old ext4 generation tool
         "-f",
+#endif
         "-y",
         blk_device
     };
@@ -644,6 +646,17 @@
     }
 }
 
+int fs_mgr_test_access(const char *device) {
+    int tries = 25;
+    while (tries--) {
+        if (!access(device, F_OK) || errno != ENOENT) {
+            return 0;
+        }
+        usleep(40 * 1000);
+    }
+    return -1;
+}
+
 /* When multiple fstab records share the same mount_point, it will
  * try to mount each one in turn, and ignore any duplicates after a
  * first successful mount.
@@ -701,7 +714,7 @@
         }
 
         if ((fstab->recs[i].fs_mgr_flags & MF_VERIFY) && device_is_secure()) {
-            int rc = fs_mgr_setup_verity(&fstab->recs[i]);
+            int rc = fs_mgr_setup_verity(&fstab->recs[i], true);
             if (__android_log_is_debuggable() && rc == FS_MGR_SETUP_VERITY_DISABLED) {
                 INFO("Verity disabled");
             } else if (rc != FS_MGR_SETUP_VERITY_SUCCESS) {
@@ -870,7 +883,7 @@
         }
 
         if ((fstab->recs[i].fs_mgr_flags & MF_VERIFY) && device_is_secure()) {
-            int rc = fs_mgr_setup_verity(&fstab->recs[i]);
+            int rc = fs_mgr_setup_verity(&fstab->recs[i], true);
             if (__android_log_is_debuggable() && rc == FS_MGR_SETUP_VERITY_DISABLED) {
                 INFO("Verity disabled");
             } else if (rc != FS_MGR_SETUP_VERITY_SUCCESS) {
@@ -1086,7 +1099,7 @@
 int fs_mgr_early_setup_verity(struct fstab_rec *fstab_rec)
 {
     if ((fstab_rec->fs_mgr_flags & MF_VERIFY) && device_is_secure()) {
-        int rc = fs_mgr_setup_verity(fstab_rec);
+        int rc = fs_mgr_setup_verity(fstab_rec, false);
         if (__android_log_is_debuggable() && rc == FS_MGR_SETUP_VERITY_DISABLED) {
             INFO("Verity disabled");
             return FS_MGR_EARLY_SETUP_VERITY_NO_VERITY;
diff --git a/fs_mgr/fs_mgr_dm_ioctl.cpp b/fs_mgr/fs_mgr_dm_ioctl.cpp
new file mode 100644
index 0000000..75ce621
--- /dev/null
+++ b/fs_mgr/fs_mgr_dm_ioctl.cpp
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <errno.h>
+#include <string.h>
+
+#include <android-base/logging.h>
+#include <sys/ioctl.h>
+
+#include "fs_mgr_priv.h"
+#include "fs_mgr_priv_dm_ioctl.h"
+
+void fs_mgr_verity_ioctl_init(struct dm_ioctl *io,
+                              const std::string &name,
+                              unsigned flags)
+{
+    memset(io, 0, DM_BUF_SIZE);
+    io->data_size = DM_BUF_SIZE;
+    io->data_start = sizeof(struct dm_ioctl);
+    io->version[0] = 4;
+    io->version[1] = 0;
+    io->version[2] = 0;
+    io->flags = flags | DM_READONLY_FLAG;
+    if (!name.empty()) {
+        strlcpy(io->name, name.c_str(), sizeof(io->name));
+    }
+}
+
+bool fs_mgr_create_verity_device(struct dm_ioctl *io,
+                                 const std::string &name,
+                                 int fd)
+{
+    fs_mgr_verity_ioctl_init(io, name, 1);
+    if (ioctl(fd, DM_DEV_CREATE, io)) {
+        ERROR("Error creating device mapping (%s)", strerror(errno));
+        return false;
+    }
+    return true;
+}
+
+bool fs_mgr_destroy_verity_device(struct dm_ioctl *io,
+                                  const std::string &name,
+                                  int fd)
+{
+    fs_mgr_verity_ioctl_init(io, name, 0);
+    if (ioctl(fd, DM_DEV_REMOVE, io)) {
+        ERROR("Error removing device mapping (%s)", strerror(errno));
+        return false;
+    }
+    return true;
+}
+
+bool fs_mgr_get_verity_device_name(struct dm_ioctl *io,
+                                   const std::string &name,
+                                   int fd,
+                                   std::string *out_dev_name)
+{
+    CHECK(out_dev_name != nullptr);
+
+    fs_mgr_verity_ioctl_init(io, name, 0);
+    if (ioctl(fd, DM_DEV_STATUS, io)) {
+        ERROR("Error fetching verity device number (%s)", strerror(errno));
+        return false;
+    }
+
+    int dev_num = (io->dev & 0xff) | ((io->dev >> 12) & 0xfff00);
+    *out_dev_name = "/dev/block/dm-" + std::to_string(dev_num);
+
+    return true;
+}
+
+bool fs_mgr_resume_verity_table(struct dm_ioctl *io,
+                                const std::string &name,
+                                int fd)
+{
+    fs_mgr_verity_ioctl_init(io, name, 0);
+    if (ioctl(fd, DM_DEV_SUSPEND, io)) {
+        ERROR("Error activating verity device (%s)", strerror(errno));
+        return false;
+    }
+    return true;
+}
diff --git a/fs_mgr/fs_mgr_priv.h b/fs_mgr/fs_mgr_priv.h
index db86afa..7f917d9 100644
--- a/fs_mgr/fs_mgr_priv.h
+++ b/fs_mgr/fs_mgr_priv.h
@@ -93,6 +93,7 @@
 #define DM_BUF_SIZE 4096
 
 int fs_mgr_set_blk_ro(const char *blockdev);
+int fs_mgr_test_access(const char *device);
 int fs_mgr_update_for_slotselect(struct fstab *fstab);
 
 __END_DECLS
diff --git a/fs_mgr/fs_mgr_priv_dm_ioctl.h b/fs_mgr/fs_mgr_priv_dm_ioctl.h
new file mode 100644
index 0000000..eeae4dd
--- /dev/null
+++ b/fs_mgr/fs_mgr_priv_dm_ioctl.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __CORE_FS_MGR_PRIV_DM_IOCTL_H
+#define __CORE_FS_MGR_PRIV_DM_IOCTL_H
+
+#include <string>
+#include <linux/dm-ioctl.h>
+
+void fs_mgr_verity_ioctl_init(struct dm_ioctl *io,
+                              const std::string &name,
+                              unsigned flags);
+
+bool fs_mgr_create_verity_device(struct dm_ioctl *io,
+                                 const std::string &name,
+                                 int fd);
+
+bool fs_mgr_destroy_verity_device(struct dm_ioctl *io,
+                                  const std::string &name,
+                                  int fd);
+
+bool fs_mgr_get_verity_device_name(struct dm_ioctl *io,
+                                   const std::string &name,
+                                   int fd,
+                                   std::string *out_dev_name);
+
+bool fs_mgr_resume_verity_table(struct dm_ioctl *io,
+                                const std::string &name,
+                                int fd);
+
+#endif /* __CORE_FS_MGR_PRIV_DM_IOCTL_H */
diff --git a/fs_mgr/fs_mgr_priv_verity.h b/fs_mgr/fs_mgr_priv_verity.h
index d9e17bb..1a6d215 100644
--- a/fs_mgr/fs_mgr_priv_verity.h
+++ b/fs_mgr/fs_mgr_priv_verity.h
@@ -22,6 +22,6 @@
 
 __BEGIN_DECLS
 
-int fs_mgr_setup_verity(struct fstab_rec *fstab);
+int fs_mgr_setup_verity(struct fstab_rec *fstab, bool verify_dev);
 
 __END_DECLS
diff --git a/fs_mgr/fs_mgr_verity.cpp b/fs_mgr/fs_mgr_verity.cpp
index 031b042..e368a82 100644
--- a/fs_mgr/fs_mgr_verity.cpp
+++ b/fs_mgr/fs_mgr_verity.cpp
@@ -31,6 +31,7 @@
 
 #include <android-base/file.h>
 #include <android-base/strings.h>
+#include <android-base/unique_fd.h>
 #include <crypto_utils/android_pubkey.h>
 #include <cutils/properties.h>
 #include <logwrap/logwrap.h>
@@ -43,6 +44,7 @@
 
 #include "fs_mgr.h"
 #include "fs_mgr_priv.h"
+#include "fs_mgr_priv_dm_ioctl.h"
 #include "fs_mgr_priv_verity.h"
 
 #define FSTAB_PREFIX "/fstab."
@@ -73,6 +75,8 @@
 #define VERITY_KMSG_RESTART "dm-verity device corrupted"
 #define VERITY_KMSG_BUFSIZE 1024
 
+#define READ_BUF_SIZE 4096
+
 #define __STRINGIFY(x) #x
 #define STRINGIFY(x) __STRINGIFY(x)
 
@@ -181,45 +185,6 @@
     return -1;
 }
 
-static void verity_ioctl_init(struct dm_ioctl *io, const char *name, unsigned flags)
-{
-    memset(io, 0, DM_BUF_SIZE);
-    io->data_size = DM_BUF_SIZE;
-    io->data_start = sizeof(struct dm_ioctl);
-    io->version[0] = 4;
-    io->version[1] = 0;
-    io->version[2] = 0;
-    io->flags = flags | DM_READONLY_FLAG;
-    if (name) {
-        strlcpy(io->name, name, sizeof(io->name));
-    }
-}
-
-static int create_verity_device(struct dm_ioctl *io, char *name, int fd)
-{
-    verity_ioctl_init(io, name, 1);
-    if (ioctl(fd, DM_DEV_CREATE, io)) {
-        ERROR("Error creating device mapping (%s)", strerror(errno));
-        return -1;
-    }
-    return 0;
-}
-
-static int get_verity_device_name(struct dm_ioctl *io, char *name, int fd, char **dev_name)
-{
-    verity_ioctl_init(io, name, 0);
-    if (ioctl(fd, DM_DEV_STATUS, io)) {
-        ERROR("Error fetching verity device number (%s)", strerror(errno));
-        return -1;
-    }
-    int dev_num = (io->dev & 0xff) | ((io->dev >> 12) & 0xfff00);
-    if (asprintf(dev_name, "/dev/block/dm-%u", dev_num) < 0) {
-        ERROR("Error getting verity block device name (%s)", strerror(errno));
-        return -1;
-    }
-    return 0;
-}
-
 struct verity_table_params {
     char *table;
     int mode;
@@ -288,14 +253,15 @@
     return true;
 }
 
-static int load_verity_table(struct dm_ioctl *io, char *name, uint64_t device_size, int fd,
+static int load_verity_table(struct dm_ioctl *io, const std::string &name,
+                             uint64_t device_size, int fd,
         const struct verity_table_params *params, format_verity_table_func format)
 {
     char *verity_params;
     char *buffer = (char*) io;
     size_t bufsize;
 
-    verity_ioctl_init(io, name, DM_STATUS_TABLE_FLAG);
+    fs_mgr_verity_ioctl_init(io, name, DM_STATUS_TABLE_FLAG);
 
     struct dm_target_spec *tgt = (struct dm_target_spec *) &buffer[sizeof(struct dm_ioctl)];
 
@@ -331,27 +297,6 @@
     return 0;
 }
 
-static int resume_verity_table(struct dm_ioctl *io, char *name, int fd)
-{
-    verity_ioctl_init(io, name, 0);
-    if (ioctl(fd, DM_DEV_SUSPEND, io)) {
-        ERROR("Error activating verity device (%s)", strerror(errno));
-        return -1;
-    }
-    return 0;
-}
-
-static int test_access(char *device) {
-    int tries = 25;
-    while (tries--) {
-        if (!access(device, F_OK) || errno != ENOENT) {
-            return 0;
-        }
-        usleep(40 * 1000);
-    }
-    return -1;
-}
-
 static int check_verity_restart(const char *fname)
 {
     char buffer[VERITY_KMSG_BUFSIZE + 1];
@@ -606,6 +551,30 @@
     return rc;
 }
 
+static int read_partition(const char *path, uint64_t size)
+{
+    char buf[READ_BUF_SIZE];
+    ssize_t size_read;
+    android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC)));
+
+    if (fd == -1) {
+        ERROR("Failed to open %s: %s\n", path, strerror(errno));
+        return -errno;
+    }
+
+    while (size) {
+        size_read = TEMP_FAILURE_RETRY(read(fd, buf, READ_BUF_SIZE));
+        if (size_read == -1) {
+            ERROR("Error in reading partition %s: %s\n", path,
+                  strerror(errno));
+            return -errno;
+        }
+        size -= size_read;
+    }
+
+    return 0;
+}
+
 static int compare_last_signature(struct fstab_rec *fstab, int *match)
 {
     char tag[METADATA_TAG_MAX_LENGTH + 1];
@@ -786,9 +755,9 @@
     alignas(dm_ioctl) char buffer[DM_BUF_SIZE];
     bool system_root = false;
     char fstab_filename[PROPERTY_VALUE_MAX + sizeof(FSTAB_PREFIX)];
-    const char *mount_point;
+    std::string mount_point;
     char propbuf[PROPERTY_VALUE_MAX];
-    char *status;
+    const char *status;
     int fd = -1;
     int i;
     int mode;
@@ -835,18 +804,22 @@
             mount_point = basename(fstab->recs[i].mount_point);
         }
 
-        verity_ioctl_init(io, mount_point, 0);
+        fs_mgr_verity_ioctl_init(io, mount_point, 0);
 
         if (ioctl(fd, DM_TABLE_STATUS, io)) {
-            ERROR("Failed to query DM_TABLE_STATUS for %s (%s)\n", mount_point,
-                strerror(errno));
-            continue;
+            if (fstab->recs[i].fs_mgr_flags & MF_VERIFYATBOOT) {
+                status = "V";
+            } else {
+                ERROR("Failed to query DM_TABLE_STATUS for %s (%s)\n",
+                      mount_point.c_str(), strerror(errno));
+                continue;
+            }
         }
 
         status = &buffer[io->data_start + sizeof(struct dm_target_spec)];
 
         if (*status == 'C' || *status == 'V') {
-            callback(&fstab->recs[i], mount_point, mode, *status);
+            callback(&fstab->recs[i], mount_point.c_str(), mode, *status);
         }
     }
 
@@ -892,18 +865,19 @@
     *table = strdup(result.c_str());
 }
 
-int fs_mgr_setup_verity(struct fstab_rec *fstab)
+int fs_mgr_setup_verity(struct fstab_rec *fstab, bool verify_dev)
 {
     int retval = FS_MGR_SETUP_VERITY_FAIL;
     int fd = -1;
-    char *verity_blk_name = NULL;
+    std::string verity_blk_name;
     struct fec_handle *f = NULL;
     struct fec_verity_metadata verity;
     struct verity_table_params params = { .table = NULL };
 
     alignas(dm_ioctl) char buffer[DM_BUF_SIZE];
     struct dm_ioctl *io = (struct dm_ioctl *) buffer;
-    char *mount_point = basename(fstab->mount_point);
+    const std::string mount_point(basename(fstab->mount_point));
+    bool verified_at_boot = false;
 
     if (fec_open(&f, fstab->blk_device, O_RDONLY, FEC_VERITY_DISABLE,
             FEC_DEFAULT_ROOTS) < 0) {
@@ -941,13 +915,13 @@
     }
 
     // create the device
-    if (create_verity_device(io, mount_point, fd) < 0) {
+    if (!fs_mgr_create_verity_device(io, mount_point, fd)) {
         ERROR("Couldn't create verity device!\n");
         goto out;
     }
 
     // get the name of the device file
-    if (get_verity_device_name(io, mount_point, fd, &verity_blk_name) < 0) {
+    if (!fs_mgr_get_verity_device_name(io, mount_point, fd, &verity_blk_name)) {
         ERROR("Couldn't get verity device number!\n");
         goto out;
     }
@@ -983,7 +957,8 @@
         }
     }
 
-    INFO("Enabling dm-verity for %s (mode %d)\n", mount_point, params.mode);
+    INFO("Enabling dm-verity for %s (mode %d)\n",
+         mount_point.c_str(), params.mode);
 
     if (fstab->fs_mgr_flags & MF_SLOTSELECT) {
         // Update the verity params using the actual block device path
@@ -998,7 +973,7 @@
 
     if (params.ecc.valid) {
         // kernel may not support error correction, try without
-        INFO("Disabling error correction for %s\n", mount_point);
+        INFO("Disabling error correction for %s\n", mount_point.c_str());
         params.ecc.valid = false;
 
         if (load_verity_table(io, mount_point, verity.data_size, fd, &params,
@@ -1015,7 +990,7 @@
 
     if (params.mode != VERITY_MODE_EIO) {
         // as a last resort, EIO mode should always be supported
-        INFO("Falling back to EIO mode for %s\n", mount_point);
+        INFO("Falling back to EIO mode for %s\n", mount_point.c_str());
         params.mode = VERITY_MODE_EIO;
 
         if (load_verity_table(io, mount_point, verity.data_size, fd, &params,
@@ -1024,26 +999,41 @@
         }
     }
 
-    ERROR("Failed to load verity table for %s\n", mount_point);
+    ERROR("Failed to load verity table for %s\n", mount_point.c_str());
     goto out;
 
 loaded:
 
     // activate the device
-    if (resume_verity_table(io, mount_point, fd) < 0) {
+    if (!fs_mgr_resume_verity_table(io, mount_point, fd)) {
         goto out;
     }
 
     // mark the underlying block device as read-only
     fs_mgr_set_blk_ro(fstab->blk_device);
 
+    // Verify the entire partition in one go
+    // If there is an error, allow it to mount as a normal verity partition.
+    if (fstab->fs_mgr_flags & MF_VERIFYATBOOT) {
+        INFO("Verifying partition %s at boot\n", fstab->blk_device);
+        int err = read_partition(verity_blk_name.c_str(), verity.data_size);
+        if (!err) {
+            INFO("Verified verity partition %s at boot\n", fstab->blk_device);
+            verified_at_boot = true;
+        }
+    }
+
     // assign the new verity block device as the block device
-    free(fstab->blk_device);
-    fstab->blk_device = verity_blk_name;
-    verity_blk_name = 0;
+    if (!verified_at_boot) {
+        free(fstab->blk_device);
+        fstab->blk_device = strdup(verity_blk_name.c_str());
+    } else if (!fs_mgr_destroy_verity_device(io, mount_point, fd)) {
+        ERROR("Failed to remove verity device %s\n", mount_point.c_str());
+        goto out;
+    }
 
     // make sure we've set everything up properly
-    if (test_access(fstab->blk_device) < 0) {
+    if (verify_dev && fs_mgr_test_access(fstab->blk_device) < 0) {
         goto out;
     }
 
@@ -1056,7 +1046,6 @@
 
     fec_close(f);
     free(params.table);
-    free(verity_blk_name);
 
     return retval;
 }
diff --git a/gatekeeperd/gatekeeperd.cpp b/gatekeeperd/gatekeeperd.cpp
index 4107f55..d4a92e5 100644
--- a/gatekeeperd/gatekeeperd.cpp
+++ b/gatekeeperd/gatekeeperd.cpp
@@ -24,7 +24,6 @@
 #include <stdint.h>
 #include <unistd.h>
 
-#include <android/log.h>
 #include <binder/IPCThreadState.h>
 #include <binder/IServiceManager.h>
 #include <binder/PermissionCache.h>
@@ -33,6 +32,7 @@
 #include <hardware/hw_auth_token.h>
 #include <keystore/IKeystoreService.h>
 #include <keystore/keystore.h> // For error code
+#include <log/log.h>
 #include <utils/Log.h>
 #include <utils/String16.h>
 
diff --git a/include/cutils/klog.h b/include/cutils/klog.h
index c837edb..e7cd300 100644
--- a/include/cutils/klog.h
+++ b/include/cutils/klog.h
@@ -44,6 +44,4 @@
 #define KLOG_INFO(tag,x...)    klog_write(KLOG_INFO_LEVEL, "<6>" tag ": " x)
 #define KLOG_DEBUG(tag,x...)   klog_write(KLOG_DEBUG_LEVEL, "<7>" tag ": " x)
 
-#define KLOG_DEFAULT_LEVEL  3  /* messages <= this level are logged */
-
 #endif
diff --git a/include/private/android_filesystem_config.h b/include/private/android_filesystem_config.h
index f7cf9b8..eb71fb8 100644
--- a/include/private/android_filesystem_config.h
+++ b/include/private/android_filesystem_config.h
@@ -173,104 +173,15 @@
 #define AID_USER            100000 /* TODO: switch users over to AID_USER_OFFSET */
 #define AID_USER_OFFSET     100000 /* offset for uid ranges for each user */
 
-#if !defined(EXCLUDE_FS_CONFIG_STRUCTURES)
 /*
- * Used in:
- *  bionic/libc/bionic/stubs.cpp
- *  external/libselinux/src/android.c
- *  system/core/logd/LogStatistics.cpp
- *  system/core/init/ueventd.cpp
- *  system/core/init/util.cpp
+ * android_ids has moved to pwd/grp functionality.
+ * If you need to add one, the structure is now
+ * auto-generated based on the AID_ constraints
+ * documented at the top of this header file.
+ * Also see build/tools/fs_config for more details.
  */
-struct android_id_info {
-    const char *name;
-    unsigned aid;
-};
 
-static const struct android_id_info android_ids[] = {
-    { "root",          AID_ROOT, },
-
-    { "system",        AID_SYSTEM, },
-
-    { "radio",         AID_RADIO, },
-    { "bluetooth",     AID_BLUETOOTH, },
-    { "graphics",      AID_GRAPHICS, },
-    { "input",         AID_INPUT, },
-    { "audio",         AID_AUDIO, },
-    { "camera",        AID_CAMERA, },
-    { "log",           AID_LOG, },
-    { "compass",       AID_COMPASS, },
-    { "mount",         AID_MOUNT, },
-    { "wifi",          AID_WIFI, },
-    { "adb",           AID_ADB, },
-    { "install",       AID_INSTALL, },
-    { "media",         AID_MEDIA, },
-    { "dhcp",          AID_DHCP, },
-    { "sdcard_rw",     AID_SDCARD_RW, },
-    { "vpn",           AID_VPN, },
-    { "keystore",      AID_KEYSTORE, },
-    { "usb",           AID_USB, },
-    { "drm",           AID_DRM, },
-    { "mdnsr",         AID_MDNSR, },
-    { "gps",           AID_GPS, },
-    // AID_UNUSED1
-    { "media_rw",      AID_MEDIA_RW, },
-    { "mtp",           AID_MTP, },
-    // AID_UNUSED2
-    { "drmrpc",        AID_DRMRPC, },
-    { "nfc",           AID_NFC, },
-    { "sdcard_r",      AID_SDCARD_R, },
-    { "clat",          AID_CLAT, },
-    { "loop_radio",    AID_LOOP_RADIO, },
-    { "mediadrm",      AID_MEDIA_DRM, },
-    { "package_info",  AID_PACKAGE_INFO, },
-    { "sdcard_pics",   AID_SDCARD_PICS, },
-    { "sdcard_av",     AID_SDCARD_AV, },
-    { "sdcard_all",    AID_SDCARD_ALL, },
-    { "logd",          AID_LOGD, },
-    { "shared_relro",  AID_SHARED_RELRO, },
-    { "dbus",          AID_DBUS, },
-    { "tlsdate",       AID_TLSDATE, },
-    { "mediaex",       AID_MEDIA_EX, },
-    { "audioserver",   AID_AUDIOSERVER, },
-    { "metrics_coll",  AID_METRICS_COLL },
-    { "metricsd",      AID_METRICSD },
-    { "webserv",       AID_WEBSERV },
-    { "debuggerd",     AID_DEBUGGERD, },
-    { "mediacodec",    AID_MEDIA_CODEC, },
-    { "cameraserver",  AID_CAMERASERVER, },
-    { "firewall",      AID_FIREWALL, },
-    { "trunks",        AID_TRUNKS, },
-    { "nvram",         AID_NVRAM, },
-    { "dns",           AID_DNS, },
-    { "dns_tether",    AID_DNS_TETHER, },
-    { "webview_zygote", AID_WEBVIEW_ZYGOTE, },
-    { "vehicle_network", AID_VEHICLE_NETWORK, },
-    { "media_audio",   AID_MEDIA_AUDIO, },
-    { "media_video",   AID_MEDIA_VIDEO, },
-    { "media_image",   AID_MEDIA_IMAGE, },
-
-    { "shell",         AID_SHELL, },
-    { "cache",         AID_CACHE, },
-    { "diag",          AID_DIAG, },
-
-    { "net_bt_admin",  AID_NET_BT_ADMIN, },
-    { "net_bt",        AID_NET_BT, },
-    { "inet",          AID_INET, },
-    { "net_raw",       AID_NET_RAW, },
-    { "net_admin",     AID_NET_ADMIN, },
-    { "net_bw_stats",  AID_NET_BW_STATS, },
-    { "net_bw_acct",   AID_NET_BW_ACCT, },
-    { "readproc",      AID_READPROC, },
-    { "wakelock",      AID_WAKELOCK, },
-
-    { "everybody",     AID_EVERYBODY, },
-    { "misc",          AID_MISC, },
-    { "nobody",        AID_NOBODY, },
-};
-
-#define android_id_count \
-    (sizeof(android_ids) / sizeof(android_ids[0]))
+#if !defined(EXCLUDE_FS_CONFIG_STRUCTURES)
 
 struct fs_path_config {
     unsigned mode;
diff --git a/include/system/radio.h b/include/system/radio.h
index d73d3ae..03b252e 100644
--- a/include/system/radio.h
+++ b/include/system/radio.h
@@ -84,7 +84,7 @@
 typedef unsigned int radio_handle_t;
 
 /* Opaque meta data structure used by radio meta data API (see system/radio_metadata.h) */
-typedef struct radio_medtadata radio_metadata_t;
+typedef struct radio_metadata radio_metadata_t;
 
 
 /* Additional attributes for an FM band configuration */
@@ -170,7 +170,8 @@
     bool             stereo;    /* program is stereo or not */
     bool             digital;   /* digital program or not (e.g HD Radio program) */
     unsigned int     signal_strength; /* signal strength from 0 to 100 */
-    radio_metadata_t *metadata; /* non null if meta data are present (e.g PTY, song title ...) */
+                                /* meta data (e.g PTY, song title ...), must not be NULL */
+    __attribute__((aligned(8))) radio_metadata_t *metadata;
 } radio_program_info_t;
 
 
diff --git a/include/utils/KeyedVector.h b/include/utils/KeyedVector.h
index 42de401..f93ad6e 100644
--- a/include/utils/KeyedVector.h
+++ b/include/utils/KeyedVector.h
@@ -21,7 +21,7 @@
 #include <stdint.h>
 #include <sys/types.h>
 
-#include <android/log.h>
+#include <log/log.h>
 #include <utils/Errors.h>
 #include <utils/SortedVector.h>
 #include <utils/TypeHelpers.h>
diff --git a/init/Android.mk b/init/Android.mk
index 111fe89..6615692 100644
--- a/init/Android.mk
+++ b/init/Android.mk
@@ -92,7 +92,7 @@
     libsquashfs_utils \
     liblogwrap \
     libcutils \
-    libext4_utils_static \
+    libext4_utils \
     libbase \
     libc \
     libselinux \
@@ -101,7 +101,7 @@
     libcrypto \
     libc++_static \
     libdl \
-    libsparse_static \
+    libsparse \
     libz \
     libprocessgroup \
     libnl \
diff --git a/libbacktrace/BacktraceLog.h b/libbacktrace/BacktraceLog.h
index 0a27982..5c39f1c 100644
--- a/libbacktrace/BacktraceLog.h
+++ b/libbacktrace/BacktraceLog.h
@@ -19,7 +19,7 @@
 
 #define LOG_TAG "libbacktrace"
 
-#include <android/log.h>
+#include <log/log.h>
 
 // Macro to log the function name along with the warning message.
 #define BACK_LOGW(format, ...) \
diff --git a/libbacktrace/BacktraceMap.cpp b/libbacktrace/BacktraceMap.cpp
index 4496375..0e31495 100644
--- a/libbacktrace/BacktraceMap.cpp
+++ b/libbacktrace/BacktraceMap.cpp
@@ -22,7 +22,8 @@
 #include <sys/types.h>
 #include <unistd.h>
 
-#include <android/log.h>
+#include <log/log.h>
+
 #include <backtrace/backtrace_constants.h>
 #include <backtrace/BacktraceMap.h>
 
diff --git a/libcutils/ashmem-dev.c b/libcutils/ashmem-dev.c
index db4ed11..92717c0 100644
--- a/libcutils/ashmem-dev.c
+++ b/libcutils/ashmem-dev.c
@@ -31,8 +31,8 @@
 #include <sys/types.h>
 #include <unistd.h>
 
-#include <android/log.h>
 #include <cutils/ashmem.h>
+#include <log/log.h>
 
 #define ASHMEM_DEVICE "/dev/ashmem"
 
diff --git a/libcutils/debugger.c b/libcutils/debugger.c
index c6bdd1a..32fac98 100644
--- a/libcutils/debugger.c
+++ b/libcutils/debugger.c
@@ -25,9 +25,9 @@
 #include <sys/types.h>
 #include <unistd.h>
 
-#include <android/log.h>
 #include <cutils/debugger.h>
 #include <cutils/sockets.h>
+#include <log/log.h>
 
 static int send_request(int sock_fd, void* msg_ptr, size_t msg_len) {
   int result = 0;
diff --git a/libcutils/dlmalloc_stubs.c b/libcutils/dlmalloc_stubs.c
index 6c07bed..2cff9dd 100644
--- a/libcutils/dlmalloc_stubs.c
+++ b/libcutils/dlmalloc_stubs.c
@@ -16,7 +16,7 @@
 
 #define LOG_TAG "dlmalloc-stubs"
 
-#include "android/log.h"
+#include "log/log.h"
 
 #define UNUSED __attribute__((__unused__))
 
diff --git a/libcutils/fs.c b/libcutils/fs.c
index c49233e..488fdfc 100644
--- a/libcutils/fs.c
+++ b/libcutils/fs.c
@@ -32,8 +32,8 @@
 #include <sys/types.h>
 #include <unistd.h>
 
-#include <android/log.h>
 #include <cutils/fs.h>
+#include <log/log.h>
 
 #define ALL_PERMS (S_ISUID | S_ISGID | S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO)
 #define BUF_SIZE 64
diff --git a/libcutils/fs_config.c b/libcutils/fs_config.c
index 6155d16..f43f1e6 100644
--- a/libcutils/fs_config.c
+++ b/libcutils/fs_config.c
@@ -33,7 +33,7 @@
 #include <sys/stat.h>
 #include <sys/types.h>
 
-#include <android/log.h>
+#include <log/log.h>
 #include <private/android_filesystem_config.h>
 #include <utils/Compat.h>
 
@@ -163,6 +163,10 @@
                                            CAP_MASK_LONG(CAP_NET_RAW),
                                               "system/bin/hw/android.hardware.wifi@1.0-service" },
 
+    /* Support Bluetooth legacy hal accessing /sys/class/rfkill */
+    { 00700, AID_BLUETOOTH, AID_BLUETOOTH, CAP_MASK_LONG(CAP_NET_ADMIN),
+                                              "system/bin/hw/android.hardware.bluetooth@1.0-service" },
+
     /* A non-privileged zygote that spawns isolated processes for web rendering. */
     { 0750,  AID_ROOT,      AID_ROOT,      CAP_MASK_LONG(CAP_SETUID) |
                                            CAP_MASK_LONG(CAP_SETGID) |
diff --git a/libcutils/klog.cpp b/libcutils/klog.cpp
index 4bad28a..15adf6b 100644
--- a/libcutils/klog.cpp
+++ b/libcutils/klog.cpp
@@ -27,7 +27,7 @@
 #include <cutils/android_get_control_file.h>
 #include <cutils/klog.h>
 
-static int klog_level = KLOG_DEFAULT_LEVEL;
+static int klog_level = KLOG_INFO_LEVEL;
 
 int klog_get_level(void) {
     return klog_level;
diff --git a/libcutils/properties.c b/libcutils/properties.c
index 740c7a9..bdbddd0 100644
--- a/libcutils/properties.c
+++ b/libcutils/properties.c
@@ -26,9 +26,9 @@
 #include <string.h>
 #include <unistd.h>
 
-#include <android/log.h>
 #include <cutils/properties.h>
 #include <cutils/sockets.h>
+#include <log/log.h>
 
 int8_t property_get_bool(const char *key, int8_t default_value) {
     if (!key) {
diff --git a/libcutils/qtaguid.c b/libcutils/qtaguid.c
index ae5a503..22b8325 100644
--- a/libcutils/qtaguid.c
+++ b/libcutils/qtaguid.c
@@ -26,7 +26,7 @@
 #include <string.h>
 #include <unistd.h>
 
-#include <android/log.h>
+#include <log/log.h>
 #include <cutils/qtaguid.h>
 
 static const char* CTRL_PROCPATH = "/proc/net/xt_qtaguid/ctrl";
diff --git a/libcutils/sockets_unix.cpp b/libcutils/sockets_unix.cpp
index 5a14a5c..e91f358 100644
--- a/libcutils/sockets_unix.cpp
+++ b/libcutils/sockets_unix.cpp
@@ -25,9 +25,9 @@
 #include <time.h>
 #include <unistd.h>
 
-#include <android/log.h>
 #include <cutils/android_get_control_file.h>
 #include <cutils/sockets.h>
+#include <log/log.h>
 
 #include "android_get_control_env.h"
 
diff --git a/libcutils/str_parms.c b/libcutils/str_parms.c
index 6bb7e58..8dafded 100644
--- a/libcutils/str_parms.c
+++ b/libcutils/str_parms.c
@@ -24,10 +24,10 @@
 #include <stdlib.h>
 #include <string.h>
 
-#include <android/log.h>
 #include <cutils/hashmap.h>
 #include <cutils/memory.h>
 #include <cutils/str_parms.h>
+#include <log/log.h>
 
 #define UNUSED __attribute__((unused))
 
diff --git a/libdiskconfig/config_mbr.c b/libdiskconfig/config_mbr.c
index 1d3cd20..ace9bbf 100644
--- a/libdiskconfig/config_mbr.c
+++ b/libdiskconfig/config_mbr.c
@@ -22,8 +22,8 @@
 #include <stdlib.h>
 #include <string.h>
 
-#include <android/log.h>
 #include <diskconfig/diskconfig.h>
+#include <log/log.h>
 
 /* start and len are in LBA units */
 static void
diff --git a/libdiskconfig/diskconfig.c b/libdiskconfig/diskconfig.c
index 2d59ad9..c7e1b43 100644
--- a/libdiskconfig/diskconfig.c
+++ b/libdiskconfig/diskconfig.c
@@ -28,8 +28,8 @@
 #include <sys/stat.h>
 #include <unistd.h>
 
-#include <android/log.h>
 #include <cutils/config_utils.h>
+#include <log/log.h>
 
 #include <diskconfig/diskconfig.h>
 
diff --git a/libdiskconfig/diskutils.c b/libdiskconfig/diskutils.c
index 3a27601..fe1b4c1 100644
--- a/libdiskconfig/diskutils.c
+++ b/libdiskconfig/diskutils.c
@@ -26,7 +26,7 @@
 #include <sys/stat.h>
 #include <unistd.h>
 
-#include <android/log.h>
+#include <log/log.h>
 
 #include <diskconfig/diskconfig.h>
 
diff --git a/libdiskconfig/dump_diskconfig.c b/libdiskconfig/dump_diskconfig.c
index c94e7f4..3c4f620 100644
--- a/libdiskconfig/dump_diskconfig.c
+++ b/libdiskconfig/dump_diskconfig.c
@@ -19,7 +19,7 @@
 
 #include <stdio.h>
 
-#include <android/log.h>
+#include <log/log.h>
 
 #include "diskconfig.h"
 
diff --git a/libdiskconfig/write_lst.c b/libdiskconfig/write_lst.c
index 21d4a31..c3d5c0a 100644
--- a/libdiskconfig/write_lst.c
+++ b/libdiskconfig/write_lst.c
@@ -23,8 +23,8 @@
 #include <sys/types.h>
 #include <unistd.h>
 
-#include <android/log.h>
 #include <diskconfig/diskconfig.h>
+#include <log/log.h>
 
 struct write_list *
 alloc_wl(uint32_t data_len)
diff --git a/libion/ion.c b/libion/ion.c
index a7b22b8..9aaa6f2 100644
--- a/libion/ion.c
+++ b/libion/ion.c
@@ -29,8 +29,8 @@
 #include <sys/types.h>
 #include <unistd.h>
 
-#include <android/log.h>
 #include <ion/ion.h>
+#include <log/log.h>
 
 int ion_open()
 {
diff --git a/liblog/Android.bp b/liblog/Android.bp
index be47fc3..bbe7d79 100644
--- a/liblog/Android.bp
+++ b/liblog/Android.bp
@@ -115,4 +115,5 @@
     name: "liblog.ndk",
     symbol_file: "liblog.map.txt",
     first_version: "9",
+    unversioned_until: "current",
 }
diff --git a/liblog/logd_writer.c b/liblog/logd_writer.c
index 8fdfb92..2bab92e 100644
--- a/liblog/logd_writer.c
+++ b/liblog/logd_writer.c
@@ -50,7 +50,7 @@
 
 LIBLOG_HIDDEN struct android_log_transport_write logdLoggerWrite = {
     .node = { &logdLoggerWrite.node, &logdLoggerWrite.node },
-    .context.sock = -1,
+    .context.sock = -EBADF,
     .name = "logd",
     .available = logdAvailable,
     .open = logdOpen,
@@ -65,8 +65,10 @@
 
     i = atomic_load(&logdLoggerWrite.context.sock);
     if (i < 0) {
-        i = TEMP_FAILURE_RETRY(socket(PF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0));
-        if (i < 0) {
+        int sock = TEMP_FAILURE_RETRY(socket(PF_UNIX, SOCK_DGRAM |
+                                                      SOCK_CLOEXEC |
+                                                      SOCK_NONBLOCK, 0));
+        if (sock < 0) {
             ret = -errno;
         } else {
             struct sockaddr_un un;
@@ -74,13 +76,22 @@
             un.sun_family = AF_UNIX;
             strcpy(un.sun_path, "/dev/socket/logdw");
 
-            if (TEMP_FAILURE_RETRY(connect(i, (struct sockaddr *)&un,
+            if (TEMP_FAILURE_RETRY(connect(sock, (struct sockaddr *)&un,
                                            sizeof(struct sockaddr_un))) < 0) {
                 ret = -errno;
-                close(i);
+                switch (ret) {
+                case -ENOTCONN:
+                case -ECONNREFUSED:
+                case -ENOENT:
+                    i = atomic_exchange(&logdLoggerWrite.context.sock, ret);
+                    /* FALLTHRU */
+                default:
+                    break;
+                }
+                close(sock);
             } else {
-                ret = atomic_exchange(&logdLoggerWrite.context.sock, i);
-                if ((ret >= 0) && (ret != i)) {
+                ret = atomic_exchange(&logdLoggerWrite.context.sock, sock);
+                if ((ret >= 0) && (ret != sock)) {
                     close(ret);
                 }
                 ret = 0;
@@ -91,14 +102,19 @@
     return ret;
 }
 
-static void logdClose()
+static void __logdClose(int negative_errno)
 {
-    int sock = atomic_exchange(&logdLoggerWrite.context.sock, -1);
+    int sock = atomic_exchange(&logdLoggerWrite.context.sock, negative_errno);
     if (sock >= 0) {
         close(sock);
     }
 }
 
+static void logdClose()
+{
+    __logdClose(-EBADF);
+}
+
 static int logdAvailable(log_id_t logId)
 {
     if (logId > LOG_ID_SECURITY) {
@@ -117,6 +133,7 @@
                      struct iovec *vec, size_t nr)
 {
     ssize_t ret;
+    int sock;
     static const unsigned headerLength = 1;
     struct iovec newVec[nr + headerLength];
     android_log_header_t header;
@@ -124,7 +141,13 @@
     static atomic_int_fast32_t dropped;
     static atomic_int_fast32_t droppedSecurity;
 
-    if (atomic_load(&logdLoggerWrite.context.sock) < 0) {
+    sock = atomic_load(&logdLoggerWrite.context.sock);
+    if (sock < 0) switch (sock) {
+    case -ENOTCONN:
+    case -ECONNREFUSED:
+    case -ENOENT:
+        break;
+    default:
         return -EBADF;
     }
 
@@ -163,7 +186,7 @@
     newVec[0].iov_base = (unsigned char *)&header;
     newVec[0].iov_len  = sizeof(header);
 
-    if (atomic_load(&logdLoggerWrite.context.sock) > 0) {
+    if (sock >= 0) {
         int32_t snapshot = atomic_exchange_explicit(&droppedSecurity, 0,
                                                     memory_order_relaxed);
         if (snapshot) {
@@ -177,8 +200,7 @@
             newVec[headerLength].iov_base = &buffer;
             newVec[headerLength].iov_len  = sizeof(buffer);
 
-            ret = TEMP_FAILURE_RETRY(writev(
-                    atomic_load(&logdLoggerWrite.context.sock), newVec, 2));
+            ret = TEMP_FAILURE_RETRY(writev(sock, newVec, 2));
             if (ret != (ssize_t)(sizeof(header) + sizeof(buffer))) {
                 atomic_fetch_add_explicit(&droppedSecurity, snapshot,
                                           memory_order_relaxed);
@@ -186,7 +208,8 @@
         }
         snapshot = atomic_exchange_explicit(&dropped, 0, memory_order_relaxed);
         if (snapshot && __android_log_is_loggable_len(ANDROID_LOG_INFO,
-                                                      "liblog", strlen("liblog"),
+                                                      "liblog",
+                                                      strlen("liblog"),
                                                       ANDROID_LOG_VERBOSE)) {
             android_log_event_int_t buffer;
 
@@ -198,8 +221,7 @@
             newVec[headerLength].iov_base = &buffer;
             newVec[headerLength].iov_len  = sizeof(buffer);
 
-            ret = TEMP_FAILURE_RETRY(writev(
-                      atomic_load(&logdLoggerWrite.context.sock), newVec, 2));
+            ret = TEMP_FAILURE_RETRY(writev(sock, newVec, 2));
             if (ret != (ssize_t)(sizeof(header) + sizeof(buffer))) {
                 atomic_fetch_add_explicit(&dropped, snapshot,
                                           memory_order_relaxed);
@@ -225,30 +247,43 @@
     /*
      * The write below could be lost, but will never block.
      *
-     * ENOTCONN occurs if logd dies.
+     * ENOTCONN occurs if logd has died.
+     * ENOENT occurs if logd is not running and socket is missing.
+     * ECONNREFUSED occurs if we can not reconnect to logd.
      * EAGAIN occurs if logd is overloaded.
      */
-    ret = TEMP_FAILURE_RETRY(writev(
-            atomic_load(&logdLoggerWrite.context.sock), newVec, i));
-    if (ret < 0) {
-        ret = -errno;
-        if (ret == -ENOTCONN) {
-            __android_log_lock();
-            logdClose();
-            ret = logdOpen();
-            __android_log_unlock();
-
-            if (ret < 0) {
-                return ret;
-            }
-
-            ret = TEMP_FAILURE_RETRY(writev(
-                    atomic_load(&logdLoggerWrite.context.sock), newVec, i));
-            if (ret < 0) {
-                ret = -errno;
-            }
+    if (sock < 0) {
+        ret = sock;
+    } else {
+        ret = TEMP_FAILURE_RETRY(writev(sock, newVec, i));
+        if (ret < 0) {
+            ret = -errno;
         }
     }
+    switch(ret) {
+    case -ENOTCONN:
+    case -ECONNREFUSED:
+    case -ENOENT:
+        if (__android_log_trylock()) {
+            return ret; /* in a signal handler? try again when less stressed */
+        }
+        __logdClose(ret);
+        ret = logdOpen();
+        __android_log_unlock();
+
+        if (ret < 0) {
+            return ret;
+        }
+
+        ret = TEMP_FAILURE_RETRY(writev(
+                atomic_load(&logdLoggerWrite.context.sock), newVec, i));
+        if (ret < 0) {
+            ret = -errno;
+        }
+        /* FALLTHRU */
+    default:
+        break;
+    }
 
     if (ret > (ssize_t)sizeof(header)) {
         ret -= sizeof(header);
diff --git a/liblog/tests/liblog_test.cpp b/liblog/tests/liblog_test.cpp
index 371e6ca..ec0352e 100644
--- a/liblog/tests/liblog_test.cpp
+++ b/liblog/tests/liblog_test.cpp
@@ -270,18 +270,19 @@
 
         ASSERT_EQ(log_msg.entry.pid, pid);
 
-        if ((log_msg.entry.len != (4 + 1 + 8))
+        if ((log_msg.entry.len != sizeof(android_log_event_long_t))
          || (log_msg.id() != LOG_ID_EVENTS)) {
             continue;
         }
 
-        char *eventData = log_msg.msg();
+        android_log_event_long_t* eventData;
+        eventData = reinterpret_cast<android_log_event_long_t*>(log_msg.msg());
 
-        if (!eventData || (eventData[4] != EVENT_TYPE_LONG)) {
+        if (!eventData || (eventData->payload.type != EVENT_TYPE_LONG)) {
             continue;
         }
 
-        log_time tx(eventData + 4 + 1);
+        log_time tx(reinterpret_cast<char*>(&eventData->payload.data));
         if (ts == tx) {
             ++count;
         } else if (ts1 == tx) {
@@ -352,18 +353,20 @@
 
         if ((log_msg.entry.sec < (ts.tv_sec - 1))
          || ((ts.tv_sec + 1) < log_msg.entry.sec)
-         || ((size_t)log_msg.entry.len != (4 + 1 + 4 + length))
+         || ((size_t)log_msg.entry.len != (sizeof(android_log_event_string_t) +
+                                           length))
          || (log_msg.id() != LOG_ID_EVENTS)) {
             continue;
         }
 
-        char *eventData = log_msg.msg();
+        android_log_event_string_t* eventData;
+        eventData = reinterpret_cast<android_log_event_string_t*>(log_msg.msg());
 
-        if (!eventData || (eventData[4] != EVENT_TYPE_STRING)) {
+        if (!eventData || (eventData->type != EVENT_TYPE_STRING)) {
             continue;
         }
 
-        size_t len = get4LE(eventData + 4 + 1);
+        size_t len = get4LE(reinterpret_cast<char*>(&eventData->length));
         if (len == total) {
             ++count;
 
@@ -501,189 +504,6 @@
     buf_write_test("\n Hello World \n");
 }
 
-TEST(liblog, __security) {
-#ifdef __ANDROID__
-    static const char persist_key[] = "persist.logd.security";
-    static const char readonly_key[] = "ro.device_owner";
-    static const char nothing_val[] = "_NOTHING_TO_SEE_HERE_";
-    char persist[PROP_VALUE_MAX];
-    char readonly[PROP_VALUE_MAX];
-
-    property_get(persist_key, persist, "");
-    property_get(readonly_key, readonly, nothing_val);
-
-    if (!strcmp(readonly, nothing_val)) {
-        EXPECT_FALSE(__android_log_security());
-        fprintf(stderr, "Warning, setting ro.device_owner to a domain\n");
-        property_set(readonly_key, "com.google.android.SecOps.DeviceOwner");
-    } else if (!strcasecmp(readonly, "false") || !readonly[0]) {
-        EXPECT_FALSE(__android_log_security());
-        return;
-    }
-
-    if (!strcasecmp(persist, "true")) {
-        EXPECT_TRUE(__android_log_security());
-    } else {
-        EXPECT_FALSE(__android_log_security());
-    }
-    property_set(persist_key, "TRUE");
-    EXPECT_TRUE(__android_log_security());
-    property_set(persist_key, "FALSE");
-    EXPECT_FALSE(__android_log_security());
-    property_set(persist_key, "true");
-    EXPECT_TRUE(__android_log_security());
-    property_set(persist_key, "false");
-    EXPECT_FALSE(__android_log_security());
-    property_set(persist_key, "");
-    EXPECT_FALSE(__android_log_security());
-    property_set(persist_key, persist);
-#else
-    GTEST_LOG_(INFO) << "This test does nothing.\n";
-#endif
-}
-
-TEST(liblog, __security_buffer) {
-#ifdef __ANDROID__
-    struct logger_list *logger_list;
-    android_event_long_t buffer;
-
-    static const char persist_key[] = "persist.logd.security";
-    char persist[PROP_VALUE_MAX];
-    bool set_persist = false;
-    bool allow_security = false;
-
-    if (__android_log_security()) {
-        allow_security = true;
-    } else {
-        property_get(persist_key, persist, "");
-        if (strcasecmp(persist, "true")) {
-            property_set(persist_key, "TRUE");
-            if (__android_log_security()) {
-                allow_security = true;
-                set_persist = true;
-            } else {
-                property_set(persist_key, persist);
-            }
-        }
-    }
-
-    if (!allow_security) {
-        fprintf(stderr, "WARNING: "
-                "security buffer disabled, bypassing end-to-end test\n");
-
-        log_time ts(CLOCK_MONOTONIC);
-
-        buffer.type = EVENT_TYPE_LONG;
-        buffer.data = *(static_cast<uint64_t *>((void *)&ts));
-
-        // expect failure!
-        ASSERT_GE(0, __android_log_security_bwrite(0, &buffer, sizeof(buffer)));
-
-        return;
-    }
-
-    /* Matches clientHasLogCredentials() in logd */
-    uid_t uid = getuid();
-    gid_t gid = getgid();
-    bool clientHasLogCredentials = true;
-    if ((uid != AID_SYSTEM) && (uid != AID_ROOT) && (uid != AID_LOG)
-     && (gid != AID_SYSTEM) && (gid != AID_ROOT) && (gid != AID_LOG)) {
-        uid_t euid = geteuid();
-        if ((euid != AID_SYSTEM) && (euid != AID_ROOT) && (euid != AID_LOG)) {
-            gid_t egid = getegid();
-            if ((egid != AID_SYSTEM) && (egid != AID_ROOT) && (egid != AID_LOG)) {
-                int num_groups = getgroups(0, NULL);
-                if (num_groups > 0) {
-                    gid_t groups[num_groups];
-                    num_groups = getgroups(num_groups, groups);
-                    while (num_groups > 0) {
-                        if (groups[num_groups - 1] == AID_LOG) {
-                            break;
-                        }
-                        --num_groups;
-                    }
-                }
-                if (num_groups <= 0) {
-                    clientHasLogCredentials = false;
-                }
-            }
-        }
-    }
-    if (!clientHasLogCredentials) {
-        fprintf(stderr, "WARNING: "
-                "not in system context, bypassing end-to-end test\n");
-
-        log_time ts(CLOCK_MONOTONIC);
-
-        buffer.type = EVENT_TYPE_LONG;
-        buffer.data = *(static_cast<uint64_t *>((void *)&ts));
-
-        // expect failure!
-        ASSERT_GE(0, __android_log_security_bwrite(0, &buffer, sizeof(buffer)));
-
-        return;
-    }
-
-    setuid(AID_SYSTEM); // only one that can read security buffer
-
-    pid_t pid = getpid();
-
-    ASSERT_TRUE(NULL != (logger_list = android_logger_list_open(
-        LOG_ID_SECURITY, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK,
-        1000, pid)));
-
-    log_time ts(CLOCK_MONOTONIC);
-
-    buffer.type = EVENT_TYPE_LONG;
-    buffer.data = *(static_cast<uint64_t *>((void *)&ts));
-
-    ASSERT_LT(0, __android_log_security_bwrite(0, &buffer, sizeof(buffer)));
-    usleep(1000000);
-
-    int count = 0;
-
-    for (;;) {
-        log_msg log_msg;
-        if (android_logger_list_read(logger_list, &log_msg) <= 0) {
-            break;
-        }
-
-        ASSERT_EQ(log_msg.entry.pid, pid);
-
-        if ((log_msg.entry.len != (4 + 1 + 8))
-         || (log_msg.id() != LOG_ID_SECURITY)) {
-            continue;
-        }
-
-        char *eventData = log_msg.msg();
-
-        if (!eventData || (eventData[4] != EVENT_TYPE_LONG)) {
-            continue;
-        }
-
-        log_time tx(eventData + 4 + 1);
-        if (ts == tx) {
-            ++count;
-        }
-    }
-
-    if (set_persist) {
-        property_set(persist_key, persist);
-    }
-
-    android_logger_list_close(logger_list);
-
-    bool clientHasSecurityCredentials = (uid == AID_SYSTEM) || (gid == AID_SYSTEM);
-    if (!clientHasSecurityCredentials) {
-        fprintf(stderr, "WARNING: "
-                "not system, content submitted but can not check end-to-end\n");
-    }
-    EXPECT_EQ(clientHasSecurityCredentials ? 1 : 0, count);
-#else
-    GTEST_LOG_(INFO) << "This test does nothing.\n";
-#endif
-}
-
 #ifdef __ANDROID__
 static unsigned signaled;
 static log_time signal_time;
@@ -786,25 +606,27 @@
 
         ASSERT_EQ(log_msg.entry.pid, pid);
 
-        if ((log_msg.entry.len != (4 + 1 + 8))
+        if ((log_msg.entry.len != sizeof(android_log_event_long_t))
          || (log_msg.id() != LOG_ID_EVENTS)) {
             continue;
         }
 
-        char *eventData = log_msg.msg();
+        android_log_event_long_t* eventData;
+        eventData = reinterpret_cast<android_log_event_long_t*>(log_msg.msg());
 
-        if (!eventData || (eventData[4] != EVENT_TYPE_LONG)) {
+        if (!eventData || (eventData->payload.type != EVENT_TYPE_LONG)) {
             continue;
         }
 
-        unsigned long long l = eventData[4 + 1 + 0] & 0xFF;
-        l |= (unsigned long long) (eventData[4 + 1 + 1] & 0xFF) << 8;
-        l |= (unsigned long long) (eventData[4 + 1 + 2] & 0xFF) << 16;
-        l |= (unsigned long long) (eventData[4 + 1 + 3] & 0xFF) << 24;
-        l |= (unsigned long long) (eventData[4 + 1 + 4] & 0xFF) << 32;
-        l |= (unsigned long long) (eventData[4 + 1 + 5] & 0xFF) << 40;
-        l |= (unsigned long long) (eventData[4 + 1 + 6] & 0xFF) << 48;
-        l |= (unsigned long long) (eventData[4 + 1 + 7] & 0xFF) << 56;
+        char* cp = reinterpret_cast<char*>(&eventData->payload.data);
+        unsigned long long l = cp[0] & 0xFF;
+        l |= (unsigned long long) (cp[1] & 0xFF) << 8;
+        l |= (unsigned long long) (cp[2] & 0xFF) << 16;
+        l |= (unsigned long long) (cp[3] & 0xFF) << 24;
+        l |= (unsigned long long) (cp[4] & 0xFF) << 32;
+        l |= (unsigned long long) (cp[5] & 0xFF) << 40;
+        l |= (unsigned long long) (cp[6] & 0xFF) << 48;
+        l |= (unsigned long long) (cp[7] & 0xFF) << 56;
 
         if (l == v) {
             ++signals;
@@ -943,25 +765,27 @@
 
         ASSERT_EQ(log_msg.entry.pid, pid);
 
-        if ((log_msg.entry.len != (4 + 1 + 8))
+        if ((log_msg.entry.len != sizeof(android_log_event_long_t))
          || (log_msg.id() != LOG_ID_EVENTS)) {
             continue;
         }
 
-        char *eventData = log_msg.msg();
+        android_log_event_long_t* eventData;
+        eventData = reinterpret_cast<android_log_event_long_t*>(log_msg.msg());
 
-        if (!eventData || (eventData[4] != EVENT_TYPE_LONG)) {
+        if (!eventData || (eventData->payload.type != EVENT_TYPE_LONG)) {
             continue;
         }
 
-        unsigned long long l = eventData[4 + 1 + 0] & 0xFF;
-        l |= (unsigned long long) (eventData[4 + 1 + 1] & 0xFF) << 8;
-        l |= (unsigned long long) (eventData[4 + 1 + 2] & 0xFF) << 16;
-        l |= (unsigned long long) (eventData[4 + 1 + 3] & 0xFF) << 24;
-        l |= (unsigned long long) (eventData[4 + 1 + 4] & 0xFF) << 32;
-        l |= (unsigned long long) (eventData[4 + 1 + 5] & 0xFF) << 40;
-        l |= (unsigned long long) (eventData[4 + 1 + 6] & 0xFF) << 48;
-        l |= (unsigned long long) (eventData[4 + 1 + 7] & 0xFF) << 56;
+        char* cp = reinterpret_cast<char*>(&eventData->payload.data);
+        unsigned long long l = cp[0] & 0xFF;
+        l |= (unsigned long long) (cp[1] & 0xFF) << 8;
+        l |= (unsigned long long) (cp[2] & 0xFF) << 16;
+        l |= (unsigned long long) (cp[3] & 0xFF) << 24;
+        l |= (unsigned long long) (cp[4] & 0xFF) << 32;
+        l |= (unsigned long long) (cp[5] & 0xFF) << 40;
+        l |= (unsigned long long) (cp[6] & 0xFF) << 48;
+        l |= (unsigned long long) (cp[7] & 0xFF) << 56;
 
         if (l == v) {
             ++signals;
@@ -1367,6 +1191,9 @@
 
 TEST(liblog, android_logger_get_) {
 #ifdef __ANDROID__
+    // This test assumes the log buffers are filled with noise from
+    // normal operations. It will fail if done immediately after a
+    // logcat -c.
     struct logger_list * logger_list = android_logger_list_alloc(ANDROID_LOG_WRONLY, 0, 0);
 
     for(int i = LOG_ID_MIN; i < LOG_ID_MAX; ++i) {
@@ -1778,6 +1605,294 @@
 }
 
 #ifdef __ANDROID__
+// helper to liblog.enoent to count end-to-end matching logging messages.
+static int count_matching_ts(log_time ts) {
+    usleep(1000000);
+
+    pid_t pid = getpid();
+
+    struct logger_list* logger_list = android_logger_list_open(
+        LOG_ID_EVENTS, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, 1000, pid);
+
+    int count = 0;
+    if (logger_list == NULL) return count;
+
+    for (;;) {
+        log_msg log_msg;
+        if (android_logger_list_read(logger_list, &log_msg) <= 0) break;
+
+        if (log_msg.entry.len != sizeof(android_log_event_long_t)) continue;
+        if (log_msg.id() != LOG_ID_EVENTS) continue;
+
+        android_log_event_long_t* eventData;
+        eventData = reinterpret_cast<android_log_event_long_t*>(log_msg.msg());
+        if (!eventData) continue;
+        if (eventData->payload.type != EVENT_TYPE_LONG) continue;
+
+        log_time tx(reinterpret_cast<char*>(&eventData->payload.data));
+        if (ts != tx) continue;
+
+        // found event message with matching timestamp signature in payload
+        ++count;
+    }
+    android_logger_list_close(logger_list);
+
+    return count;
+}
+
+// meant to be handed to ASSERT_TRUE / EXPECT_TRUE only to expand the message
+static testing::AssertionResult IsOk(bool ok, std::string &message) {
+    return ok ?
+        testing::AssertionSuccess() :
+        (testing::AssertionFailure() << message);
+}
+#endif
+
+TEST(liblog, enoent) {
+#ifdef __ANDROID__
+    log_time ts(CLOCK_MONOTONIC);
+    EXPECT_LT(0, __android_log_btwrite(0, EVENT_TYPE_LONG, &ts, sizeof(ts)));
+    EXPECT_EQ(1, count_matching_ts(ts));
+
+    // This call will fail if we are setuid(AID_SYSTEM), beware of any
+    // test prior to this one playing with setuid and causing interference.
+    // We need to run before these tests so that they do not interfere with
+    // this test.
+    //
+    // Stopping the logger can affect some other test's expectations as they
+    // count on the log buffers filled with existing content, and this
+    // effectively does a logcat -c emptying it.  So we want this test to be
+    // as near as possible to the bottom of the file.  For example
+    // liblog.android_logger_get_ is one of those tests that has no recourse
+    // and that would be adversely affected by emptying the log if it was run
+    // right after this test.
+    system("stop logd");
+    usleep(1000000);
+
+    // A clean stop like we are testing returns -ENOENT, but in the _real_
+    // world we could get -ENOTCONN or -ECONNREFUSED depending on timing.
+    // Alas we can not test these other return values; accept that they
+    // are treated equally within the open-retry logic in liblog.
+    ts = log_time(CLOCK_MONOTONIC);
+    int ret = __android_log_btwrite(0, EVENT_TYPE_LONG, &ts, sizeof(ts));
+    std::string content = android::base::StringPrintf(
+        "__android_log_btwrite(0, EVENT_TYPE_LONG, &ts, sizeof(ts)) = %d %s\n",
+        ret, strerror(-ret));
+    EXPECT_TRUE(IsOk((ret == -ENOENT) ||
+                     (ret == -ENOTCONN) ||
+                     (ret == -ECONNREFUSED), content));
+    ret = __android_log_btwrite(0, EVENT_TYPE_LONG, &ts, sizeof(ts));
+    content = android::base::StringPrintf(
+        "__android_log_btwrite(0, EVENT_TYPE_LONG, &ts, sizeof(ts)) = %d %s\n",
+        ret, strerror(-ret));
+    EXPECT_TRUE(IsOk((ret == -ENOENT) ||
+                     (ret == -ENOTCONN) ||
+                     (ret == -ECONNREFUSED), content));
+    EXPECT_EQ(0, count_matching_ts(ts));
+
+    system("start logd");
+    usleep(1000000);
+
+    EXPECT_EQ(0, count_matching_ts(ts));
+
+    ts = log_time(CLOCK_MONOTONIC);
+    EXPECT_LT(0, __android_log_btwrite(0, EVENT_TYPE_LONG, &ts, sizeof(ts)));
+    EXPECT_EQ(1, count_matching_ts(ts));
+
+#else
+    GTEST_LOG_(INFO) << "This test does nothing.\n";
+#endif
+}
+
+// Below this point we run risks of setuid(AID_SYSTEM) which may affect others.
+
+TEST(liblog, __security) {
+#ifdef __ANDROID__
+    static const char persist_key[] = "persist.logd.security";
+    static const char readonly_key[] = "ro.device_owner";
+    // A silly default value that can never be in readonly_key so
+    // that it can be determined the property is not set.
+    static const char nothing_val[] = "_NOTHING_TO_SEE_HERE_";
+    char persist[PROP_VALUE_MAX];
+    char readonly[PROP_VALUE_MAX];
+
+    property_get(persist_key, persist, "");
+    property_get(readonly_key, readonly, nothing_val);
+
+    if (!strcmp(readonly, nothing_val)) {
+        EXPECT_FALSE(__android_log_security());
+        fprintf(stderr, "Warning, setting ro.device_owner to a domain\n");
+        property_set(readonly_key, "com.google.android.SecOps.DeviceOwner");
+    } else if (!strcasecmp(readonly, "false") || !readonly[0]) {
+        EXPECT_FALSE(__android_log_security());
+        return;
+    }
+
+    if (!strcasecmp(persist, "true")) {
+        EXPECT_TRUE(__android_log_security());
+    } else {
+        EXPECT_FALSE(__android_log_security());
+    }
+    property_set(persist_key, "TRUE");
+    EXPECT_TRUE(__android_log_security());
+    property_set(persist_key, "FALSE");
+    EXPECT_FALSE(__android_log_security());
+    property_set(persist_key, "true");
+    EXPECT_TRUE(__android_log_security());
+    property_set(persist_key, "false");
+    EXPECT_FALSE(__android_log_security());
+    property_set(persist_key, "");
+    EXPECT_FALSE(__android_log_security());
+    property_set(persist_key, persist);
+#else
+    GTEST_LOG_(INFO) << "This test does nothing.\n";
+#endif
+}
+
+TEST(liblog, __security_buffer) {
+#ifdef __ANDROID__
+    struct logger_list *logger_list;
+    android_event_long_t buffer;
+
+    static const char persist_key[] = "persist.logd.security";
+    char persist[PROP_VALUE_MAX];
+    bool set_persist = false;
+    bool allow_security = false;
+
+    if (__android_log_security()) {
+        allow_security = true;
+    } else {
+        property_get(persist_key, persist, "");
+        if (strcasecmp(persist, "true")) {
+            property_set(persist_key, "TRUE");
+            if (__android_log_security()) {
+                allow_security = true;
+                set_persist = true;
+            } else {
+                property_set(persist_key, persist);
+            }
+        }
+    }
+
+    if (!allow_security) {
+        fprintf(stderr, "WARNING: "
+                "security buffer disabled, bypassing end-to-end test\n");
+
+        log_time ts(CLOCK_MONOTONIC);
+
+        buffer.type = EVENT_TYPE_LONG;
+        buffer.data = *(static_cast<uint64_t *>((void *)&ts));
+
+        // expect failure!
+        ASSERT_GE(0, __android_log_security_bwrite(0, &buffer, sizeof(buffer)));
+
+        return;
+    }
+
+    /* Matches clientHasLogCredentials() in logd */
+    uid_t uid = getuid();
+    gid_t gid = getgid();
+    bool clientHasLogCredentials = true;
+    if ((uid != AID_SYSTEM) && (uid != AID_ROOT) && (uid != AID_LOG)
+     && (gid != AID_SYSTEM) && (gid != AID_ROOT) && (gid != AID_LOG)) {
+        uid_t euid = geteuid();
+        if ((euid != AID_SYSTEM) && (euid != AID_ROOT) && (euid != AID_LOG)) {
+            gid_t egid = getegid();
+            if ((egid != AID_SYSTEM) && (egid != AID_ROOT) && (egid != AID_LOG)) {
+                int num_groups = getgroups(0, NULL);
+                if (num_groups > 0) {
+                    gid_t groups[num_groups];
+                    num_groups = getgroups(num_groups, groups);
+                    while (num_groups > 0) {
+                        if (groups[num_groups - 1] == AID_LOG) {
+                            break;
+                        }
+                        --num_groups;
+                    }
+                }
+                if (num_groups <= 0) {
+                    clientHasLogCredentials = false;
+                }
+            }
+        }
+    }
+    if (!clientHasLogCredentials) {
+        fprintf(stderr, "WARNING: "
+                "not in system context, bypassing end-to-end test\n");
+
+        log_time ts(CLOCK_MONOTONIC);
+
+        buffer.type = EVENT_TYPE_LONG;
+        buffer.data = *(static_cast<uint64_t *>((void *)&ts));
+
+        // expect failure!
+        ASSERT_GE(0, __android_log_security_bwrite(0, &buffer, sizeof(buffer)));
+
+        return;
+    }
+
+    EXPECT_EQ(0, setuid(AID_SYSTEM)); // only one that can read security buffer
+
+    pid_t pid = getpid();
+
+    ASSERT_TRUE(NULL != (logger_list = android_logger_list_open(
+        LOG_ID_SECURITY, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK,
+        1000, pid)));
+
+    log_time ts(CLOCK_MONOTONIC);
+
+    buffer.type = EVENT_TYPE_LONG;
+    buffer.data = *(static_cast<uint64_t *>((void *)&ts));
+
+    ASSERT_LT(0, __android_log_security_bwrite(0, &buffer, sizeof(buffer)));
+    usleep(1000000);
+
+    int count = 0;
+
+    for (;;) {
+        log_msg log_msg;
+        if (android_logger_list_read(logger_list, &log_msg) <= 0) {
+            break;
+        }
+
+        ASSERT_EQ(log_msg.entry.pid, pid);
+
+        if ((log_msg.entry.len != sizeof(android_log_event_long_t))
+         || (log_msg.id() != LOG_ID_SECURITY)) {
+            continue;
+        }
+
+        android_log_event_long_t* eventData;
+        eventData = reinterpret_cast<android_log_event_long_t*>(log_msg.msg());
+
+        if (!eventData || (eventData->payload.type != EVENT_TYPE_LONG)) {
+            continue;
+        }
+
+        log_time tx(reinterpret_cast<char*>(&eventData->payload.data));
+        if (ts == tx) {
+            ++count;
+        }
+    }
+
+    if (set_persist) {
+        property_set(persist_key, persist);
+    }
+
+    android_logger_list_close(logger_list);
+
+    bool clientHasSecurityCredentials = (uid == AID_SYSTEM) || (gid == AID_SYSTEM);
+    if (!clientHasSecurityCredentials) {
+        fprintf(stderr, "WARNING: "
+                "not system, content submitted but can not check end-to-end\n");
+    }
+    EXPECT_EQ(clientHasSecurityCredentials ? 1 : 0, count);
+#else
+    GTEST_LOG_(INFO) << "This test does nothing.\n";
+#endif
+}
+
+#ifdef __ANDROID__
 static void android_errorWriteWithInfoLog_helper(int TAG, const char* SUBTAG,
                                                  int UID, const char* payload,
                                                  int DATA_LEN, int& count) {
@@ -1842,7 +1957,7 @@
         int subtag_len = strlen(SUBTAG);
         if (subtag_len > 32) subtag_len = 32;
         ASSERT_EQ(subtag_len, get4LE(eventData));
-        eventData +=4;
+        eventData += 4;
 
         if (memcmp(SUBTAG, eventData, subtag_len)) {
             continue;
@@ -2795,13 +2910,6 @@
 }
 
 #ifdef __ANDROID__
-// meant to be handed to ASSERT_TRUE / EXPECT_TRUE only to expand the message
-static testing::AssertionResult IsOk(bool ok, std::string &message) {
-    return ok ?
-        testing::AssertionSuccess() :
-        (testing::AssertionFailure() << message);
-}
-
 // must be: '<needle:> 0 kB'
 static bool isZero(const std::string &content, std::string::size_type pos,
                    const char* needle) {
diff --git a/libmemtrack/memtrack.c b/libmemtrack/memtrack.c
index 29cc92c..9ed9451 100644
--- a/libmemtrack/memtrack.c
+++ b/libmemtrack/memtrack.c
@@ -22,8 +22,8 @@
 #include <malloc.h>
 #include <string.h>
 
-#include <android/log.h>
 #include <hardware/memtrack.h>
+#include <log/log.h>
 
 #define ARRAY_SIZE(x) (sizeof(x)/sizeof((x)[0]))
 
diff --git a/libmemunreachable/log.h b/libmemunreachable/log.h
index dd146b6..cdfbfd9 100644
--- a/libmemunreachable/log.h
+++ b/libmemunreachable/log.h
@@ -19,6 +19,6 @@
 
 #define LOG_TAG "libmemunreachable"
 
-#include <android/log.h>
+#include <log/log.h>
 
 #endif // LIBMEMUNREACHABLE_LOG_H_
diff --git a/libnativebridge/native_bridge.cc b/libnativebridge/native_bridge.cc
index eafc53d..83f35b1 100644
--- a/libnativebridge/native_bridge.cc
+++ b/libnativebridge/native_bridge.cc
@@ -28,7 +28,7 @@
 
 #include <cstring>
 
-#include <android/log.h>
+#include <log/log.h>
 
 namespace android {
 
diff --git a/libnativeloader/Android.bp b/libnativeloader/Android.bp
index 9d33899..c1133fb 100644
--- a/libnativeloader/Android.bp
+++ b/libnativeloader/Android.bp
@@ -9,8 +9,8 @@
         "liblog",
         "libcutils",
         "libnativebridge",
+        "libbase",
     ],
-    static_libs: ["libbase"],
     target: {
         android: {
             shared_libs: ["libdl"],
diff --git a/libnativeloader/native_loader.cpp b/libnativeloader/native_loader.cpp
index 15fe054..94c46fc 100644
--- a/libnativeloader/native_loader.cpp
+++ b/libnativeloader/native_loader.cpp
@@ -19,10 +19,10 @@
 
 #include <dlfcn.h>
 #ifdef __ANDROID__
-#include "dlext_namespaces.h"
 #define LOG_TAG "libnativeloader"
-#include "android/log.h"
+#include "dlext_namespaces.h"
 #include "cutils/properties.h"
+#include "log/log.h"
 #endif
 #include "nativebridge/native_bridge.h"
 
diff --git a/libnetutils/dhcpclient.c b/libnetutils/dhcpclient.c
index d17bdd3..11c116a 100644
--- a/libnetutils/dhcpclient.c
+++ b/libnetutils/dhcpclient.c
@@ -31,8 +31,8 @@
 #include <time.h>
 #include <unistd.h>
 
-#include <android/log.h>
 #include <cutils/properties.h>
+#include <log/log.h>
 
 #include <netutils/ifc.h>
 #include "dhcpmsg.h"
diff --git a/libnetutils/ifc_utils.c b/libnetutils/ifc_utils.c
index 275327a..a098d59 100644
--- a/libnetutils/ifc_utils.c
+++ b/libnetutils/ifc_utils.c
@@ -38,8 +38,8 @@
 
 #ifdef ANDROID
 #define LOG_TAG "NetUtils"
-#include <android/log.h>
 #include <cutils/properties.h>
+#include <log/log.h>
 #else
 #define ALOGD printf
 #define ALOGW printf
diff --git a/libnetutils/packet.c b/libnetutils/packet.c
index 56168e8..e53a4c8 100644
--- a/libnetutils/packet.c
+++ b/libnetutils/packet.c
@@ -28,7 +28,7 @@
 
 #ifdef ANDROID
 #define LOG_TAG "DHCP"
-#include <android/log.h>
+#include <log/log.h>
 #else
 #include <stdio.h>
 #define ALOGD printf
diff --git a/libpackagelistparser/packagelistparser.c b/libpackagelistparser/packagelistparser.c
index f74b8b4..3e1a3d1 100644
--- a/libpackagelistparser/packagelistparser.c
+++ b/libpackagelistparser/packagelistparser.c
@@ -27,7 +27,7 @@
 #include <string.h>
 #include <sys/limits.h>
 
-#include <android/log.h>
+#include <log/log.h>
 #include <packagelistparser/packagelistparser.h>
 
 #define CLOGE(fmt, ...) \
diff --git a/libpixelflinger/codeflinger/ARMAssembler.cpp b/libpixelflinger/codeflinger/ARMAssembler.cpp
index 36c1326..ac009a9 100644
--- a/libpixelflinger/codeflinger/ARMAssembler.cpp
+++ b/libpixelflinger/codeflinger/ARMAssembler.cpp
@@ -20,8 +20,8 @@
 #include <stdio.h>
 #include <stdlib.h>
 
-#include <android/log.h>
 #include <cutils/properties.h>
+#include <log/log.h>
 #include <private/pixelflinger/ggl_context.h>
 
 #include "ARMAssembler.h"
diff --git a/libpixelflinger/codeflinger/ARMAssemblerInterface.cpp b/libpixelflinger/codeflinger/ARMAssemblerInterface.cpp
index e212f1b..c96cf4b 100644
--- a/libpixelflinger/codeflinger/ARMAssemblerInterface.cpp
+++ b/libpixelflinger/codeflinger/ARMAssemblerInterface.cpp
@@ -21,7 +21,7 @@
 #include <stdlib.h>
 #include <sys/types.h>
 
-#include <android/log.h>
+#include <log/log.h>
 
 #include "ARMAssemblerInterface.h"
 
diff --git a/libpixelflinger/codeflinger/Arm64Assembler.cpp b/libpixelflinger/codeflinger/Arm64Assembler.cpp
index fb297ec..bff87bb 100644
--- a/libpixelflinger/codeflinger/Arm64Assembler.cpp
+++ b/libpixelflinger/codeflinger/Arm64Assembler.cpp
@@ -32,8 +32,8 @@
 #include <stdlib.h>
 #include <string.h>
 
-#include <android/log.h>
 #include <cutils/properties.h>
+#include <log/log.h>
 #include <private/pixelflinger/ggl_context.h>
 
 #include "codeflinger/Arm64Assembler.h"
diff --git a/libpixelflinger/codeflinger/CodeCache.cpp b/libpixelflinger/codeflinger/CodeCache.cpp
index 37bd074..8516640 100644
--- a/libpixelflinger/codeflinger/CodeCache.cpp
+++ b/libpixelflinger/codeflinger/CodeCache.cpp
@@ -23,8 +23,8 @@
 #include <sys/mman.h>
 #include <unistd.h>
 
-#include <android/log.h>
 #include <cutils/ashmem.h>
+#include <log/log.h>
 
 #include "CodeCache.h"
 
diff --git a/libpixelflinger/codeflinger/GGLAssembler.cpp b/libpixelflinger/codeflinger/GGLAssembler.cpp
index 0b9b5a4..91fbd53 100644
--- a/libpixelflinger/codeflinger/GGLAssembler.cpp
+++ b/libpixelflinger/codeflinger/GGLAssembler.cpp
@@ -23,7 +23,7 @@
 #include <stdlib.h>
 #include <sys/types.h>
 
-#include <android/log.h>
+#include <log/log.h>
 
 #include "GGLAssembler.h"
 
diff --git a/libpixelflinger/codeflinger/MIPS64Assembler.cpp b/libpixelflinger/codeflinger/MIPS64Assembler.cpp
index a7bbaf7..d5e4cea 100644
--- a/libpixelflinger/codeflinger/MIPS64Assembler.cpp
+++ b/libpixelflinger/codeflinger/MIPS64Assembler.cpp
@@ -30,8 +30,8 @@
 #include <stdio.h>
 #include <stdlib.h>
 
-#include <android/log.h>
 #include <cutils/properties.h>
+#include <log/log.h>
 #include <private/pixelflinger/ggl_context.h>
 
 #include "MIPS64Assembler.h"
diff --git a/libpixelflinger/codeflinger/MIPSAssembler.cpp b/libpixelflinger/codeflinger/MIPSAssembler.cpp
index 4cddcc8..865a568 100644
--- a/libpixelflinger/codeflinger/MIPSAssembler.cpp
+++ b/libpixelflinger/codeflinger/MIPSAssembler.cpp
@@ -47,14 +47,13 @@
 ** functions in ARMAssemblerInterface.cpp so they could be used as static initializers).
 */
 
-
 #define LOG_TAG "MIPSAssembler"
 
 #include <stdio.h>
 #include <stdlib.h>
 
-#include <android/log.h>
 #include <cutils/properties.h>
+#include <log/log.h>
 #include <private/pixelflinger/ggl_context.h>
 
 #include "CodeCache.h"
diff --git a/libpixelflinger/codeflinger/blending.cpp b/libpixelflinger/codeflinger/blending.cpp
index 092f140..a55dfe3 100644
--- a/libpixelflinger/codeflinger/blending.cpp
+++ b/libpixelflinger/codeflinger/blending.cpp
@@ -23,7 +23,7 @@
 #include <stdlib.h>
 #include <sys/types.h>
 
-#include <android/log.h>
+#include <log/log.h>
 
 #include "GGLAssembler.h"
 
diff --git a/libpixelflinger/codeflinger/load_store.cpp b/libpixelflinger/codeflinger/load_store.cpp
index b8a0e55..da21e1d 100644
--- a/libpixelflinger/codeflinger/load_store.cpp
+++ b/libpixelflinger/codeflinger/load_store.cpp
@@ -20,7 +20,7 @@
 #include <assert.h>
 #include <stdio.h>
 
-#include <android/log.h>
+#include <log/log.h>
 
 #include "GGLAssembler.h"
 
diff --git a/libpixelflinger/codeflinger/texturing.cpp b/libpixelflinger/codeflinger/texturing.cpp
index f4f4657..4c357af 100644
--- a/libpixelflinger/codeflinger/texturing.cpp
+++ b/libpixelflinger/codeflinger/texturing.cpp
@@ -23,7 +23,7 @@
 #include <stdlib.h>
 #include <sys/types.h>
 
-#include <android/log.h>
+#include <log/log.h>
 
 #include "GGLAssembler.h"
 
diff --git a/libpixelflinger/scanline.cpp b/libpixelflinger/scanline.cpp
index 1a2f6fb..c6cf5bf 100644
--- a/libpixelflinger/scanline.cpp
+++ b/libpixelflinger/scanline.cpp
@@ -22,8 +22,8 @@
 #include <stdlib.h>
 #include <string.h>
 
-#include <android/log.h>
 #include <cutils/memory.h>
+#include <log/log.h>
 
 #include "buffer.h"
 #include "scanline.h"
diff --git a/libpixelflinger/trap.cpp b/libpixelflinger/trap.cpp
index fa6338a..234bfdd 100644
--- a/libpixelflinger/trap.cpp
+++ b/libpixelflinger/trap.cpp
@@ -21,8 +21,8 @@
 #include <stdio.h>
 #include <stdlib.h>
 
-#include <android/log.h>
 #include <cutils/memory.h>
+#include <log/log.h>
 
 #include "trap.h"
 #include "picker.h"
diff --git a/libsparse/Android.bp b/libsparse/Android.bp
index 7a6ae8a..dd8b5fd 100644
--- a/libsparse/Android.bp
+++ b/libsparse/Android.bp
@@ -1,7 +1,9 @@
 // Copyright 2010 The Android Open Source Project
 
-cc_defaults {
-    name: "libsparse_defaults",
+cc_library {
+    name: "libsparse",
+    host_supported: true,
+    unique_host_soname: true,
     srcs: [
         "backed_block.c",
         "output_file.c",
@@ -13,32 +15,19 @@
     cflags: ["-Werror"],
     local_include_dirs: ["include"],
     export_include_dirs: ["include"],
-}
-
-cc_library_host_static {
-    name: "libsparse_host",
-    defaults: ["libsparse_defaults"],
-    static_libs: ["libz"],
     target: {
+        host: {
+            shared_libs: ["libz-host"],
+        },
+        android: {
+            shared_libs: ["libz"],
+        },
         windows: {
             enabled: true,
         },
     },
 }
 
-cc_library_shared {
-    name: "libsparse",
-    defaults: ["libsparse_defaults"],
-    shared_libs: ["libz"],
-}
-
-cc_library_static {
-    name: "libsparse_static",
-    host_supported: true,
-    defaults: ["libsparse_defaults"],
-    static_libs: ["libz"],
-}
-
 cc_binary {
     name: "simg2img",
     host_supported: true,
@@ -47,7 +36,7 @@
         "sparse_crc32.c",
     ],
     static_libs: [
-        "libsparse_static",
+        "libsparse",
         "libz",
     ],
 
@@ -59,7 +48,7 @@
     host_supported: true,
     srcs: ["img2simg.c"],
     static_libs: [
-        "libsparse_static",
+        "libsparse",
         "libz",
     ],
 
@@ -70,7 +59,7 @@
     name: "append2simg",
     srcs: ["append2simg.c"],
     static_libs: [
-        "libsparse_static",
+        "libsparse",
         "libz",
     ],
 
diff --git a/libsuspend/autosuspend.c b/libsuspend/autosuspend.c
index 64d1bfc..54730c2 100644
--- a/libsuspend/autosuspend.c
+++ b/libsuspend/autosuspend.c
@@ -18,7 +18,7 @@
 
 #include <stdbool.h>
 
-#include <android/log.h>
+#include <log/log.h>
 
 #include <suspend/autosuspend.h>
 
diff --git a/libsuspend/autosuspend_autosleep.c b/libsuspend/autosuspend_autosleep.c
index 97109ac..77d8db0 100644
--- a/libsuspend/autosuspend_autosleep.c
+++ b/libsuspend/autosuspend_autosleep.c
@@ -24,7 +24,7 @@
 #include <sys/types.h>
 #include <unistd.h>
 
-#include <android/log.h>
+#include <log/log.h>
 
 #include "autosuspend_ops.h"
 
diff --git a/libsuspend/autosuspend_earlysuspend.c b/libsuspend/autosuspend_earlysuspend.c
index 9519e51..809ee82 100644
--- a/libsuspend/autosuspend_earlysuspend.c
+++ b/libsuspend/autosuspend_earlysuspend.c
@@ -26,7 +26,7 @@
 #include <sys/types.h>
 #include <unistd.h>
 
-#include <android/log.h>
+#include <log/log.h>
 
 #include "autosuspend_ops.h"
 
diff --git a/libsuspend/autosuspend_wakeup_count.c b/libsuspend/autosuspend_wakeup_count.c
index 3457d5b..2da204a 100644
--- a/libsuspend/autosuspend_wakeup_count.c
+++ b/libsuspend/autosuspend_wakeup_count.c
@@ -29,7 +29,7 @@
 #include <sys/types.h>
 #include <unistd.h>
 
-#include <android/log.h>
+#include <log/log.h>
 
 #include "autosuspend_ops.h"
 
diff --git a/libutils/Looper.cpp b/libutils/Looper.cpp
index 26e27cf..77e69e4 100644
--- a/libutils/Looper.cpp
+++ b/libutils/Looper.cpp
@@ -21,7 +21,7 @@
 #include <sys/eventfd.h>
 #include <unistd.h>
 
-#include <android/log.h>
+#include <log/log.h>
 #include <utils/Looper.h>
 #include <utils/Timers.h>
 
diff --git a/libutils/SharedBuffer.cpp b/libutils/SharedBuffer.cpp
index 269326a..957aedb 100644
--- a/libutils/SharedBuffer.cpp
+++ b/libutils/SharedBuffer.cpp
@@ -19,7 +19,7 @@
 #include <stdlib.h>
 #include <string.h>
 
-#include <android/log.h>
+#include <log/log.h>
 
 #include "SharedBuffer.h"
 
diff --git a/libutils/Unicode.cpp b/libutils/Unicode.cpp
index c32f462..f1a41b9 100644
--- a/libutils/Unicode.cpp
+++ b/libutils/Unicode.cpp
@@ -19,7 +19,7 @@
 #include <limits.h>
 #include <stddef.h>
 
-#include <android/log.h>
+#include <log/log.h>
 #include <utils/Unicode.h>
 
 #if defined(_WIN32)
diff --git a/libutils/VectorImpl.cpp b/libutils/VectorImpl.cpp
index 893e4f2..f7ca8f4 100644
--- a/libutils/VectorImpl.cpp
+++ b/libutils/VectorImpl.cpp
@@ -20,7 +20,7 @@
 #include <stdlib.h>
 #include <string.h>
 
-#include <android/log.h>
+#include <log/log.h>
 #include <utils/Errors.h>
 #include <utils/VectorImpl.h>
 
diff --git a/libziparchive/Android.bp b/libziparchive/Android.bp
index 1495f39..44daf36 100644
--- a/libziparchive/Android.bp
+++ b/libziparchive/Android.bp
@@ -57,11 +57,13 @@
     name: "libziparchive",
     host_supported: true,
     defaults: ["libziparchive_defaults", "libziparchive_flags"],
-    static_libs: ["libutils"],
     shared_libs: ["liblog", "libbase"],
     target: {
         android: {
-            static_libs: ["libz"],
+            shared_libs: ["libz", "libutils"],
+        },
+        host: {
+            static_libs: ["libutils"],
         },
         linux_bionic: {
             static_libs: ["libz"],
diff --git a/libziparchive/zip_archive_stream_entry.cc b/libziparchive/zip_archive_stream_entry.cc
index 64b24c3..3f336a6 100644
--- a/libziparchive/zip_archive_stream_entry.cc
+++ b/libziparchive/zip_archive_stream_entry.cc
@@ -26,8 +26,9 @@
 #include <memory>
 #include <vector>
 
-#include <android/log.h>
 #include <android-base/file.h>
+#include <log/log.h>
+
 #include <ziparchive/zip_archive.h>
 #include <ziparchive/zip_archive_stream_entry.h>
 #include <zlib.h>
diff --git a/lmkd/lmkd.c b/lmkd/lmkd.c
index 49746b3..8a6168c 100644
--- a/lmkd/lmkd.c
+++ b/lmkd/lmkd.c
@@ -31,8 +31,8 @@
 #include <sys/types.h>
 #include <unistd.h>
 
-#include <android/log.h>
 #include <cutils/sockets.h>
+#include <log/log.h>
 #include <processgroup/processgroup.h>
 
 #ifndef __unused
diff --git a/logwrapper/logwrap.c b/logwrapper/logwrap.c
index 1bfecd6..3ad0983 100644
--- a/logwrapper/logwrap.c
+++ b/logwrapper/logwrap.c
@@ -28,8 +28,8 @@
 #include <sys/wait.h>
 #include <unistd.h>
 
-#include <android/log.h>
 #include <cutils/klog.h>
+#include <log/log.h>
 #include <logwrap/logwrap.h>
 #include <private/android_filesystem_config.h>
 
diff --git a/logwrapper/logwrapper.c b/logwrapper/logwrapper.c
index 28fe530..33454c6 100644
--- a/logwrapper/logwrapper.c
+++ b/logwrapper/logwrapper.c
@@ -20,8 +20,8 @@
 #include <sys/wait.h>
 #include <unistd.h>
 
-#include <android/log.h>
 #include <cutils/klog.h>
+#include <log/log.h>
 #include <logwrap/logwrap.h>
 
 void fatal(const char *msg) {
diff --git a/rootdir/init.rc b/rootdir/init.rc
index c0a0fce..791d67f 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -312,6 +312,7 @@
     # Make sure /sys/kernel/debug (if present) is labeled properly
     # Note that tracefs may be mounted under debug, so we need to cross filesystems
     restorecon --recursive --cross-filesystems /sys/kernel/debug
+    chmod 0755 /sys/kernel/debug/tracing
 
     # We chown/chmod /cache again so because mount is run as root + defaults
     chown system cache /cache
diff --git a/rootdir/init.zygote32.rc b/rootdir/init.zygote32.rc
index eedeba8..d836c4e 100644
--- a/rootdir/init.zygote32.rc
+++ b/rootdir/init.zygote32.rc
@@ -10,4 +10,5 @@
     onrestart restart cameraserver
     onrestart restart media
     onrestart restart netd
+    onrestart restart wificond
     writepid /dev/cpuset/foreground/tasks
diff --git a/rootdir/init.zygote32_64.rc b/rootdir/init.zygote32_64.rc
index 84a907f..ed11164 100644
--- a/rootdir/init.zygote32_64.rc
+++ b/rootdir/init.zygote32_64.rc
@@ -10,6 +10,7 @@
     onrestart restart cameraserver
     onrestart restart media
     onrestart restart netd
+    onrestart restart wificond
     writepid /dev/cpuset/foreground/tasks /dev/stune/foreground/tasks
 
 service zygote_secondary /system/bin/app_process64 -Xzygote /system/bin --zygote --socket-name=zygote_secondary
diff --git a/rootdir/init.zygote64.rc b/rootdir/init.zygote64.rc
index 76e2b79..05ec16f 100644
--- a/rootdir/init.zygote64.rc
+++ b/rootdir/init.zygote64.rc
@@ -10,4 +10,5 @@
     onrestart restart cameraserver
     onrestart restart media
     onrestart restart netd
+    onrestart restart wificond
     writepid /dev/cpuset/foreground/tasks
diff --git a/rootdir/init.zygote64_32.rc b/rootdir/init.zygote64_32.rc
index e918b67..66e7750 100644
--- a/rootdir/init.zygote64_32.rc
+++ b/rootdir/init.zygote64_32.rc
@@ -10,6 +10,7 @@
     onrestart restart cameraserver
     onrestart restart media
     onrestart restart netd
+    onrestart restart wificond
     writepid /dev/cpuset/foreground/tasks /dev/stune/foreground/tasks
 
 service zygote_secondary /system/bin/app_process32 -Xzygote /system/bin --zygote --socket-name=zygote_secondary
diff --git a/rootdir/ueventd.rc b/rootdir/ueventd.rc
index 8725113..0633a68 100644
--- a/rootdir/ueventd.rc
+++ b/rootdir/ueventd.rc
@@ -38,8 +38,6 @@
 # these should not be world writable
 /dev/diag                 0660   radio      radio
 /dev/diag_arm9            0660   radio      radio
-/dev/android_adb          0660   adb        adb
-/dev/android_adb_enable   0660   adb        adb
 /dev/ttyMSM0              0600   bluetooth  bluetooth
 /dev/uhid                 0660   system     bluetooth
 /dev/uinput               0660   system     bluetooth
diff --git a/trusty/gatekeeper/trusty_gatekeeper.cpp b/trusty/gatekeeper/trusty_gatekeeper.cpp
index 7e55fb1..b3fbfa9 100644
--- a/trusty/gatekeeper/trusty_gatekeeper.cpp
+++ b/trusty/gatekeeper/trusty_gatekeeper.cpp
@@ -19,9 +19,10 @@
 #include <assert.h>
 #include <errno.h>
 #include <stdio.h>
+
 #include <type_traits>
 
-#include <android/log.h>
+#include <log/log.h>
 
 #include "trusty_gatekeeper.h"
 #include "trusty_gatekeeper_ipc.h"
diff --git a/trusty/gatekeeper/trusty_gatekeeper_ipc.c b/trusty/gatekeeper/trusty_gatekeeper_ipc.c
index 45e65a7..f67944b 100644
--- a/trusty/gatekeeper/trusty_gatekeeper_ipc.c
+++ b/trusty/gatekeeper/trusty_gatekeeper_ipc.c
@@ -22,7 +22,7 @@
 #include <string.h>
 #include <unistd.h>
 
-#include <android/log.h>
+#include <log/log.h>
 #include <trusty/tipc.h>
 
 #include "trusty_gatekeeper_ipc.h"
diff --git a/trusty/keymaster/trusty_keymaster_device.cpp b/trusty/keymaster/trusty_keymaster_device.cpp
index de5e463..1368f88 100644
--- a/trusty/keymaster/trusty_keymaster_device.cpp
+++ b/trusty/keymaster/trusty_keymaster_device.cpp
@@ -27,9 +27,9 @@
 
 #include <type_traits>
 
-#include <android/log.h>
 #include <hardware/keymaster0.h>
 #include <keymaster/authorization_set.h>
+#include <log/log.h>
 
 #include "trusty_keymaster_device.h"
 #include "trusty_keymaster_ipc.h"
diff --git a/trusty/keymaster/trusty_keymaster_ipc.c b/trusty/keymaster/trusty_keymaster_ipc.c
index 8755093..88546af 100644
--- a/trusty/keymaster/trusty_keymaster_ipc.c
+++ b/trusty/keymaster/trusty_keymaster_ipc.c
@@ -23,7 +23,7 @@
 #include <string.h>
 #include <unistd.h>
 
-#include <android/log.h>
+#include <log/log.h>
 #include <trusty/tipc.h>
 
 #include "trusty_keymaster_ipc.h"
diff --git a/trusty/libtrusty/trusty.c b/trusty/libtrusty/trusty.c
index 2398a53..a6238af 100644
--- a/trusty/libtrusty/trusty.c
+++ b/trusty/libtrusty/trusty.c
@@ -25,7 +25,7 @@
 #include <sys/ioctl.h>
 #include <unistd.h>
 
-#include <android/log.h>
+#include <log/log.h>
 
 #include "tipc_ioctl.h"
 
diff --git a/trusty/nvram/trusty_nvram_implementation.cpp b/trusty/nvram/trusty_nvram_implementation.cpp
index ddaf333..9215c85 100644
--- a/trusty/nvram/trusty_nvram_implementation.cpp
+++ b/trusty/nvram/trusty_nvram_implementation.cpp
@@ -22,8 +22,8 @@
 #include <string.h>
 #include <unistd.h>
 
-#include <android/log.h>
 #include <hardware/nvram.h>
+#include <log/log.h>
 #include <trusty/tipc.h>
 
 #include <nvram/messages/blob.h>
diff --git a/trusty/storage/lib/storage.c b/trusty/storage/lib/storage.c
index 3002c0b..915bc17 100644
--- a/trusty/storage/lib/storage.c
+++ b/trusty/storage/lib/storage.c
@@ -23,7 +23,7 @@
 #include <string.h>
 #include <sys/uio.h>
 
-#include <android/log.h>
+#include <log/log.h>
 #include <trusty/tipc.h>
 #include <trusty/lib/storage.h>
 
diff --git a/trusty/storage/proxy/log.h b/trusty/storage/proxy/log.h
index 3d2e654..c81beab 100644
--- a/trusty/storage/proxy/log.h
+++ b/trusty/storage/proxy/log.h
@@ -16,5 +16,5 @@
 
 #define LOG_TAG "storageproxyd"
 
-#include <android/log.h>
+#include <log/log.h>
 
diff --git a/tzdatacheck/tzdatacheck.cpp b/tzdatacheck/tzdatacheck.cpp
index c1ab2ac..fb5c84b 100644
--- a/tzdatacheck/tzdatacheck.cpp
+++ b/tzdatacheck/tzdatacheck.cpp
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include <ctype.h>
 #include <errno.h>
 #include <ftw.h>
 #include <libgen.h>
@@ -29,47 +30,105 @@
 
 #include "android-base/logging.h"
 
+static const char* BUNDLE_VERSION_FILENAME = "/bundle_version";
+// bundle_version is an ASCII file consisting of 17 bytes in the form: AAA.BBB|CCCCC|DDD
+// AAA.BBB is the major/minor version of the bundle format (e.g. 001.001),
+// CCCCC is the rules version (e.g. 2016g)
+// DDD is the android revision for this rules version to allow for bundle corrections (e.g. 001)
+// We only need the first 13 to determine if it is suitable for the device.
+static const int BUNDLE_VERSION_LENGTH = 13;
+// The major version of the bundle format supported by this code as a null-terminated char[].
+static const char REQUIRED_BUNDLE_VERSION[] = "001";
+static const size_t REQUIRED_BUNDLE_VERSION_LEN = sizeof(REQUIRED_BUNDLE_VERSION) - 1; // exclude \0
+// The length of the IANA rules version bytes. e.g. 2016a
+static const size_t RULES_VERSION_LEN = 5;
+// Bundle version bytes are: AAA.BBB|CCCCC - the rules version is CCCCC
+static const size_t BUNDLE_VERSION_RULES_IDX = 8;
+
 static const char* TZDATA_FILENAME = "/tzdata";
 // tzdata file header (as much as we need for the version):
 // byte[11] tzdata_version  -- e.g. "tzdata2012f"
 static const int TZ_HEADER_LENGTH = 11;
+// The major version of the bundle format supported by this code as a null-terminated char[].
+static const char TZ_DATA_HEADER_PREFIX[] = "tzdata";
+static const size_t TZ_DATA_HEADER_PREFIX_LEN = sizeof(TZ_DATA_HEADER_PREFIX) - 1; // exclude \0
+
 
 static void usage() {
     std::cerr << "Usage: tzdatacheck SYSTEM_TZ_DIR DATA_TZ_DIR\n"
             "\n"
-            "Compares the headers of two tzdata files. If the one in SYSTEM_TZ_DIR is the\n"
-            "same or a higher version than the one in DATA_TZ_DIR the DATA_TZ_DIR is renamed\n"
-            "and then deleted.\n";
+            "Checks whether any timezone update bundle in DATA_TZ_DIR is compatible with the\n"
+            "current Android release and better than or the same as base system timezone rules in\n"
+            "SYSTEM_TZ_DIR. If the timezone rules in SYSTEM_TZ_DIR are a higher version than the\n"
+            "one in DATA_TZ_DIR the DATA_TZ_DIR is renamed and then deleted.\n";
     exit(1);
 }
 
 /*
- * Opens a file and fills headerBytes with the first byteCount bytes from the file. It is a fatal
- * error if the file is too small or cannot be opened. If the file does not exist false is returned.
+ * Opens a file and fills buffer with the first byteCount bytes from the file.
+ * If the file does not exist or cannot be opened or is too short then false is returned.
  * If the bytes were read successfully then true is returned.
  */
-static bool readHeader(const std::string& tzDataFileName, char* headerBytes, size_t byteCount) {
-    FILE* tzDataFile = fopen(tzDataFileName.c_str(), "r");
-    if (tzDataFile == nullptr) {
-        if (errno == ENOENT) {
-            return false;
-        } else {
-            PLOG(FATAL) << "Error opening tzdata file " << tzDataFileName;
+static bool readBytes(const std::string& fileName, char* buffer, size_t byteCount) {
+    FILE* file = fopen(fileName.c_str(), "r");
+    if (file == nullptr) {
+        if (errno != ENOENT) {
+            PLOG(WARNING) << "Error opening file " << fileName;
         }
+        return false;
     }
-    size_t bytesRead = fread(headerBytes, 1, byteCount, tzDataFile);
+    size_t bytesRead = fread(buffer, 1, byteCount, file);
+    fclose(file);
     if (bytesRead != byteCount) {
-        LOG(FATAL) << tzDataFileName << " is too small. " << byteCount << " bytes required";
+        LOG(WARNING) << fileName << " is too small. " << byteCount << " bytes required";
+        return false;
     }
-    fclose(tzDataFile);
     return true;
 }
 
-/* Checks the contents of headerBytes. It is a fatal error if it not a tzdata header. */
-static void checkValidHeader(const std::string& fileName, char* headerBytes) {
+/*
+ * Checks the contents of headerBytes. Returns true if it is valid (starts with "tzdata"), false
+ * otherwise.
+ */
+static bool checkValidTzDataHeader(const std::string& fileName, const char* headerBytes) {
     if (strncmp("tzdata", headerBytes, 6) != 0) {
-        LOG(FATAL) << fileName << " does not start with the expected bytes (tzdata)";
+        LOG(WARNING) << fileName << " does not start with the expected bytes (tzdata)";
+        return false;
     }
+    return true;
+}
+
+static bool checkDigits(const char* buffer, const size_t count, size_t* i) {
+    for (size_t j = 0; j < count; j++) {
+      char toCheck = buffer[(*i)++];
+      if (!isdigit(toCheck)) {
+        return false;
+      }
+    }
+    return true;
+}
+
+static bool checkValidBundleVersion(const char* buffer) {
+    // See BUNDLE_VERSION_LENGTH comments above for a description of the format.
+    size_t i = 0;
+    if (!checkDigits(buffer, 3, &i)) {
+      return false;
+    }
+    if (buffer[i++] != '.') {
+      return false;
+    }
+    if (!checkDigits(buffer, 3, &i)) {
+      return false;
+    }
+    if (buffer[i++] != '|') {
+      return false;
+    }
+    if (!checkDigits(buffer, 4, &i)) {
+      return false;
+    }
+    // Ignore the last character. It is assumed to be a letter but we don't check because it's not
+    // obvious what would happen at 'z'.
+    return true;
 }
 
 /* Return the parent directory of dirName. */
@@ -103,9 +162,24 @@
     return 0;
 }
 
+enum PathStatus { ERR, NONE, IS_DIR, NOT_DIR };
+
+static PathStatus checkPath(const std::string& path) {
+    struct stat buf;
+    if (stat(path.c_str(), &buf) != 0) {
+        if (errno != ENOENT) {
+            PLOG(WARNING) << "Unable to stat " << path;
+            return ERR;
+        }
+        return NONE;
+    }
+    return S_ISDIR(buf.st_mode) ? IS_DIR : NOT_DIR;
+}
+
 /*
  * Deletes dirToDelete and returns true if it is successful in removing or moving the directory out
- * of the way. If dirToDelete does not exist this function does nothing and returns true.
+ * of the way. If dirToDelete does not exist this function does nothing and returns true. If
+ * dirToDelete is not a directory or cannot be accessed this method returns false.
  *
  * During deletion, this function first renames the directory to a temporary name. If the temporary
  * directory cannot be created, or the directory cannot be renamed, false is returned. After the
@@ -114,23 +188,18 @@
  */
 static bool deleteDir(const std::string& dirToDelete) {
     // Check whether the dir exists.
-    struct stat buf;
-    if (stat(dirToDelete.c_str(), &buf) == 0) {
-      if (!S_ISDIR(buf.st_mode)) {
-        LOG(WARNING) << dirToDelete << " is not a directory";
+    int pathStatus = checkPath(dirToDelete);
+    if (pathStatus == NONE) {
+        LOG(INFO) << "Path " << dirToDelete << " does not exist";
+        return true;
+    }
+    if (pathStatus != IS_DIR) {
+        LOG(WARNING) << "Path " << dirToDelete << " failed to stat() or is not a directory.";
         return false;
-      }
-    } else {
-      if (errno == ENOENT) {
-          PLOG(INFO) << "Directory does not exist: " << dirToDelete;
-          return true;
-      } else {
-          PLOG(WARNING) << "Unable to stat " << dirToDelete;
-          return false;
-      }
     }
 
     // First, rename dirToDelete.
+
     std::string tempDirNameTemplate = getParentDir(dirToDelete);
     tempDirNameTemplate += "/tempXXXXXX";
 
@@ -142,7 +211,7 @@
         return false;
     }
 
-    // Rename dirToDelete to tempDirName.
+    // Rename dirToDelete to tempDirName (replacing the empty tempDirName directory created above).
     int rc = rename(dirToDelete.c_str(), &tempDirName[0]);
     if (rc == -1) {
         PLOG(WARNING) << "Unable to rename directory from " << dirToDelete << " to "
@@ -151,6 +220,7 @@
     }
 
     // Recursively delete contents of tempDirName.
+
     rc = nftw(&tempDirName[0], deleteFn, 10 /* openFiles */,
             FTW_DEPTH | FTW_MOUNT | FTW_PHYS);
     if (rc == -1) {
@@ -160,9 +230,36 @@
 }
 
 /*
+ * Deletes the ConfigInstaller metadata directory.
+ * TODO(nfuller). http://b/31008728 Remove this when ConfigInstaller is no longer used.
+ */
+static void deleteConfigUpdaterMetadataDir(const char* dataZoneInfoDir) {
+    // Delete the update metadata
+    std::string dataUpdatesDirName(dataZoneInfoDir);
+    dataUpdatesDirName += "/updates";
+    LOG(INFO) << "Removing: " << dataUpdatesDirName;
+    bool deleted = deleteDir(dataUpdatesDirName);
+    if (!deleted) {
+        LOG(WARNING) << "Deletion of install metadata " << dataUpdatesDirName
+                << " was not successful";
+    }
+}
+
+/*
+ * Deletes the timezone update bundle directory.
+ */
+static void deleteUpdateBundleDir(std::string& bundleDirName) {
+    LOG(INFO) << "Removing: " << bundleDirName;
+    bool deleted = deleteDir(bundleDirName);
+    if (!deleted) {
+        LOG(WARNING) << "Deletion of bundle dir " << bundleDirName << " was not successful";
+    }
+}
+
+/*
  * After a platform update it is likely that timezone data found on the system partition will be
  * newer than the version found in the data partition. This tool detects this case and removes the
- * version in /data along with any update metadata.
+ * version in /data.
  *
  * Note: This code is related to code in com.android.server.updates.TzDataInstallReceiver. The
  * paths for the metadata and current timezone data must match.
@@ -175,62 +272,103 @@
 int main(int argc, char* argv[]) {
     if (argc != 3) {
         usage();
+        return 1;
     }
 
     const char* systemZoneInfoDir = argv[1];
     const char* dataZoneInfoDir = argv[2];
 
+    // Check the bundle directory exists. If it does not, exit quickly: nothing to do.
     std::string dataCurrentDirName(dataZoneInfoDir);
     dataCurrentDirName += "/current";
-    std::string dataTzDataFileName(dataCurrentDirName);
-    dataTzDataFileName += TZDATA_FILENAME;
-
-    std::vector<char> dataTzDataHeader;
-    dataTzDataHeader.reserve(TZ_HEADER_LENGTH);
-
-    bool dataFileExists = readHeader(dataTzDataFileName, dataTzDataHeader.data(), TZ_HEADER_LENGTH);
-    if (!dataFileExists) {
-        LOG(INFO) << "tzdata file " << dataTzDataFileName << " does not exist. No action required.";
+    int dataCurrentDirStatus = checkPath(dataCurrentDirName);
+    if (dataCurrentDirStatus == NONE) {
+        LOG(INFO) << "timezone bundle dir " << dataCurrentDirName
+                << " does not exist. No action required.";
         return 0;
     }
-    checkValidHeader(dataTzDataFileName, dataTzDataHeader.data());
+    // If the bundle directory path is not a directory or we can't stat() the path, exit with a
+    // warning: either there's a problem accessing storage or the world is not as it should be;
+    // nothing to do.
+    if (dataCurrentDirStatus != IS_DIR) {
+        LOG(WARNING) << "Current bundle dir " << dataCurrentDirName
+                << " could not be accessed or is not a directory. result=" << dataCurrentDirStatus;
+        return 2;
+    }
 
+    // Check the installed bundle version.
+    std::string bundleVersionFileName(dataCurrentDirName);
+    bundleVersionFileName += BUNDLE_VERSION_FILENAME;
+    std::vector<char> bundleVersion;
+    bundleVersion.reserve(BUNDLE_VERSION_LENGTH);
+    bool bundleVersionReadOk =
+            readBytes(bundleVersionFileName, bundleVersion.data(), BUNDLE_VERSION_LENGTH);
+    if (!bundleVersionReadOk) {
+        LOG(WARNING) << "bundle version file " << bundleVersionFileName
+                << " does not exist or is too short. Deleting bundle dir.";
+        // Implies the contents of the data partition is corrupt in some way. Try to clean up.
+        deleteConfigUpdaterMetadataDir(dataZoneInfoDir);
+        deleteUpdateBundleDir(dataCurrentDirName);
+        return 3;
+    }
+
+    if (!checkValidBundleVersion(bundleVersion.data())) {
+        LOG(WARNING) << "bundle version file " << bundleVersionFileName
+                << " is not valid. Deleting bundle dir.";
+        // Implies the contents of the data partition is corrupt in some way. Try to clean up.
+        deleteConfigUpdaterMetadataDir(dataZoneInfoDir);
+        deleteUpdateBundleDir(dataCurrentDirName);
+        return 4;
+    }
+
+    // Check the first 3 bytes of the bundleVersionHeader: these are the major version (e.g. 001).
+    // It must match exactly to be ok. The minor version is currently ignored.
+    if (strncmp(&bundleVersion[0], REQUIRED_BUNDLE_VERSION, REQUIRED_BUNDLE_VERSION_LEN) != 0) {
+        LOG(INFO) << "bundle version file " << bundleVersionFileName
+                << " is not the required version " << REQUIRED_BUNDLE_VERSION
+                << ". Deleting bundle dir.";
+        // This shouldn't happen with 001, but it in future, this will imply there has been an OTA
+        // and the installed bundle is not compatible with the new version of Android. Remove the
+        // installed bundle.
+        deleteConfigUpdaterMetadataDir(dataZoneInfoDir);
+        deleteUpdateBundleDir(dataCurrentDirName);
+        return 5;
+    }
+
+    // Read the system rules version out of the /system tzdata file.
     std::string systemTzDataFileName(systemZoneInfoDir);
     systemTzDataFileName += TZDATA_FILENAME;
     std::vector<char> systemTzDataHeader;
     systemTzDataHeader.reserve(TZ_HEADER_LENGTH);
     bool systemFileExists =
-            readHeader(systemTzDataFileName, systemTzDataHeader.data(), TZ_HEADER_LENGTH);
+            readBytes(systemTzDataFileName, systemTzDataHeader.data(), TZ_HEADER_LENGTH);
     if (!systemFileExists) {
-        LOG(FATAL) << systemTzDataFileName << " does not exist or could not be opened";
+        // Implies the contents of the system partition is corrupt in some way. Nothing we can do.
+        LOG(WARNING) << systemTzDataFileName << " does not exist or could not be opened";
+        return 6;
     }
-    checkValidHeader(systemTzDataFileName, systemTzDataHeader.data());
-
-    if (strncmp(&systemTzDataHeader[0], &dataTzDataHeader[0], TZ_HEADER_LENGTH) < 0) {
-        LOG(INFO) << "tzdata file " << dataTzDataFileName << " is the newer than "
-                << systemTzDataFileName << ". No action required.";
-    } else {
-        // We have detected the case this tool is intended to prevent. Go fix it.
-        LOG(INFO) << "tzdata file " << dataTzDataFileName << " is the same as or older than "
-                << systemTzDataFileName << "; fixing...";
-
-        // Delete the update metadata
-        std::string dataUpdatesDirName(dataZoneInfoDir);
-        dataUpdatesDirName += "/updates";
-        LOG(INFO) << "Removing: " << dataUpdatesDirName;
-        bool deleted = deleteDir(dataUpdatesDirName);
-        if (!deleted) {
-            LOG(WARNING) << "Deletion of install metadata " << dataUpdatesDirName
-                    << " was not successful";
-        }
-
-        // Delete the TZ data
-        LOG(INFO) << "Removing: " << dataCurrentDirName;
-        deleted = deleteDir(dataCurrentDirName);
-        if (!deleted) {
-            LOG(WARNING) << "Deletion of tzdata " << dataCurrentDirName << " was not successful";
-        }
+    if (!checkValidTzDataHeader(systemTzDataFileName, systemTzDataHeader.data())) {
+        // Implies the contents of the system partition is corrupt in some way. Nothing we can do.
+        LOG(WARNING) << systemTzDataFileName << " does not have a valid header.";
+        return 7;
     }
 
+    // Compare the bundle rules version against the system rules version.
+    if (strncmp(
+            &systemTzDataHeader[TZ_DATA_HEADER_PREFIX_LEN],
+            &bundleVersion[BUNDLE_VERSION_RULES_IDX],
+            RULES_VERSION_LEN) <= 0) {
+        LOG(INFO) << "Found an installed bundle but it is valid. No action taken.";
+        // Implies there is an installed update, but it is good.
+        return 0;
+    }
+
+    // Implies there has been an OTA and the system version of the timezone rules is now newer
+    // than the version installed in /data. Remove the installed bundle.
+    LOG(INFO) << "timezone bundle in " << dataCurrentDirName << " is older than data in "
+            << systemTzDataFileName << "; fixing...";
+
+    deleteConfigUpdaterMetadataDir(dataZoneInfoDir);
+    deleteUpdateBundleDir(dataCurrentDirName);
     return 0;
 }