Merge "Revert "Create command to run adb tests and output results""
diff --git a/.clang-format b/.clang-format
new file mode 100644
index 0000000..fc4eb1b
--- /dev/null
+++ b/.clang-format
@@ -0,0 +1,13 @@
+BasedOnStyle: Google
+AllowShortBlocksOnASingleLine: false
+AllowShortFunctionsOnASingleLine: false
+
+AccessModifierOffset: -2
+ColumnLimit: 100
+CommentPragmas: NOLINT:.*
+DerivePointerAlignment: false
+IndentWidth: 4
+PointerAlignment: Left
+TabWidth: 4
+UseTab: Never
+PenaltyExcessCharacter: 32
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
new file mode 100644
index 0000000..c8dbf77
--- /dev/null
+++ b/PREUPLOAD.cfg
@@ -0,0 +1,5 @@
+[Builtin Hooks]
+clang_format = true
+
+[Builtin Hooks Options]
+clang_format = --commit ${PREUPLOAD_COMMIT} --style file --extensions c,h,cc,cpp
diff --git a/adb/NOTICE b/adb/NOTICE
index 9ffcc08..ff47c95 100644
--- a/adb/NOTICE
+++ b/adb/NOTICE
@@ -189,3 +189,63 @@
 
    END OF TERMS AND CONDITIONS
 
+------------------------------------------------------------
+libwinpthread license:
+------------------------------------------------------------
+Copyright (c) 2011 mingw-w64 project
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+
+/*
+ * Parts of this library are derived by:
+ *
+ * Posix Threads library for Microsoft Windows
+ *
+ * Use at own risk, there is no implied warranty to this code.
+ * It uses undocumented features of Microsoft Windows that can change
+ * at any time in the future.
+ *
+ * (C) 2010 Lockless Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ *
+ *  * Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *  * Neither the name of Lockless Inc. nor the names of its contributors may be
+ *    used to endorse or promote products derived from this software without
+ *    specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AN
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
diff --git a/adb/daemon/usb.cpp b/adb/daemon/usb.cpp
index c08b922..92e9039 100644
--- a/adb/daemon/usb.cpp
+++ b/adb/daemon/usb.cpp
@@ -283,6 +283,8 @@
             D("[ %s: writing strings failed: errno=%d]", USB_FFS_ADB_EP0, errno);
             goto err;
         }
+        //Signal only when writing the descriptors to ffs
+        android::base::SetProperty("sys.usb.ffs.ready", "1");
     }
 
     h->bulk_out = adb_open(USB_FFS_ADB_OUT, O_RDWR);
@@ -358,7 +360,6 @@
             }
             std::this_thread::sleep_for(1s);
         }
-        android::base::SetProperty("sys.usb.ffs.ready", "1");
 
         D("[ usb_thread - registering device ]");
         register_usb_transport(usb, 0, 0, 1);
diff --git a/adb/transport_usb.cpp b/adb/transport_usb.cpp
index e16cf12..516b4f2 100644
--- a/adb/transport_usb.cpp
+++ b/adb/transport_usb.cpp
@@ -102,7 +102,7 @@
 #if defined(_WIN32) || !ADB_HOST
     return false;
 #else
-    static bool enable = getenv("ADB_LIBUSB") && strcmp(getenv("ADB_LIBUSB"), "1") == 0;
-    return enable;
+    static bool disable = getenv("ADB_LIBUSB") && strcmp(getenv("ADB_LIBUSB"), "0") == 0;
+    return !disable;
 #endif
 }
diff --git a/debuggerd/crasher/Android.bp b/debuggerd/crasher/Android.bp
index 4727894..f73f672 100644
--- a/debuggerd/crasher/Android.bp
+++ b/debuggerd/crasher/Android.bp
@@ -48,6 +48,7 @@
     shared_libs: [
         "libbase",
         "liblog",
+        "libseccomp_policy",
     ],
     multilib: {
         lib32: {
@@ -69,6 +70,7 @@
         "libdebuggerd_handler",
         "libbase",
         "liblog",
+        "libseccomp_policy",
     ],
     multilib: {
         lib32: {
diff --git a/debuggerd/crasher/crasher.cpp b/debuggerd/crasher/crasher.cpp
index 1c01e3e..6970201 100644
--- a/debuggerd/crasher/crasher.cpp
+++ b/debuggerd/crasher/crasher.cpp
@@ -33,6 +33,8 @@
 #include <android-base/logging.h>
 #include <log/log.h>
 
+#include "seccomp_policy.h"
+
 #if defined(STATIC_CRASHER)
 #include "debuggerd/handler.h"
 #endif
@@ -269,6 +271,7 @@
         munmap(map, sizeof(int));
         map[0] = '8';
     } else if (!strcasecmp(arg, "seccomp")) {
+        set_seccomp_filter();
         syscall(99999);
 #if defined(__arm__)
     } else if (!strcasecmp(arg, "kuser_helper_version")) {
diff --git a/debuggerd/debuggerd.cpp b/debuggerd/debuggerd.cpp
index 0c5d3cf..492e9f0 100644
--- a/debuggerd/debuggerd.cpp
+++ b/debuggerd/debuggerd.cpp
@@ -34,6 +34,8 @@
 
 static void usage(int exit_code) {
   fprintf(stderr, "usage: debuggerd [-b] PID\n");
+  fprintf(stderr, "\n");
+  fprintf(stderr, "-b, --backtrace    just a backtrace rather than a full tombstone\n");
   _exit(exit_code);
 }
 
@@ -56,7 +58,8 @@
 int main(int argc, char* argv[]) {
   if (argc <= 1) usage(0);
   if (argc > 3) usage(1);
-  if (argc == 3 && strcmp(argv[1], "-b") != 0) usage(1);
+  if (argc == 3 && strcmp(argv[1], "-b") != 0 && strcmp(argv[1], "--backtrace") != 0) usage(1);
+  bool backtrace_only = argc == 3;
 
   pid_t pid;
   if (!android::base::ParseInt(argv[argc - 1], &pid, 1, std::numeric_limits<pid_t>::max())) {
@@ -69,9 +72,8 @@
   }
 
   std::thread redirect_thread = spawn_redirect_thread(std::move(piperead));
-  bool backtrace = argc == 3;
   if (!debuggerd_trigger_dump(pid, std::move(pipewrite),
-                              backtrace ? kDebuggerdBacktrace : kDebuggerdTombstone, 0)) {
+                              backtrace_only ? kDebuggerdBacktrace : kDebuggerdTombstone, 0)) {
     redirect_thread.join();
     errx(1, "failed to dump process %d", pid);
   }
diff --git a/debuggerd/libdebuggerd/tombstone.cpp b/debuggerd/libdebuggerd/tombstone.cpp
index 3166bfc..4686bfd 100644
--- a/debuggerd/libdebuggerd/tombstone.cpp
+++ b/debuggerd/libdebuggerd/tombstone.cpp
@@ -214,7 +214,8 @@
       cause = "call to kuser_cmpxchg64";
     }
   } else if (si.si_signo == SIGSYS && si.si_code == SYS_SECCOMP) {
-    cause = StringPrintf("seccomp prevented call to disallowed system call %d", si.si_syscall);
+    cause = StringPrintf("seccomp prevented call to disallowed %s system call %d",
+                         ABI_STRING, si.si_syscall);
   }
 
   if (!cause.empty()) _LOG(log, logtype::HEADER, "Cause: %s\n", cause.c_str());
diff --git a/debuggerd/libdebuggerd/utility.cpp b/debuggerd/libdebuggerd/utility.cpp
index 57209aa..744cd72 100644
--- a/debuggerd/libdebuggerd/utility.cpp
+++ b/debuggerd/libdebuggerd/utility.cpp
@@ -41,6 +41,7 @@
   return false;
 }
 
+__attribute__((__weak__, visibility("default")))
 void _LOG(log_t* log, enum logtype ltype, const char* fmt, ...) {
   bool write_to_tombstone = (log->tfd != -1);
   bool write_to_logcat = is_allowed_in_logcat(ltype)
diff --git a/debuggerd/tombstoned/tombstoned.cpp b/debuggerd/tombstoned/tombstoned.cpp
index 8705ece..6754508 100644
--- a/debuggerd/tombstoned/tombstoned.cpp
+++ b/debuggerd/tombstoned/tombstoned.cpp
@@ -34,6 +34,7 @@
 #include <android-base/unique_fd.h>
 #include <cutils/sockets.h>
 
+#include "debuggerd/handler.h"
 #include "debuggerd/protocol.h"
 #include "debuggerd/util.h"
 
@@ -116,7 +117,7 @@
   }
 
   result.reset(
-    openat(tombstone_directory_fd, buf, O_CREAT | O_EXCL | O_WRONLY | O_APPEND | O_CLOEXEC, 0700));
+    openat(tombstone_directory_fd, buf, O_CREAT | O_EXCL | O_WRONLY | O_APPEND | O_CLOEXEC, 0640));
   if (result == -1) {
     PLOG(FATAL) << "failed to create tombstone at " << kTombstoneDirectory << buf;
   }
@@ -254,6 +255,16 @@
 }
 
 int main(int, char* []) {
+  umask(0137);
+
+  // Don't try to connect to ourselves if we crash.
+  struct sigaction action = {};
+  action.sa_handler = [](int signal) {
+    LOG(ERROR) << "received fatal signal " << signal;
+    _exit(1);
+  };
+  debuggerd_register_handlers(&action);
+
   tombstone_directory_fd = open(kTombstoneDirectory, O_DIRECTORY | O_RDONLY | O_CLOEXEC);
   if (tombstone_directory_fd == -1) {
     PLOG(FATAL) << "failed to open tombstone directory";
diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp
index a50817e..d0e4682 100644
--- a/fs_mgr/fs_mgr.cpp
+++ b/fs_mgr/fs_mgr.cpp
@@ -31,6 +31,8 @@
 #include <time.h>
 #include <unistd.h>
 
+#include <android-base/file.h>
+#include <android-base/stringprintf.h>
 #include <android-base/unique_fd.h>
 #include <cutils/android_reboot.h>
 #include <cutils/partition_utils.h>
@@ -64,6 +66,21 @@
 
 #define ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a)))
 
+// record fs stat
+enum FsStatFlags {
+    FS_STAT_IS_EXT4           = 0x0001,
+    FS_STAT_NEW_IMAGE_VERSION = 0x0002,
+    FS_STAT_E2FSCK_F_ALWAYS   = 0x0004,
+    FS_STAT_UNCLEAN_SHUTDOWN  = 0x0008,
+    FS_STAT_QUOTA_ENABLED     = 0x0010,
+    FS_STAT_TUNE2FS_FAILED    = 0x0020,
+    FS_STAT_RO_MOUNT_FAILED   = 0x0040,
+    FS_STAT_RO_UNMOUNT_FAILED = 0x0080,
+    FS_STAT_FULL_MOUNT_FAILED = 0x0100,
+    FS_STAT_E2FSCK_FAILED     = 0x0200,
+    FS_STAT_E2FSCK_FS_FIXED   = 0x0400,
+};
+
 /*
  * gettime() - returns the time in seconds of the system's monotonic clock or
  * zero on error.
@@ -94,7 +111,18 @@
     return ret;
 }
 
-static void check_fs(const char *blk_device, char *fs_type, char *target)
+static void log_fs_stat(const char* blk_device, int fs_stat)
+{
+    if ((fs_stat & FS_STAT_IS_EXT4) == 0) return; // only log ext4
+    std::string msg = android::base::StringPrintf("\nfs_stat,%s,0x%x\n", blk_device, fs_stat);
+    android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(FSCK_LOG_FILE, O_WRONLY | O_CLOEXEC |
+                                                        O_APPEND | O_CREAT, 0664)));
+    if (fd == -1 || !android::base::WriteStringToFd(msg, fd)) {
+        LWARNING << __FUNCTION__ << "() cannot log " << msg;
+    }
+}
+
+static void check_fs(const char *blk_device, char *fs_type, char *target, int *fs_stat)
 {
     int status;
     int ret;
@@ -141,10 +169,13 @@
                           << ") succeeded";
                     break;
                 }
+                *fs_stat |= FS_STAT_RO_UNMOUNT_FAILED;
                 PERROR << __FUNCTION__ << "(): umount(" << target << ")="
                        << result;
                 sleep(1);
             }
+        } else {
+            *fs_stat |= FS_STAT_RO_MOUNT_FAILED;
         }
 
         /*
@@ -157,6 +188,7 @@
         } else {
             LINFO << "Running " << E2FSCK_BIN << " on " << blk_device;
 
+            *fs_stat |= FS_STAT_E2FSCK_F_ALWAYS;
             ret = android_fork_execvp_ext(ARRAY_SIZE(e2fsck_argv),
                                           const_cast<char **>(e2fsck_argv),
                                           &status, true, LOG_KLOG | LOG_FILE,
@@ -167,6 +199,10 @@
             if (ret < 0) {
                 /* No need to check for error in fork, we can't really handle it now */
                 LERROR << "Failed trying to run " << E2FSCK_BIN;
+                *fs_stat |= FS_STAT_E2FSCK_FAILED;
+            } else if (status != 0) {
+                LINFO << "e2fsck returned status 0x" << std::hex << status;
+                *fs_stat |= FS_STAT_E2FSCK_FS_FIXED;
             }
         }
     } else if (!strcmp(fs_type, "f2fs")) {
@@ -221,7 +257,8 @@
             le32_to_cpu(es->s_r_blocks_count_lo);
 }
 
-static int do_quota(char *blk_device, char *fs_type, struct fstab_rec *rec)
+static int do_quota_with_shutdown_check(char *blk_device, char *fs_type,
+                                        struct fstab_rec *rec, int *fs_stat)
 {
     int force_check = 0;
     if (!strcmp(fs_type, "ext4")) {
@@ -246,7 +283,16 @@
                     PERROR << "Can't read '" << blk_device << "' super block";
                     return force_check;
                 }
-
+                *fs_stat |= FS_STAT_IS_EXT4;
+                //TODO check if it is new version or not
+                if ((sb.s_feature_incompat & EXT4_FEATURE_INCOMPAT_RECOVER) != 0 ||
+                    (sb.s_state & EXT4_VALID_FS) == 0) {
+                    LINFO << __FUNCTION__ << "(): was not clealy shutdown, state flag:"
+                          << std::hex << sb.s_state
+                          << "incompat flag:" << std::hex << sb.s_feature_incompat;
+                    force_check = 1;
+                    *fs_stat |= FS_STAT_UNCLEAN_SHUTDOWN;
+                }
                 int has_quota = (sb.s_feature_ro_compat
                         & cpu_to_le32(EXT4_FEATURE_RO_COMPAT_QUOTA)) != 0;
                 int want_quota = fs_mgr_is_quota(rec) != 0;
@@ -259,6 +305,7 @@
                     arg1 = "-Oquota";
                     arg2 = "-Qusrquota,grpquota";
                     force_check = 1;
+                    *fs_stat |= FS_STAT_QUOTA_ENABLED;
                 } else {
                     LINFO << "Disabling quota on " << blk_device;
                     arg1 = "-Q^usrquota,^grpquota";
@@ -282,13 +329,14 @@
             if (ret < 0) {
                 /* No need to check for error in fork, we can't really handle it now */
                 LERROR << "Failed trying to run " << TUNE2FS_BIN;
+                *fs_stat |= FS_STAT_TUNE2FS_FAILED;
             }
         }
     }
     return force_check;
 }
 
-static void do_reserved_size(char *blk_device, char *fs_type, struct fstab_rec *rec)
+static void do_reserved_size(char *blk_device, char *fs_type, struct fstab_rec *rec, int *fs_stat)
 {
     /* Check for the types of filesystems we know how to check */
     if (!strcmp(fs_type, "ext2") || !strcmp(fs_type, "ext3") || !strcmp(fs_type, "ext4")) {
@@ -347,6 +395,7 @@
             if (ret < 0) {
                 /* No need to check for error in fork, we can't really handle it now */
                 LERROR << "Failed trying to run " << TUNE2FS_BIN;
+                *fs_stat |= FS_STAT_TUNE2FS_FAILED;
             }
         }
     }
@@ -487,17 +536,19 @@
                 continue;
             }
 
-            int force_check = do_quota(fstab->recs[i].blk_device, fstab->recs[i].fs_type,
-                                       &fstab->recs[i]);
+            int fs_stat = 0;
+            int force_check = do_quota_with_shutdown_check(fstab->recs[i].blk_device,
+                                                           fstab->recs[i].fs_type,
+                                                           &fstab->recs[i], &fs_stat);
 
             if ((fstab->recs[i].fs_mgr_flags & MF_CHECK) || force_check) {
                 check_fs(fstab->recs[i].blk_device, fstab->recs[i].fs_type,
-                         fstab->recs[i].mount_point);
+                         fstab->recs[i].mount_point, &fs_stat);
             }
 
             if (fstab->recs[i].fs_mgr_flags & MF_RESERVEDSIZE) {
                 do_reserved_size(fstab->recs[i].blk_device, fstab->recs[i].fs_type,
-                                 &fstab->recs[i]);
+                                 &fstab->recs[i], &fs_stat);
             }
 
             if (!__mount(fstab->recs[i].blk_device, fstab->recs[i].mount_point, &fstab->recs[i])) {
@@ -511,9 +562,11 @@
                            << fstab->recs[start_idx].fs_type;
                 }
             } else {
+                fs_stat |= FS_STAT_FULL_MOUNT_FAILED;
                 /* back up errno for crypto decisions */
                 mount_errno = errno;
             }
+            log_fs_stat(fstab->recs[i].blk_device, fs_stat);
     }
 
     /* Adjust i for the case where it was still withing the recs[] */
@@ -950,16 +1003,18 @@
             wait_for_file(n_blk_device, WAIT_TIMEOUT);
         }
 
-        int force_check = do_quota(fstab->recs[i].blk_device, fstab->recs[i].fs_type,
-                                   &fstab->recs[i]);
+        int fs_stat = 0;
+        int force_check = do_quota_with_shutdown_check(fstab->recs[i].blk_device,
+                                                       fstab->recs[i].fs_type,
+                                                       &fstab->recs[i], &fs_stat);
 
         if ((fstab->recs[i].fs_mgr_flags & MF_CHECK) || force_check) {
             check_fs(n_blk_device, fstab->recs[i].fs_type,
-                     fstab->recs[i].mount_point);
+                     fstab->recs[i].mount_point, &fs_stat);
         }
 
         if (fstab->recs[i].fs_mgr_flags & MF_RESERVEDSIZE) {
-            do_reserved_size(n_blk_device, fstab->recs[i].fs_type, &fstab->recs[i]);
+            do_reserved_size(n_blk_device, fstab->recs[i].fs_type, &fstab->recs[i], &fs_stat);
         }
 
         if (fs_mgr_is_avb_used() && (fstab->recs[i].fs_mgr_flags & MF_AVB)) {
@@ -996,9 +1051,12 @@
         if (__mount(n_blk_device, m, &fstab->recs[i])) {
             if (!first_mount_errno) first_mount_errno = errno;
             mount_errors++;
+            fs_stat |= FS_STAT_FULL_MOUNT_FAILED;
+            log_fs_stat(fstab->recs[i].blk_device, fs_stat);
             continue;
         } else {
             ret = 0;
+            log_fs_stat(fstab->recs[i].blk_device, fs_stat);
             goto out;
         }
     }
diff --git a/fs_mgr/fs_mgr_verity.cpp b/fs_mgr/fs_mgr_verity.cpp
index e8ed6a2..54a6f71 100644
--- a/fs_mgr/fs_mgr_verity.cpp
+++ b/fs_mgr/fs_mgr_verity.cpp
@@ -30,6 +30,7 @@
 #include <unistd.h>
 
 #include <android-base/file.h>
+#include <android-base/properties.h>
 #include <android-base/strings.h>
 #include <android-base/unique_fd.h>
 #include <crypto_utils/android_pubkey.h>
@@ -874,6 +875,11 @@
     // read verity metadata
     if (fec_verity_get_metadata(f, &verity) < 0) {
         PERROR << "Failed to get verity metadata '" << fstab->blk_device << "'";
+        // Allow verity disabled when the device is unlocked without metadata
+        if ("0" == android::base::GetProperty("ro.boot.flash.locked", "")) {
+            retval = FS_MGR_SETUP_VERITY_DISABLED;
+            LWARNING << "Allow invalid metadata when the device is unlocked";
+        }
         goto out;
     }
 
diff --git a/healthd/BatteryMonitor.cpp b/healthd/BatteryMonitor.cpp
index 4007203..4df0af1 100644
--- a/healthd/BatteryMonitor.cpp
+++ b/healthd/BatteryMonitor.cpp
@@ -141,7 +141,6 @@
     struct sysfsStringEnumMap supplyTypeMap[] = {
             { "Unknown", ANDROID_POWER_SUPPLY_TYPE_UNKNOWN },
             { "Battery", ANDROID_POWER_SUPPLY_TYPE_BATTERY },
-            { "BMS", ANDROID_POWER_SUPPLY_TYPE_BATTERY },
             { "UPS", ANDROID_POWER_SUPPLY_TYPE_AC },
             { "Mains", ANDROID_POWER_SUPPLY_TYPE_AC },
             { "USB", ANDROID_POWER_SUPPLY_TYPE_USB },
diff --git a/include/system/window.h b/include/system/window.h
index c340773..31a239b 100644
--- a/include/system/window.h
+++ b/include/system/window.h
@@ -317,6 +317,12 @@
      * retire info, 0 if it won't.
      */
     NATIVE_WINDOW_FRAME_TIMESTAMPS_SUPPORTS_RETIRE = 18,
+
+    /*
+     * Returns 1 if the native window is valid, 0 otherwise. native window is valid
+     * if it is safe (i.e. no crash will occur) to call any method on it.
+     */
+    NATIVE_WINDOW_IS_VALID = 19,
 };
 
 /* Valid operations for the (*perform)() hook.
@@ -330,6 +336,7 @@
  * ANativeWindow.
  */
 enum {
+// clang-format off
     NATIVE_WINDOW_SET_USAGE                 =  0,
     NATIVE_WINDOW_CONNECT                   =  1,   /* deprecated */
     NATIVE_WINDOW_DISCONNECT                =  2,   /* deprecated */
@@ -358,6 +365,9 @@
     NATIVE_WINDOW_ENABLE_FRAME_TIMESTAMPS   = 25,
     NATIVE_WINDOW_GET_COMPOSITOR_TIMING     = 26,
     NATIVE_WINDOW_GET_FRAME_TIMESTAMPS      = 27,
+    NATIVE_WINDOW_GET_WIDE_COLOR_SUPPORT    = 28,
+    NATIVE_WINDOW_GET_HDR_SUPPORT           = 29,
+// clang-format on
 };
 
 /* parameter for NATIVE_WINDOW_[API_][DIS]CONNECT */
@@ -1065,6 +1075,16 @@
             outDisplayRetireTime, outDequeueReadyTime, outReleaseTime);
 }
 
+static inline int native_window_get_wide_color_support(
+    struct ANativeWindow* window, bool* outSupport) {
+  return window->perform(window, NATIVE_WINDOW_GET_WIDE_COLOR_SUPPORT,
+                         outSupport);
+}
+
+static inline int native_window_get_hdr_support(struct ANativeWindow* window,
+                                                bool* outSupport) {
+  return window->perform(window, NATIVE_WINDOW_GET_HDR_SUPPORT, outSupport);
+}
 
 __END_DECLS
 
diff --git a/init/Android.mk b/init/Android.mk
index 2fc6f19..5bcfb7b 100644
--- a/init/Android.mk
+++ b/init/Android.mk
@@ -119,7 +119,14 @@
     mapping_sepolicy.cil \
     nonplat_sepolicy.cil \
     plat_sepolicy.cil \
+    plat_sepolicy.cil.sha256 \
     secilc
+
+# Include precompiled policy, unless told otherwise
+ifneq ($(PRODUCT_PRECOMPILED_SEPOLICY),false)
+LOCAL_REQUIRED_MODULES += precompiled_sepolicy precompiled_sepolicy.plat.sha256
+endif
+
 else
 # Use monolithic SELinux policy
 LOCAL_REQUIRED_MODULES += sepolicy
diff --git a/init/builtins.cpp b/init/builtins.cpp
index 270afcf..507c4a0 100644
--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -604,20 +604,27 @@
     int mount_mode = MOUNT_MODE_DEFAULT;
     const char* fstabfile = args[1].c_str();
     std::size_t path_arg_end = args.size();
+    const char* prop_post_fix = "default";
 
     for (na = args.size() - 1; na > 1; --na) {
         if (args[na] == "--early") {
             path_arg_end = na;
             queue_event = false;
             mount_mode = MOUNT_MODE_EARLY;
+            prop_post_fix = "early";
         } else if (args[na] == "--late") {
             path_arg_end = na;
             import_rc = false;
             mount_mode = MOUNT_MODE_LATE;
+            prop_post_fix = "late";
         }
     }
 
+    std::string prop_name = android::base::StringPrintf("ro.boottime.init.mount_all.%s",
+                                                        prop_post_fix);
+    Timer t;
     int ret =  mount_fstab(fstabfile, mount_mode);
+    property_set(prop_name.c_str(), std::to_string(t.duration_ms()).c_str());
 
     if (import_rc) {
         /* Paths of .rc files are specified at the 2nd argument and beyond */
diff --git a/init/init.cpp b/init/init.cpp
index 53e7482..38178a7 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -621,11 +621,21 @@
 
 /*
  * Forks, executes the provided program in the child, and waits for the completion in the parent.
+ * Child's stderr is captured and logged using LOG(ERROR).
  *
  * Returns true if the child exited with status code 0, returns false otherwise.
  */
 static bool fork_execve_and_wait_for_completion(const char* filename, char* const argv[],
                                                 char* const envp[]) {
+    // Create a pipe used for redirecting child process's output.
+    // * pipe_fds[0] is the FD the parent will use for reading.
+    // * pipe_fds[1] is the FD the child will use for writing.
+    int pipe_fds[2];
+    if (pipe(pipe_fds) == -1) {
+        PLOG(ERROR) << "Failed to create pipe";
+        return false;
+    }
+
     pid_t child_pid = fork();
     if (child_pid == -1) {
         PLOG(ERROR) << "Failed to fork for " << filename;
@@ -634,6 +644,18 @@
 
     if (child_pid == 0) {
         // fork succeeded -- this is executing in the child process
+
+        // Close the pipe FD not used by this process
+        TEMP_FAILURE_RETRY(close(pipe_fds[0]));
+
+        // Redirect stderr to the pipe FD provided by the parent
+        if (TEMP_FAILURE_RETRY(dup2(pipe_fds[1], STDERR_FILENO)) == -1) {
+            PLOG(ERROR) << "Failed to redirect stderr of " << filename;
+            _exit(127);
+            return false;
+        }
+        TEMP_FAILURE_RETRY(close(pipe_fds[1]));
+
         if (execve(filename, argv, envp) == -1) {
             PLOG(ERROR) << "Failed to execve " << filename;
             return false;
@@ -644,6 +666,30 @@
         return false;
     } else {
         // fork succeeded -- this is executing in the original/parent process
+
+        // Close the pipe FD not used by this process
+        TEMP_FAILURE_RETRY(close(pipe_fds[1]));
+
+        // Log the redirected output of the child process.
+        // It's unfortunate that there's no standard way to obtain an istream for a file descriptor.
+        // As a result, we're buffering all output and logging it in one go at the end of the
+        // invocation, instead of logging it as it comes in.
+        const int child_out_fd = pipe_fds[0];
+        std::string child_output;
+        if (!android::base::ReadFdToString(child_out_fd, &child_output)) {
+            PLOG(ERROR) << "Failed to capture full output of " << filename;
+        }
+        TEMP_FAILURE_RETRY(close(child_out_fd));
+        if (!child_output.empty()) {
+            // Log captured output, line by line, because LOG expects to be invoked for each line
+            std::istringstream in(child_output);
+            std::string line;
+            while (std::getline(in, line)) {
+                LOG(ERROR) << filename << ": " << line;
+            }
+        }
+
+        // Wait for child to terminate
         int status;
         if (TEMP_FAILURE_RETRY(waitpid(child_pid, &status, 0)) != child_pid) {
             PLOG(ERROR) << "Failed to wait for " << filename;
@@ -669,7 +715,45 @@
     }
 }
 
-static constexpr const char plat_policy_cil_file[] = "/plat_sepolicy.cil";
+static bool read_first_line(const char* file, std::string* line) {
+    line->clear();
+
+    std::string contents;
+    if (!android::base::ReadFileToString(file, &contents, true /* follow symlinks */)) {
+        return false;
+    }
+    std::istringstream in(contents);
+    std::getline(in, *line);
+    return true;
+}
+
+static bool selinux_find_precompiled_split_policy(std::string* file) {
+    file->clear();
+
+    static constexpr const char precompiled_sepolicy[] = "/vendor/etc/selinux/precompiled_sepolicy";
+    if (access(precompiled_sepolicy, R_OK) == -1) {
+        return false;
+    }
+    std::string actual_plat_id;
+    if (!read_first_line("/system/etc/selinux/plat_sepolicy.cil.sha256", &actual_plat_id)) {
+        PLOG(INFO) << "Failed to read /system/etc/selinux/plat_sepolicy.cil.sha256";
+        return false;
+    }
+    std::string precompiled_plat_id;
+    if (!read_first_line("/vendor/etc/selinux/precompiled_sepolicy.plat.sha256",
+                         &precompiled_plat_id)) {
+        PLOG(INFO) << "Failed to read /vendor/etc/selinux/precompiled_sepolicy.plat.sha256";
+        return false;
+    }
+    if ((actual_plat_id.empty()) || (actual_plat_id != precompiled_plat_id)) {
+        return false;
+    }
+
+    *file = precompiled_sepolicy;
+    return true;
+}
+
+static constexpr const char plat_policy_cil_file[] = "/system/etc/selinux/plat_sepolicy.cil";
 
 static bool selinux_is_split_policy_device() { return access(plat_policy_cil_file, R_OK) != -1; }
 
@@ -688,6 +772,22 @@
     // secilc is invoked to compile the above three policy files into a single monolithic policy
     // file. This file is then loaded into the kernel.
 
+    // Load precompiled policy from vendor image, if a matching policy is found there. The policy
+    // must match the platform policy on the system image.
+    std::string precompiled_sepolicy_file;
+    if (selinux_find_precompiled_split_policy(&precompiled_sepolicy_file)) {
+        android::base::unique_fd fd(
+            open(precompiled_sepolicy_file.c_str(), O_RDONLY | O_CLOEXEC | O_BINARY));
+        if (fd != -1) {
+            if (selinux_android_load_policy_from_fd(fd, precompiled_sepolicy_file.c_str()) < 0) {
+                LOG(ERROR) << "Failed to load SELinux policy from " << precompiled_sepolicy_file;
+                return false;
+            }
+            return true;
+        }
+    }
+    // No suitable precompiled policy could be loaded
+
     LOG(INFO) << "Compiling SELinux policy";
 
     // We store the output of the compilation on /dev because this is the most convenient tmpfs
@@ -701,7 +801,8 @@
 
     const char* compile_args[] = {"/system/bin/secilc", plat_policy_cil_file, "-M", "true", "-c",
                                   "30",  // TODO: pass in SELinux policy version from build system
-                                  "/mapping_sepolicy.cil", "/nonplat_sepolicy.cil", "-o",
+                                  "/vendor/etc/selinux/mapping_sepolicy.cil",
+                                  "/vendor/etc/selinux/nonplat_sepolicy.cil", "-o",
                                   compiled_sepolicy,
                                   // We don't care about file_contexts output by the compiler
                                   "-f", "/sys/fs/selinux/null",  // /dev/null is not yet available
diff --git a/libbinderwrapper/Android.mk b/libbinderwrapper/Android.mk
index b38d262..c768373 100644
--- a/libbinderwrapper/Android.mk
+++ b/libbinderwrapper/Android.mk
@@ -41,7 +41,7 @@
 
 include $(BUILD_SHARED_LIBRARY)
 
-# libbinderwrapper_test_support shared library
+# libbinderwrapper_test_support static library
 # ========================================================
 
 include $(CLEAR_VARS)
@@ -59,4 +59,4 @@
   binder_test_base.cc \
   stub_binder_wrapper.cc \
 
-include $(BUILD_SHARED_LIBRARY)
+include $(BUILD_STATIC_LIBRARY)
diff --git a/liblog/Android.bp b/liblog/Android.bp
index 310dbf4..bb8c3af 100644
--- a/liblog/Android.bp
+++ b/liblog/Android.bp
@@ -26,6 +26,7 @@
     "logger_read.c",
     "logger_write.c",
     "logprint.c",
+    "stderr_write.c",
 ]
 liblog_host_sources = [
     "fake_log_device.c",
diff --git a/liblog/config_write.c b/liblog/config_write.c
index 583dcff..6a6c220 100644
--- a/liblog/config_write.c
+++ b/liblog/config_write.c
@@ -78,6 +78,29 @@
                                     &fakeLoggerWrite);
 #endif
     }
+
+    if (__android_log_frontend & LOGGER_STDERR) {
+        extern struct android_log_transport_write stderrLoggerWrite;
+
+        /*
+         * stderr logger should be primary if we can be the only one, or if
+         * already in the primary list.  Otherwise land in the persist list.
+         * Remember we can be called here if we are already initialized.
+         */
+        if (list_empty(&__android_log_transport_write)) {
+            __android_log_add_transport(&__android_log_transport_write,
+                                        &stderrLoggerWrite);
+        } else {
+            struct android_log_transport_write *transp;
+            write_transport_for_each(transp, &__android_log_transport_write) {
+                if (transp == &stderrLoggerWrite) {
+                    return;
+                }
+            }
+            __android_log_add_transport(&__android_log_persist_write,
+                                        &stderrLoggerWrite);
+        }
+    }
 }
 
 LIBLOG_HIDDEN void __android_log_config_write_close() {
diff --git a/liblog/include/log/log_frontend.h b/liblog/include/log/log_frontend.h
index 9527779..5efa548 100644
--- a/liblog/include/log/log_frontend.h
+++ b/liblog/include/log/log_frontend.h
@@ -17,11 +17,12 @@
 /*
  * Logging frontends, bit mask to select features. Function returns selection.
  */
-#define LOGGER_DEFAULT 0x0
-#define LOGGER_LOGD    0x1
-#define LOGGER_KERNEL  0x2 /* Reserved/Deprecated */
-#define LOGGER_NULL    0x4 /* Does not release resources of other selections */
-#define LOGGER_LOCAL   0x8 /* logs sent to local memory */
+#define LOGGER_DEFAULT 0x00
+#define LOGGER_LOGD    0x01
+#define LOGGER_KERNEL  0x02 /* Reserved/Deprecated */
+#define LOGGER_NULL    0x04 /* Does not release resources of other selections */
+#define LOGGER_LOCAL   0x08 /* logs sent to local memory */
+#define LOGGER_STDERR  0x10 /* logs sent to stderr */
 
 /* Both return the selected frontend flag mask, or negative errno */
 int android_set_log_frontend(int frontend_flag);
diff --git a/liblog/logger_write.c b/liblog/logger_write.c
index e149e68..2a97101 100644
--- a/liblog/logger_write.c
+++ b/liblog/logger_write.c
@@ -664,9 +664,9 @@
         return retval;
     }
 
-    __android_log_frontend &= LOGGER_LOCAL | LOGGER_LOGD;
+    __android_log_frontend &= LOGGER_LOCAL | LOGGER_LOGD | LOGGER_STDERR;
 
-    frontend_flag &= LOGGER_LOCAL | LOGGER_LOGD;
+    frontend_flag &= LOGGER_LOCAL | LOGGER_LOGD | LOGGER_STDERR;
 
     if (__android_log_frontend != frontend_flag) {
         __android_log_frontend = frontend_flag;
@@ -695,7 +695,7 @@
     if (write_to_log == __write_to_log_null) {
         ret = LOGGER_NULL;
     } else {
-        __android_log_frontend &= LOGGER_LOCAL | LOGGER_LOGD;
+        __android_log_frontend &= LOGGER_LOCAL | LOGGER_LOGD | LOGGER_STDERR;
         ret = __android_log_frontend;
         if ((write_to_log != __write_to_log_init) &&
             (write_to_log != __write_to_log_daemon)) {
diff --git a/liblog/logprint.c b/liblog/logprint.c
index af52528..4421f83 100644
--- a/liblog/logprint.c
+++ b/liblog/logprint.c
@@ -20,9 +20,6 @@
 #define HAVE_STRSEP
 #endif
 
-//#ifndef __MINGW32__
-//#include <arpa/inet.h>
-//#endif
 #include <assert.h>
 #include <ctype.h>
 #include <errno.h>
@@ -117,7 +114,7 @@
     c = tolower(c);
 
     if (c >= '0' && c <= '9') {
-        if (c >= ('0'+ANDROID_LOG_SILENT)) {
+        if (c >= ('0' + ANDROID_LOG_SILENT)) {
             pri = ANDROID_LOG_VERBOSE;
         } else {
             pri = (android_LogPriority)(c - '0');
@@ -397,7 +394,7 @@
     }
 
     if(filterExpression[tagNameLength] == ':') {
-        pri = filterCharToPri(filterExpression[tagNameLength+1]);
+        pri = filterCharToPri(filterExpression[tagNameLength + 1]);
 
         if (pri == ANDROID_LOG_UNKNOWN) {
             goto error;
@@ -521,6 +518,9 @@
         struct logger_entry *buf,
         AndroidLogEntry *entry)
 {
+    entry->message = NULL;
+    entry->messageLen = 0;
+
     entry->tv_sec = buf->sec;
     entry->tv_nsec = buf->nsec;
     entry->uid = -1;
@@ -621,7 +621,7 @@
 
     low = src[0] | (src[1] << 8) | (src[2] << 16) | (src[3] << 24);
     high = src[4] | (src[5] << 8) | (src[6] << 16) | (src[7] << 24);
-    return ((uint64_t) high << 32) | (uint64_t) low;
+    return ((uint64_t)high << 32) | (uint64_t)low;
 }
 
 static bool findChar(const char** cp, size_t* len, int c) {
@@ -829,7 +829,10 @@
             eventData += 4;
             eventDataLen -= 4;
 
-            if (eventDataLen < strLen) return -1;
+            if (eventDataLen < strLen) {
+                result = -1; /* mark truncated */
+                strLen = eventDataLen;
+            }
 
             if (cp && (strLen == 0)) {
                 /* reset the format if no content */
@@ -840,15 +843,18 @@
                 memcpy(outBuf, eventData, strLen);
                 outBuf += strLen;
                 outBufLen -= strLen;
-            } else if (outBufLen > 0) {
-                /* copy what we can */
-                memcpy(outBuf, eventData, outBufLen);
-                outBuf += outBufLen;
-                outBufLen -= outBufLen;
-                goto no_room;
+            } else {
+                if (outBufLen > 0) {
+                    /* copy what we can */
+                    memcpy(outBuf, eventData, outBufLen);
+                    outBuf += outBufLen;
+                    outBufLen -= outBufLen;
+                }
+                if (!result) result = 1; /* if not truncated, return no room */
             }
             eventData += strLen;
             eventDataLen -= strLen;
+            if (result != 0) goto bail;
             break;
         }
     case EVENT_TYPE_LIST:
@@ -991,13 +997,16 @@
 LIBLOG_ABI_PUBLIC int android_log_processBinaryLogBuffer(
         struct logger_entry *buf,
         AndroidLogEntry *entry,
-        const EventTagMap *map __unused, // only on !__ANDROID__
+        const EventTagMap *map __unused, /* only on !__ANDROID__ */
         char *messageBuf, int messageBufLen)
 {
     size_t inCount;
     uint32_t tagIndex;
     const unsigned char* eventData;
 
+    entry->message = NULL;
+    entry->messageLen = 0;
+
     entry->tv_sec = buf->sec;
     entry->tv_nsec = buf->nsec;
     entry->priority = ANDROID_LOG_INFO;
@@ -1009,7 +1018,7 @@
      * Pull the tag out, fill in some additional details based on incoming
      * buffer version (v3 adds lid, v4 adds uid).
      */
-    eventData = (const unsigned char*) buf->msg;
+    eventData = (const unsigned char*)buf->msg;
     struct logger_entry_v2 *buf2 = (struct logger_entry_v2 *)buf;
     if (buf2->hdr_size) {
         if ((buf2->hdr_size < sizeof(((struct log_msg *)NULL)->entry_v1)) ||
@@ -1122,7 +1131,7 @@
      */
     *outBuf = '\0';
     entry->messageLen = outBuf - messageBuf;
-    assert(entry->messageLen == (messageBufLen-1) - outRemaining);
+    assert(entry->messageLen == (messageBufLen - 1) - outRemaining);
 
     entry->message = messageBuf;
 
@@ -1217,7 +1226,7 @@
                 } else if (*message == '\b') {
                     strcpy(buf, "\\b");
                 } else if (*message == '\t') {
-                    strcpy(buf, "\t"); // Do not escape tabs
+                    strcpy(buf, "\t"); /* Do not escape tabs */
                 } else if (*message == '\v') {
                     strcpy(buf, "\\v");
                 } else if (*message == '\f') {
@@ -1574,7 +1583,7 @@
     nsec = entry->tv_nsec;
 #if __ANDROID__
     if (p_format->monotonic_output) {
-        // prevent convertMonotonic from being called if logd is monotonic
+        /* prevent convertMonotonic from being called if logd is monotonic */
         if (android_log_clockid() != CLOCK_MONOTONIC) {
             struct timespec time;
             convertMonotonic(&time, entry);
@@ -1648,7 +1657,7 @@
             } else
 #endif
             {
-                 // Not worth parsing package list, names all longer than 5
+                 /* Not worth parsing package list, names all longer than 5 */
                  snprintf(uid, sizeof(uid), "%5d:", entry->uid);
             }
         } else {
@@ -1758,7 +1767,7 @@
             if (*pm++ == '\n') numLines++;
         }
         /* plus one line for anything not newline-terminated at the end */
-        if (pm > entry->message && *(pm-1) != '\n') numLines++;
+        if (pm > entry->message && *(pm - 1) != '\n') numLines++;
     }
 
     /*
diff --git a/liblog/stderr_write.c b/liblog/stderr_write.c
new file mode 100644
index 0000000..b739299
--- /dev/null
+++ b/liblog/stderr_write.c
@@ -0,0 +1,219 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+/*
+ * stderr write handler.  Output is logcat-like, and responds to
+ * logcat's environment variables ANDROID_PRINTF_LOG and
+ * ANDROID_LOG_TAGS to filter output.
+ *
+ * This transport only provides a writer, that means that it does not
+ * provide an End-To-End capability as the logs are effectively _lost_
+ * to the stderr file stream.  The purpose of this transport is to
+ * supply a means for command line tools to report their logging
+ * to the stderr stream, in line with all other activities.
+ */
+
+#include <errno.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <log/event_tag_map.h>
+#include <log/log.h>
+#include <log/logprint.h>
+#include <log/uio.h>
+
+#include "log_portability.h"
+#include "logger.h"
+
+static int stderrOpen();
+static void stderrClose();
+static int stderrAvailable(log_id_t logId);
+static int stderrWrite(log_id_t logId, struct timespec* ts,
+                       struct iovec* vec, size_t nr);
+
+struct stderrContext {
+    AndroidLogFormat* logformat;
+#if defined(__ANDROID__)
+    EventTagMap* eventTagMap;
+#endif
+};
+
+LIBLOG_HIDDEN struct android_log_transport_write stderrLoggerWrite = {
+    .node = { &stderrLoggerWrite.node, &stderrLoggerWrite.node },
+    .context.private = NULL,
+    .name = "stderr",
+    .available = stderrAvailable,
+    .open = stderrOpen,
+    .close = stderrClose,
+    .write = stderrWrite,
+};
+
+static int stderrOpen()
+{
+    struct stderrContext* ctx;
+    const char* envStr;
+    bool setFormat;
+
+    if (!stderr || (fileno(stderr) < 0)) {
+        return -EBADF;
+    }
+
+    if (stderrLoggerWrite.context.private) {
+        return fileno(stderr);
+    }
+
+    ctx = calloc(1, sizeof(struct stderrContext));
+    if (!ctx) {
+        return -ENOMEM;
+    }
+
+    ctx->logformat = android_log_format_new();
+    if (!ctx->logformat) {
+        free(ctx);
+        return -ENOMEM;
+    }
+
+    envStr = getenv("ANDROID_PRINTF_LOG");
+    setFormat = false;
+
+    if (envStr) {
+        char* formats = strdup(envStr);
+        char* sv = NULL;
+        char* arg = formats;
+        while (!!(arg = strtok_r(arg, ",:; \t\n\r\f", &sv))) {
+            AndroidLogPrintFormat format = android_log_formatFromString(arg);
+            arg = NULL;
+            if (format == FORMAT_OFF) {
+                continue;
+            }
+            if (android_log_setPrintFormat(ctx->logformat, format) <= 0) {
+                continue;
+            }
+            setFormat = true;
+        }
+        free(formats);
+    }
+    if (!setFormat) {
+        AndroidLogPrintFormat format = android_log_formatFromString(
+                "threadtime");
+        android_log_setPrintFormat(ctx->logformat, format);
+    }
+    envStr = getenv("ANDROID_LOG_TAGS");
+    if (envStr) {
+        android_log_addFilterString(ctx->logformat, envStr);
+    }
+    stderrLoggerWrite.context.private = ctx;
+
+    return fileno(stderr);
+}
+
+static void stderrClose()
+{
+    struct stderrContext* ctx = stderrLoggerWrite.context.private;
+
+    if (ctx) {
+        stderrLoggerWrite.context.private = NULL;
+        if (ctx->logformat) {
+            android_log_format_free(ctx->logformat);
+            ctx->logformat = NULL;
+        }
+#if defined(__ANDROID__)
+        if (ctx->eventTagMap) {
+            android_closeEventTagMap(ctx->eventTagMap);
+            ctx->eventTagMap = NULL;
+        }
+#endif
+    }
+}
+
+static int stderrAvailable(log_id_t logId)
+{
+    if ((logId >= LOG_ID_MAX) || (logId == LOG_ID_KERNEL)) {
+        return -EINVAL;
+    }
+    return 1;
+}
+
+static int stderrWrite(log_id_t logId, struct timespec* ts,
+                       struct iovec* vec, size_t nr)
+{
+    struct log_msg log_msg;
+    AndroidLogEntry entry;
+    char binaryMsgBuf[1024];
+    int err;
+    size_t i;
+    struct stderrContext* ctx = stderrLoggerWrite.context.private;
+
+    if (!ctx) return -EBADF;
+    if (!vec || !nr) return -EINVAL;
+
+    log_msg.entry.len = 0;
+    log_msg.entry.hdr_size = sizeof(log_msg.entry);
+    log_msg.entry.pid = getpid();
+#ifdef __BIONIC__
+    log_msg.entry.tid = gettid();
+#else
+    log_msg.entry.tid = getpid();
+#endif
+    log_msg.entry.sec = ts->tv_sec;
+    log_msg.entry.nsec = ts->tv_nsec;
+    log_msg.entry.lid = logId;
+    log_msg.entry.uid = __android_log_uid();
+
+    for (i = 0; i < nr; ++i) {
+        size_t len = vec[i].iov_len;
+        if ((log_msg.entry.len + len) > LOGGER_ENTRY_MAX_PAYLOAD) {
+            len = LOGGER_ENTRY_MAX_PAYLOAD - log_msg.entry.len;
+        }
+        if (!len) continue;
+        memcpy(log_msg.entry.msg + log_msg.entry.len, vec[i].iov_base, len);
+        log_msg.entry.len += len;
+    }
+
+    if ((logId == LOG_ID_EVENTS) || (logId == LOG_ID_SECURITY)) {
+#if defined(__ANDROID__)
+        if (!ctx->eventTagMap) {
+            ctx->eventTagMap = android_openEventTagMap(NULL);
+        }
+#endif
+        err = android_log_processBinaryLogBuffer(&log_msg.entry_v1,
+                                                 &entry,
+#if defined(__ANDROID__)
+                                                 ctx->eventTagMap,
+#else
+                                                 NULL,
+#endif
+                                                 binaryMsgBuf,
+                                                 sizeof(binaryMsgBuf));
+    } else {
+        err = android_log_processLogBuffer(&log_msg.entry_v1, &entry);
+    }
+
+    /* print known truncated data, in essence logcat --debug */
+    if ((err < 0) && !entry.message) return -EINVAL;
+
+    if (!android_log_shouldPrintLine(ctx->logformat, entry.tag, entry.priority)) {
+        return log_msg.entry.len;
+    }
+
+    err = android_log_printLogLine(ctx->logformat, fileno(stderr), &entry);
+    if (err < 0) return errno ? -errno : -EINVAL;
+    return log_msg.entry.len;
+}
diff --git a/liblog/tests/Android.mk b/liblog/tests/Android.mk
index cfea452..0e6432c 100644
--- a/liblog/tests/Android.mk
+++ b/liblog/tests/Android.mk
@@ -57,6 +57,8 @@
 test_src_files := \
     liblog_test_default.cpp \
     liblog_test_local.cpp \
+    liblog_test_stderr.cpp \
+    liblog_test_stderr_local.cpp \
     log_id_test.cpp \
     log_radio_test.cpp \
     log_read_test.cpp \
diff --git a/liblog/tests/liblog_test.cpp b/liblog/tests/liblog_test.cpp
index bc0ea4c..2537fac 100644
--- a/liblog/tests/liblog_test.cpp
+++ b/liblog/tests/liblog_test.cpp
@@ -47,7 +47,7 @@
 #endif
 #endif
 
-#if (!defined(USING_LOGGER_DEFAULT) || !defined(USING_LOGGER_LOCAL))
+#if (!defined(USING_LOGGER_DEFAULT) || !defined(USING_LOGGER_LOCAL) || !defined(USING_LOGGER_STDERR))
 #ifdef liblog // a binary clue that we are overriding the test names
 // Does not support log reading blocking feature yet
 // Does not support LOG_ID_SECURITY (unless we set LOGGER_LOCAL | LOGGER_LOGD)
@@ -62,6 +62,11 @@
 #define USING_LOGGER_DEFAULT
 #endif
 #endif
+#ifdef USING_LOGGER_STDERR
+# define SUPPORTS_END_TO_END 0
+#else
+# define SUPPORTS_END_TO_END 1
+#endif
 
 // enhanced version of LOG_FAILURE_RETRY to add support for EAGAIN and
 // non-syscall libs. Since we are only using this in the emergency of
@@ -98,7 +103,7 @@
     usleep(1000);
 }
 
-#if (defined(__ANDROID__) && !defined(USING_LOGGER_LOCAL))
+#if (defined(__ANDROID__) && defined(USING_LOGGER_DEFAULT))
 static std::string popenToString(std::string command) {
     std::string ret;
 
@@ -176,8 +181,8 @@
         LOG_ID_EVENTS, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, 1000, pid)));
 
     log_time ts(CLOCK_MONOTONIC);
-    ASSERT_LT(0, __android_log_btwrite(0, EVENT_TYPE_LONG, &ts, sizeof(ts)));
-#ifndef USING_LOGGER_LOCAL
+    EXPECT_LT(0, __android_log_btwrite(0, EVENT_TYPE_LONG, &ts, sizeof(ts)));
+#ifdef USING_LOGGER_DEFAULT
     // Check that we can close and reopen the logger
     bool pmsgActiveAfter__android_log_btwrite;
     bool logdwActiveAfter__android_log_btwrite;
@@ -200,8 +205,8 @@
 #endif
 
     log_time ts1(CLOCK_MONOTONIC);
-    ASSERT_LT(0, __android_log_btwrite(0, EVENT_TYPE_LONG, &ts1, sizeof(ts1)));
-#ifndef USING_LOGGER_LOCAL
+    EXPECT_LT(0, __android_log_btwrite(0, EVENT_TYPE_LONG, &ts1, sizeof(ts1)));
+#ifdef USING_LOGGER_DEFAULT
     if (getuid() == AID_ROOT) {
         pmsgActiveAfter__android_log_btwrite = isPmsgActive();
         logdwActiveAfter__android_log_btwrite = isLogdwActive();
@@ -220,7 +225,7 @@
             break;
         }
 
-        ASSERT_EQ(log_msg.entry.pid, pid);
+        EXPECT_EQ(log_msg.entry.pid, pid);
 
         if ((log_msg.entry.len != sizeof(android_log_event_long_t))
          || (log_msg.id() != LOG_ID_EVENTS)) {
@@ -242,8 +247,8 @@
         }
     }
 
-    EXPECT_EQ(1, count);
-    EXPECT_EQ(1, second_count);
+    EXPECT_EQ(SUPPORTS_END_TO_END, count);
+    EXPECT_EQ(SUPPORTS_END_TO_END, second_count);
 
     android_logger_list_close(logger_list);
 #else
@@ -251,6 +256,54 @@
 #endif
 }
 
+#if (defined(__ANDROID__) || defined(USING_LOGGER_LOCAL))
+static void print_frontend(const char* prefix, int logger) {
+    static const char orstr[] = " | ";
+
+    if (!prefix) {
+        prefix = "";
+    }
+    if (logger < 0) {
+        fprintf(stderr, "%s%s\n", prefix, strerror(-logger));
+        return;
+    }
+
+    if (logger == LOGGER_DEFAULT) {
+        fprintf(stderr, "%sLOGGER_DEFAULT", prefix);
+        prefix = orstr;
+    }
+    if (logger & LOGGER_LOGD) {
+        fprintf(stderr, "%sLOGGER_LOGD", prefix);
+        prefix = orstr;
+    }
+    if (logger & LOGGER_KERNEL) {
+        fprintf(stderr, "%sLOGGER_KERNEL", prefix);
+        prefix = orstr;
+    }
+    if (logger & LOGGER_NULL) {
+        fprintf(stderr, "%sLOGGER_NULL", prefix);
+        prefix = orstr;
+    }
+    if (logger & LOGGER_LOCAL) {
+        fprintf(stderr, "%sLOGGER_LOCAL", prefix);
+        prefix = orstr;
+    }
+    if (logger & LOGGER_STDERR) {
+        fprintf(stderr, "%sLOGGER_STDERR", prefix);
+        prefix = orstr;
+    }
+    logger &= ~(LOGGER_LOGD | LOGGER_KERNEL | LOGGER_NULL | LOGGER_LOCAL |
+                LOGGER_STDERR);
+    if (logger) {
+        fprintf(stderr, "%s0x%x", prefix, logger);
+        prefix = orstr;
+    }
+    if (prefix == orstr) {
+        fprintf(stderr, "\n");
+    }
+}
+#endif
+
 // This test makes little sense standalone, and requires the tests ahead
 // and behind us, to make us whole.  We could incorporate a prefix and
 // suffix test to make this standalone, but opted to not complicate this.
@@ -261,10 +314,14 @@
 #endif
 
     int logger = android_get_log_frontend();
+    print_frontend("android_get_log_frontend = ", logger);
     EXPECT_NE(LOGGER_NULL, logger);
 
-    EXPECT_EQ(LOGGER_NULL, android_set_log_frontend(LOGGER_NULL));
-    EXPECT_EQ(LOGGER_NULL, android_get_log_frontend());
+    int ret;
+    EXPECT_EQ(LOGGER_NULL, ret = android_set_log_frontend(LOGGER_NULL));
+    print_frontend("android_set_log_frontend = ", ret);
+    EXPECT_EQ(LOGGER_NULL, ret = android_get_log_frontend());
+    print_frontend("android_get_log_frontend = ", ret);
 
     pid_t pid = getpid();
 
@@ -273,7 +330,7 @@
         LOG_ID_EVENTS, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, 1000, pid)));
 
     log_time ts(CLOCK_MONOTONIC);
-    ASSERT_LT(0, __android_log_btwrite(0, EVENT_TYPE_LONG, &ts, sizeof(ts)));
+    EXPECT_LT(0, __android_log_btwrite(0, EVENT_TYPE_LONG, &ts, sizeof(ts)));
 
     usleep(1000000);
 
@@ -285,7 +342,7 @@
             break;
         }
 
-        ASSERT_EQ(log_msg.entry.pid, pid);
+        EXPECT_EQ(log_msg.entry.pid, pid);
 
         if ((log_msg.entry.len != sizeof(android_log_event_long_t))
          || (log_msg.id() != LOG_ID_EVENTS)) {
@@ -307,8 +364,10 @@
 
     android_logger_list_close(logger_list);
 
-    EXPECT_EQ(logger, android_set_log_frontend(logger));
-    EXPECT_EQ(logger, android_get_log_frontend());
+    EXPECT_EQ(logger, ret = android_set_log_frontend(logger));
+    print_frontend("android_set_log_frontend = ", ret);
+    EXPECT_EQ(logger, ret = android_get_log_frontend());
+    print_frontend("android_get_log_frontend = ", ret);
 
     // False negative if liblog.__android_log_btwrite__android_logger_list_read
     // fails above, so we will likely succeed. But we will have so many
@@ -350,7 +409,7 @@
     log_time ts(CLOCK_REALTIME);
 #endif
 
-    ASSERT_LT(0, __android_log_bswrite(0, message));
+    EXPECT_LT(0, __android_log_bswrite(0, message));
     size_t num_lines = 1, size = 0, length = 0, total = 0;
     const char *cp = message;
     while (*cp) {
@@ -382,7 +441,7 @@
             break;
         }
 
-        ASSERT_EQ(log_msg.entry.pid, pid);
+        EXPECT_EQ(log_msg.entry.pid, pid);
 
         if ((log_msg.entry.sec < (ts.tv_sec - 1))
          || ((ts.tv_sec + 1) < log_msg.entry.sec)
@@ -413,19 +472,26 @@
             int processBinaryLogBuffer = android_log_processBinaryLogBuffer(
                 &log_msg.entry_v1, &entry, NULL, msgBuf, sizeof(msgBuf));
             EXPECT_EQ((length == total) ? 0 : -1, processBinaryLogBuffer);
-            if (processBinaryLogBuffer == 0) {
+            if ((processBinaryLogBuffer == 0) || entry.message) {
                 size_t line_overhead = 20;
                 if (pid > 99999) ++line_overhead;
                 if (pid > 999999) ++line_overhead;
                 fflush(stderr);
-                EXPECT_EQ((int)((line_overhead * num_lines) + size),
-                    android_log_printLogLine(logformat, fileno(stderr), &entry));
+                if (processBinaryLogBuffer) {
+                    EXPECT_GT((int)((line_overhead * num_lines) + size),
+                              android_log_printLogLine(logformat,
+                                                       fileno(stderr), &entry));
+                } else {
+                    EXPECT_EQ((int)((line_overhead * num_lines) + size),
+                              android_log_printLogLine(logformat,
+                                                       fileno(stderr), &entry));
+                }
             }
             android_log_format_free(logformat);
         }
     }
 
-    EXPECT_EQ(1, count);
+    EXPECT_EQ(SUPPORTS_END_TO_END, count);
 
     android_logger_list_close(logger_list);
 #else
@@ -527,7 +593,7 @@
         android_log_format_free(logformat);
     }
 
-    EXPECT_EQ(1, count);
+    EXPECT_EQ(SUPPORTS_END_TO_END, count);
 
     android_logger_list_close(logger_list);
 #else
@@ -1058,10 +1124,14 @@
 
     android_logger_list_close(logger_list);
 
+#if SUPPORTS_END_TO_END
     EXPECT_EQ(true, matches);
 
     EXPECT_LE(SIZEOF_MAX_PAYLOAD_BUF, static_cast<size_t>(max_len));
 #else
+    EXPECT_EQ(false, matches);
+#endif
+#else
     GTEST_LOG_(INFO) << "This test does nothing.\n";
 #endif
 }
@@ -1123,7 +1193,7 @@
         android_log_format_free(logformat);
     }
 
-    EXPECT_EQ(1, count);
+    EXPECT_EQ(SUPPORTS_END_TO_END, count);
 
     android_logger_list_close(logger_list);
 #else
@@ -1184,6 +1254,11 @@
 
     android_logger_list_close(logger_list);
 
+#if !SUPPORTS_END_TO_END
+    max_len = max_len ?
+        max_len :
+        LOGGER_ENTRY_MAX_PAYLOAD - sizeof(big_payload_tag);
+#endif
     EXPECT_LE(LOGGER_ENTRY_MAX_PAYLOAD - sizeof(big_payload_tag),
               static_cast<size_t>(max_len));
 
@@ -1255,14 +1330,14 @@
     android_logger_list_close(logger_list1);
     android_logger_list_close(logger_list2);
 
-    EXPECT_EQ(num, count1);
-    EXPECT_EQ(num - 10, count2);
+    EXPECT_EQ(num * SUPPORTS_END_TO_END, count1);
+    EXPECT_EQ((num - 10) * SUPPORTS_END_TO_END, count2);
 #else
     GTEST_LOG_(INFO) << "This test does nothing.\n";
 #endif
 }
 
-#ifndef USING_LOGGER_LOCAL // Do not retest logprint
+#ifdef USING_LOGGER_DEFAULT // Do not retest logprint
 static bool checkPriForTag(AndroidLogFormat *p_format, const char *tag, android_LogPriority pri) {
     return android_log_shouldPrintLine(p_format, tag, pri)
         && !android_log_shouldPrintLine(p_format, tag, (android_LogPriority)(pri - 1));
@@ -1331,9 +1406,9 @@
 
     android_log_format_free(p_format);
 }
-#endif // !USING_LOGGER_LOCAL
+#endif // USING_LOGGER_DEFAULT
 
-#ifndef USING_LOGGER_LOCAL // Do not retest property handling
+#ifdef USING_LOGGER_DEFAULT // Do not retest property handling
 TEST(liblog, is_loggable) {
 #ifdef __ANDROID__
     static const char tag[] = "is_loggable";
@@ -1632,12 +1707,12 @@
     GTEST_LOG_(INFO) << "This test does nothing.\n";
 #endif
 }
-#endif // !USING_LOGGER_LOCAL
+#endif // USING_LOGGER_DEFAULT
 
 // Following tests the specific issues surrounding error handling wrt logd.
 // Kills logd and toss all collected data, equivalent to logcat -b all -c,
 // except we also return errors to the logging callers.
-#ifndef USING_LOGGER_LOCAL
+#ifdef USING_LOGGER_DEFAULT
 #ifdef TEST_PREFIX
 // helper to liblog.enoent to count end-to-end matching logging messages.
 static int count_matching_ts(log_time ts) {
@@ -1687,7 +1762,7 @@
     TEST_PREFIX
     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));
+    EXPECT_EQ(SUPPORTS_END_TO_END, 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.
@@ -1732,18 +1807,18 @@
 
     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));
+    EXPECT_EQ(SUPPORTS_END_TO_END, count_matching_ts(ts));
 
 #else
     GTEST_LOG_(INFO) << "This test does nothing.\n";
 #endif
 }
-#endif // !USING_LOCAL_LOGGER
+#endif // USING_LOCAL_LOGD
 
 // Below this point we run risks of setuid(AID_SYSTEM) which may affect others.
 
 // Do not retest properties, and cannot log into LOG_ID_SECURITY
-#ifndef USING_LOGGER_LOCAL
+#ifdef USING_LOGGER_DEFAULT
 TEST(liblog, __security) {
 #ifdef __ANDROID__
     static const char persist_key[] = "persist.logd.security";
@@ -1929,7 +2004,7 @@
     GTEST_LOG_(INFO) << "This test does nothing.\n";
 #endif
 }
-#endif // !USING_LOGGER_LOCAL
+#endif // USING_LOGGER_DEFAULT
 
 #ifdef TEST_PREFIX
 static void android_errorWriteWithInfoLog_helper(int TAG, const char* SUBTAG,
@@ -2047,7 +2122,7 @@
             max_payload_buf,
             200,
             count);
-    EXPECT_EQ(1, count);
+    EXPECT_EQ(SUPPORTS_END_TO_END, count);
 #else
     GTEST_LOG_(INFO) << "This test does nothing.\n";
 #endif
@@ -2063,7 +2138,7 @@
             max_payload_buf,
             sizeof(max_payload_buf),
             count);
-    EXPECT_EQ(1, count);
+    EXPECT_EQ(SUPPORTS_END_TO_END, count);
 #else
     GTEST_LOG_(INFO) << "This test does nothing.\n";
 #endif
@@ -2095,7 +2170,7 @@
             max_payload_buf,
             200,
             count);
-    EXPECT_EQ(1, count);
+    EXPECT_EQ(SUPPORTS_END_TO_END, count);
 #else
     GTEST_LOG_(INFO) << "This test does nothing.\n";
 #endif
@@ -2118,6 +2193,46 @@
 
     count = 0;
 
+    // Do a Before and After on the count to measure the effect. Decrement
+    // what we find in Before to set the stage.
+    ASSERT_TRUE(NULL != (logger_list = android_logger_list_open(
+        LOG_ID_EVENTS, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, 1000, pid)));
+
+    for (;;) {
+        log_msg log_msg;
+        if (android_logger_list_read(logger_list, &log_msg) <= 0) break;
+
+        char *eventData = log_msg.msg();
+        if (!eventData) continue;
+
+        // Tag
+        int tag = get4LE(eventData);
+        eventData += 4;
+
+        if (tag != TAG) continue;
+
+        if (!SUBTAG) {
+            // This tag should not have been written because the data was null
+            --count;
+            break;
+        }
+
+        // List type
+        eventData++;
+        // Number of elements in list
+        eventData++;
+        // Element #1: string type for subtag
+        eventData++;
+
+        eventData +=4;
+
+        if (memcmp(SUBTAG, eventData, strlen(SUBTAG))) continue;
+        --count;
+    }
+
+    android_logger_list_close(logger_list);
+
+    // Do an After on the count to measure the effect.
     ASSERT_TRUE(NULL != (logger_list = android_logger_list_open(
         LOG_ID_EVENTS, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, 1000, pid)));
 
@@ -2184,7 +2299,7 @@
 #ifdef TEST_PREFIX
     int count;
     android_errorWriteLog_helper(123456785, "test-subtag", count);
-    EXPECT_EQ(1, count);
+    EXPECT_EQ(SUPPORTS_END_TO_END, count);
 #else
     GTEST_LOG_(INFO) << "This test does nothing.\n";
 #endif
@@ -2703,7 +2818,7 @@
         EXPECT_EQ(0, strcmp(expected_string, msgBuf));
     }
 
-    EXPECT_EQ(1, count);
+    EXPECT_EQ(SUPPORTS_END_TO_END, count);
 
     android_logger_list_close(logger_list);
 }
@@ -2789,7 +2904,7 @@
 #endif
 }
 
-#ifndef USING_LOGGER_LOCAL // Do not retest logger list handling
+#ifdef USING_LOGGER_DEFAULT // Do not retest logger list handling
 TEST(liblog, create_android_logger_overflow) {
     android_log_context ctx;
 
@@ -2829,9 +2944,9 @@
                                            msgBuf, sizeof(msgBuf)), 0);
     EXPECT_STREQ(msgBuf, "[1005,tag_def,(tag|1),(name|3),(format|3)]");
 }
-#endif // !USING_LOGGER_LOCAL
+#endif // USING_LOGGER_DEFAULT
 
-#ifndef USING_LOGGER_LOCAL // Do not retest pmsg functionality
+#ifdef USING_LOGGER_DEFAULT // Do not retest pmsg functionality
 #ifdef __ANDROID__
 static const char __pmsg_file[] =
         "/data/william-shakespeare/MuchAdoAboutNothing.txt";
@@ -2957,9 +3072,9 @@
     GTEST_LOG_(INFO) << "This test does nothing.\n";
 #endif
 }
-#endif // !USING_LOGGER_LOCAL
+#endif // USING_LOGGER_DEFAULT
 
-#ifndef USING_LOGGER_LOCAL // Do not retest event mapping functionality
+#ifdef USING_LOGGER_DEFAULT // Do not retest event mapping functionality
 #ifdef __ANDROID__
 // must be: '<needle:> 0 kB'
 static bool isZero(const std::string &content, std::string::size_type pos,
@@ -3063,9 +3178,9 @@
     GTEST_LOG_(INFO) << "This test does nothing.\n";
 #endif
 }
-#endif // !USING_LOGGER_LOCAL
+#endif // USING_LOGGER_DEFAULT
 
-#ifndef USING_LOGGER_LOCAL // Do not retest ratelimit
+#ifdef USING_LOGGER_DEFAULT // Do not retest ratelimit
 TEST(liblog, __android_log_ratelimit) {
     time_t state = 0;
 
@@ -3097,9 +3212,9 @@
     }
     // Do not test default seconds, to allow liblog to tune freely
 }
-#endif // !USING_LOGGER_LOCAL
+#endif // USING_LOGGER_DEFAULT
 
-#ifndef USING_LOGGER_LOCAL // Do not retest event mapping functionality
+#ifdef USING_LOGGER_DEFAULT // Do not retest event mapping functionality
 TEST(liblog, android_lookupEventTagNum) {
 #ifdef __ANDROID__
     EventTagMap* map = android_openEventTagMap(NULL);
@@ -3115,4 +3230,4 @@
     GTEST_LOG_(INFO) << "This test does nothing.\n";
 #endif
 }
-#endif // !USING_LOGGER_LOCAL
+#endif // USING_LOGGER_DEFAULT
diff --git a/liblog/tests/liblog_test_stderr.cpp b/liblog/tests/liblog_test_stderr.cpp
new file mode 100644
index 0000000..f0cb192
--- /dev/null
+++ b/liblog/tests/liblog_test_stderr.cpp
@@ -0,0 +1,5 @@
+#include <log/log_frontend.h>
+#define liblog liblog_stderr
+#define TEST_PREFIX android_set_log_frontend(LOGGER_STDERR);
+#define USING_LOGGER_STDERR
+#include "liblog_test.cpp"
diff --git a/liblog/tests/liblog_test_stderr_local.cpp b/liblog/tests/liblog_test_stderr_local.cpp
new file mode 100644
index 0000000..1555b4e
--- /dev/null
+++ b/liblog/tests/liblog_test_stderr_local.cpp
@@ -0,0 +1,4 @@
+#include <log/log_frontend.h>
+#define liblog liblog_stderr_local
+#define TEST_PREFIX android_set_log_frontend(LOGGER_LOCAL | LOGGER_STDERR);
+#include "liblog_test.cpp"
diff --git a/libmetricslogger/Android.bp b/libmetricslogger/Android.bp
index 75eab66..da8afe1 100644
--- a/libmetricslogger/Android.bp
+++ b/libmetricslogger/Android.bp
@@ -22,7 +22,7 @@
 
         // 524291 corresponds to sysui_histogram, from
         // frameworks/base/core/java/com/android/internal/logging/EventLogTags.logtags
-        "-DHISTOGRAM_LOG_TAG=524291",
+        "-DHISTOGRAM_LOG_TAG=524292",
     ],
 }
 
diff --git a/libmetricslogger/include/metricslogger/metrics_logger.h b/libmetricslogger/include/metricslogger/metrics_logger.h
index d30e56c..26aa189 100644
--- a/libmetricslogger/include/metricslogger/metrics_logger.h
+++ b/libmetricslogger/include/metricslogger/metrics_logger.h
@@ -24,5 +24,14 @@
 // buffer.
 void LogHistogram(const std::string& event, int32_t data);
 
+// TODO: replace these with the metric_logger.proto definitions
+enum {
+  LOGBUILDER_CATEGORY = 757,
+  LOGBUILDER_NAME = 799,
+  LOGBUILDER_BUCKET = 801,
+  LOGBUILDER_VALUE = 802,
+  LOGBUILDER_HISTOGRAM = 804,
+};
+
 }  // namespace metricslogger
 }  // namespace android
diff --git a/libmetricslogger/metrics_logger.cpp b/libmetricslogger/metrics_logger.cpp
index f8e0174..0d08f5c 100644
--- a/libmetricslogger/metrics_logger.cpp
+++ b/libmetricslogger/metrics_logger.cpp
@@ -23,9 +23,14 @@
 namespace android {
 namespace metricslogger {
 
+// Mirror com.android.internal.logging.MetricsLogger#histogram().
 void LogHistogram(const std::string& event, int32_t data) {
   android_log_event_list log(HISTOGRAM_LOG_TAG);
-  log << event << data << LOG_ID_EVENTS;
+  log << LOGBUILDER_CATEGORY << LOGBUILDER_HISTOGRAM
+      << LOGBUILDER_NAME << event
+      << LOGBUILDER_BUCKET << data
+      << LOGBUILDER_VALUE << 1
+      << LOG_ID_EVENTS;
 }
 
 }  // namespace metricslogger
diff --git a/libutils/BlobCache.cpp b/libutils/BlobCache.cpp
index 126995b..b0fdd44 100644
--- a/libutils/BlobCache.cpp
+++ b/libutils/BlobCache.cpp
@@ -17,13 +17,10 @@
 #define LOG_TAG "BlobCache"
 //#define LOG_NDEBUG 0
 
-#include <inttypes.h>
-#include <stdlib.h>
-#include <string.h>
-
 #include <utils/BlobCache.h>
-#include <utils/Errors.h>
-#include <utils/Log.h>
+#include <utils/Timers.h>
+
+#include <inttypes.h>
 
 #include <cutils/properties.h>
 
diff --git a/libutils/CallStack.cpp b/libutils/CallStack.cpp
index 699da74..bd6015e 100644
--- a/libutils/CallStack.cpp
+++ b/libutils/CallStack.cpp
@@ -16,9 +16,10 @@
 
 #define LOG_TAG "CallStack"
 
+#include <utils/CallStack.h>
+
 #include <memory>
 
-#include <utils/CallStack.h>
 #include <utils/Printer.h>
 #include <utils/Errors.h>
 #include <utils/Log.h>
diff --git a/libutils/LinearTransform.cpp b/libutils/LinearTransform.cpp
index 138ce8b..d2e91a8 100644
--- a/libutils/LinearTransform.cpp
+++ b/libutils/LinearTransform.cpp
@@ -16,10 +16,9 @@
 
 #define __STDC_LIMIT_MACROS
 
-#include <assert.h>
-#include <stdint.h>
-
 #include <utils/LinearTransform.h>
+#include <assert.h>
+
 
 // disable sanitize as these functions may intentionally overflow (see comments below).
 // the ifdef can be removed when host builds use clang.
diff --git a/libutils/Log.cpp b/libutils/Log.cpp
index bffb56e..2c1fb86 100644
--- a/libutils/Log.cpp
+++ b/libutils/Log.cpp
@@ -21,14 +21,14 @@
 
 namespace android {
 
-LogIfSlow::LogIfSlow(const char* tag, android_LogPriority priority,
-        int timeoutMillis, const char* message) :
-        mTag(tag), mPriority(priority), mTimeoutMillis(timeoutMillis), mMessage(message),
-        mStart(systemTime(SYSTEM_TIME_BOOTTIME)) {
+LogIfSlow::LogIfSlow(
+        const char* tag, android_LogPriority priority, int timeoutMillis, const char* message)
+        : mTag(tag), mPriority(priority), mTimeoutMillis(timeoutMillis), mMessage(message),
+          mStart(systemTime(SYSTEM_TIME_BOOTTIME)) {
 }
 
 LogIfSlow::~LogIfSlow() {
-    int durationMillis = nanoseconds_to_milliseconds(systemTime(SYSTEM_TIME_BOOTTIME) - mStart);
+    int durationMillis = (int)nanoseconds_to_milliseconds(systemTime(SYSTEM_TIME_BOOTTIME) - mStart);
     if (durationMillis > mTimeoutMillis) {
         LOG_PRI(mPriority, mTag, "%s: %dms", mMessage, durationMillis);
     }
diff --git a/libutils/Looper.cpp b/libutils/Looper.cpp
index 84bc028..6c57b2e 100644
--- a/libutils/Looper.cpp
+++ b/libutils/Looper.cpp
@@ -13,17 +13,8 @@
 // Debugs callback registration and invocation.
 #define DEBUG_CALLBACKS 0
 
-#include <errno.h>
-#include <fcntl.h>
-#include <inttypes.h>
-#include <limits.h>
-#include <string.h>
-#include <sys/eventfd.h>
-#include <unistd.h>
-
-#include <log/log.h>
 #include <utils/Looper.h>
-#include <utils/Timers.h>
+#include <sys/eventfd.h>
 
 namespace android {
 
diff --git a/libutils/NativeHandle.cpp b/libutils/NativeHandle.cpp
index e4daca7..97d06b8 100644
--- a/libutils/NativeHandle.cpp
+++ b/libutils/NativeHandle.cpp
@@ -19,14 +19,14 @@
 
 namespace android {
 
-sp<NativeHandle> NativeHandle::create(
-        native_handle_t* handle, bool ownsHandle) {
+sp<NativeHandle> NativeHandle::create(native_handle_t* handle, bool ownsHandle) {
     return handle ? new NativeHandle(handle, ownsHandle) : NULL;
 }
 
 NativeHandle::NativeHandle(native_handle_t* handle, bool ownsHandle)
-:   mHandle(handle), mOwnsHandle(ownsHandle)
-{}
+        : mHandle(handle), mOwnsHandle(ownsHandle) {
+
+}
 
 NativeHandle::~NativeHandle() {
     if (mOwnsHandle) {
diff --git a/libutils/Printer.cpp b/libutils/Printer.cpp
index 98cd2c6..9573a10 100644
--- a/libutils/Printer.cpp
+++ b/libutils/Printer.cpp
@@ -21,10 +21,6 @@
 #include <utils/String8.h>
 #include <utils/Log.h>
 
-#include <string.h>
-#include <stdio.h>
-#include <stdlib.h>
-
 namespace android {
 
 /*
diff --git a/libutils/ProcessCallStack.cpp b/libutils/ProcessCallStack.cpp
index 73ed4eb..1d9f30d 100644
--- a/libutils/ProcessCallStack.cpp
+++ b/libutils/ProcessCallStack.cpp
@@ -17,18 +17,11 @@
 #define LOG_TAG "ProcessCallStack"
 // #define LOG_NDEBUG 0
 
-#include <dirent.h>
-#include <errno.h>
-#include <stdio.h>
-#include <string.h>
-#include <memory>
-
-#include <utils/Log.h>
-#include <utils/Errors.h>
 #include <utils/ProcessCallStack.h>
-#include <utils/Printer.h>
 
-#include <limits.h>
+#include <dirent.h>
+
+#include <utils/Printer.h>
 
 namespace android {
 
diff --git a/libutils/PropertyMap.cpp b/libutils/PropertyMap.cpp
index 5520702..4bcdd0f 100644
--- a/libutils/PropertyMap.cpp
+++ b/libutils/PropertyMap.cpp
@@ -16,11 +16,7 @@
 
 #define LOG_TAG "PropertyMap"
 
-#include <stdlib.h>
-#include <string.h>
-
 #include <utils/PropertyMap.h>
-#include <utils/Log.h>
 
 // Enables debug output for the parser.
 #define DEBUG_PARSER 0
diff --git a/libutils/RefBase.cpp b/libutils/RefBase.cpp
index 4252ba6..0d98db9 100644
--- a/libutils/RefBase.cpp
+++ b/libutils/RefBase.cpp
@@ -17,18 +17,9 @@
 #define LOG_TAG "RefBase"
 // #define LOG_NDEBUG 0
 
-#include <fcntl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-
 #include <utils/RefBase.h>
 
 #include <utils/CallStack.h>
-#include <utils/Log.h>
-#include <utils/threads.h>
 
 #ifndef __unused
 #define __unused __attribute__((__unused__))
diff --git a/libutils/SharedBuffer.cpp b/libutils/SharedBuffer.cpp
index 1fa1d7a..bad98b2 100644
--- a/libutils/SharedBuffer.cpp
+++ b/libutils/SharedBuffer.cpp
@@ -16,13 +16,13 @@
 
 #define LOG_TAG "sharedbuffer"
 
+#include "SharedBuffer.h"
+
 #include <stdlib.h>
 #include <string.h>
 
 #include <log/log.h>
 
-#include "SharedBuffer.h"
-
 // ---------------------------------------------------------------------------
 
 namespace android {
diff --git a/libutils/StopWatch.cpp b/libutils/StopWatch.cpp
index 8c7b596..219c13c 100644
--- a/libutils/StopWatch.cpp
+++ b/libutils/StopWatch.cpp
@@ -16,9 +16,7 @@
 
 #define LOG_TAG "StopWatch"
 
-#include <string.h>
-#include <stdlib.h>
-#include <stdio.h>
+#include <utils/StopWatch.h>
 
 /* for PRId64 */
 #ifndef __STDC_FORMAT_MACROS
@@ -27,8 +25,6 @@
 #include <inttypes.h>
 
 #include <utils/Log.h>
-#include <utils/Errors.h>
-#include <utils/StopWatch.h>
 
 /*****************************************************************************/
 
diff --git a/libutils/String16.cpp b/libutils/String16.cpp
index 9f5cfea..12bb7c4 100644
--- a/libutils/String16.cpp
+++ b/libutils/String16.cpp
@@ -17,12 +17,6 @@
 #include <utils/String16.h>
 
 #include <utils/Log.h>
-#include <utils/Unicode.h>
-#include <utils/threads.h>
-
-#include <memory.h>
-#include <stdio.h>
-#include <ctype.h>
 
 #include "SharedBuffer.h"
 
diff --git a/libutils/String8.cpp b/libutils/String8.cpp
index cacaf91..0ac39f9 100644
--- a/libutils/String8.cpp
+++ b/libutils/String8.cpp
@@ -21,11 +21,7 @@
 
 #include <utils/Compat.h>
 #include <utils/Log.h>
-#include <utils/Unicode.h>
 #include <utils/String16.h>
-#include <utils/threads.h>
-
-#include <ctype.h>
 
 #include "SharedBuffer.h"
 
diff --git a/libutils/SystemClock.cpp b/libutils/SystemClock.cpp
index 965e32c..28fc351 100644
--- a/libutils/SystemClock.cpp
+++ b/libutils/SystemClock.cpp
@@ -19,17 +19,17 @@
  * System clock functions.
  */
 
+#define LOG_TAG "SystemClock"
+
+#include <utils/SystemClock.h>
+
 #include <sys/time.h>
-#include <limits.h>
-#include <fcntl.h>
 #include <string.h>
 #include <errno.h>
 
 #include <cutils/compiler.h>
-#include <utils/SystemClock.h>
-#include <utils/Timers.h>
 
-#define LOG_TAG "SystemClock"
+#include <utils/Timers.h>
 #include <utils/Log.h>
 
 namespace android {
diff --git a/libutils/Threads.cpp b/libutils/Threads.cpp
index def739f..6317c32 100644
--- a/libutils/Threads.cpp
+++ b/libutils/Threads.cpp
@@ -18,16 +18,10 @@
 #define LOG_TAG "libutils.threads"
 
 #include <assert.h>
-#include <errno.h>
-#include <memory.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
+#include <utils/Thread.h>
+#include <utils/AndroidThreads.h>
 
 #if !defined(_WIN32)
-# include <pthread.h>
-# include <sched.h>
 # include <sys/resource.h>
 #else
 # include <windows.h>
@@ -40,7 +34,6 @@
 #include <sys/prctl.h>
 #endif
 
-#include <utils/threads.h>
 #include <utils/Log.h>
 
 #include <cutils/sched_policy.h>
diff --git a/libutils/Timers.cpp b/libutils/Timers.cpp
index 201bc41..b2df9a5 100644
--- a/libutils/Timers.cpp
+++ b/libutils/Timers.cpp
@@ -20,7 +20,6 @@
 #include <utils/Timers.h>
 
 #include <limits.h>
-#include <sys/time.h>
 #include <time.h>
 
 #if defined(__ANDROID__)
@@ -53,7 +52,7 @@
 
 int toMillisecondTimeoutDelay(nsecs_t referenceTime, nsecs_t timeoutTime)
 {
-    int timeoutDelayMillis;
+    nsecs_t timeoutDelayMillis;
     if (timeoutTime > referenceTime) {
         uint64_t timeoutDelay = uint64_t(timeoutTime - referenceTime);
         if (timeoutDelay > uint64_t((INT_MAX - 1) * 1000000LL)) {
@@ -64,5 +63,5 @@
     } else {
         timeoutDelayMillis = 0;
     }
-    return timeoutDelayMillis;
+    return (int)timeoutDelayMillis;
 }
diff --git a/libutils/Tokenizer.cpp b/libutils/Tokenizer.cpp
index 2d0e83d..b68a2cf 100644
--- a/libutils/Tokenizer.cpp
+++ b/libutils/Tokenizer.cpp
@@ -16,14 +16,10 @@
 
 #define LOG_TAG "Tokenizer"
 
-#include <stdlib.h>
-#include <unistd.h>
+#include <utils/Tokenizer.h>
 #include <fcntl.h>
-#include <errno.h>
-#include <sys/types.h>
 #include <sys/stat.h>
 #include <utils/Log.h>
-#include <utils/Tokenizer.h>
 
 // Enables debug output for the tokenizer.
 #define DEBUG_TOKENIZER 0
diff --git a/libutils/Trace.cpp b/libutils/Trace.cpp
index 36fd802..8530fdc 100644
--- a/libutils/Trace.cpp
+++ b/libutils/Trace.cpp
@@ -14,12 +14,11 @@
  * limitations under the License.
  */
 
-#include <utils/misc.h>
 #include <utils/Trace.h>
+#include <utils/misc.h>
 
 static void traceInit() __attribute__((constructor));
 
-static void traceInit()
-{
+static void traceInit() {
     ::android::add_sysprop_change_callback(atrace_update_tags, 0);
 }
diff --git a/libutils/Unicode.cpp b/libutils/Unicode.cpp
index f1a41b9..5fd9155 100644
--- a/libutils/Unicode.cpp
+++ b/libutils/Unicode.cpp
@@ -16,11 +16,10 @@
 
 #define LOG_TAG "unicode"
 
+#include <utils/Unicode.h>
 #include <limits.h>
-#include <stddef.h>
 
 #include <log/log.h>
-#include <utils/Unicode.h>
 
 #if defined(_WIN32)
 # undef  nhtol
diff --git a/libutils/VectorImpl.cpp b/libutils/VectorImpl.cpp
index f7ca8f4..ef3277f 100644
--- a/libutils/VectorImpl.cpp
+++ b/libutils/VectorImpl.cpp
@@ -16,13 +16,13 @@
 
 #define LOG_TAG "Vector"
 
+#include <utils/VectorImpl.h>
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
 #include <log/log.h>
-#include <utils/Errors.h>
-#include <utils/VectorImpl.h>
 
 #include <safe_iop.h>
 
diff --git a/libutils/include/utils/BlobCache.h b/libutils/include/utils/BlobCache.h
index 65dca9f..27a81e3 100644
--- a/libutils/include/utils/BlobCache.h
+++ b/libutils/include/utils/BlobCache.h
@@ -19,10 +19,8 @@
 
 #include <stddef.h>
 
-#include <utils/Flattenable.h>
 #include <utils/RefBase.h>
 #include <utils/SortedVector.h>
-#include <utils/threads.h>
 
 namespace android {
 
diff --git a/libutils/include/utils/Condition.h b/libutils/include/utils/Condition.h
index 2c80acd..3019a21 100644
--- a/libutils/include/utils/Condition.h
+++ b/libutils/include/utils/Condition.h
@@ -41,6 +41,11 @@
  * call wait(), then either re-wait() if things aren't quite what you want,
  * or unlock the mutex and continue.  All threads calling wait() must
  * use the same mutex for a given Condition.
+ *
+ * On Android and Apple platforms, these are implemented as a simple wrapper
+ * around pthread condition variables.  Care must be taken to abide by
+ * the pthreads semantics, in particular, a boolean predicate must
+ * be re-evaluated after a wake-up, as spurious wake-ups may happen.
  */
 class Condition {
 public:
@@ -58,10 +63,11 @@
     explicit Condition(int type);
     ~Condition();
     // Wait on the condition variable.  Lock the mutex before calling.
+    // Note that spurious wake-ups may happen.
     status_t wait(Mutex& mutex);
     // same with relative timeout
     status_t waitRelative(Mutex& mutex, nsecs_t reltime);
-    // Signal the condition variable, allowing exactly one thread to continue.
+    // Signal the condition variable, allowing one thread to continue.
     void signal();
     // Signal the condition variable, allowing one or all threads to continue.
     void signal(WakeUpType type) {
@@ -142,17 +148,6 @@
     return -pthread_cond_timedwait(&mCond, &mutex.mMutex, &ts);
 }
 inline void Condition::signal() {
-    /*
-     * POSIX says pthread_cond_signal wakes up "one or more" waiting threads.
-     * However bionic follows the glibc guarantee which wakes up "exactly one"
-     * waiting thread.
-     *
-     * man 3 pthread_cond_signal
-     *   pthread_cond_signal restarts one of the threads that are waiting on
-     *   the condition variable cond. If no threads are waiting on cond,
-     *   nothing happens. If several threads are waiting on cond, exactly one
-     *   is restarted, but it is not specified which.
-     */
     pthread_cond_signal(&mCond);
 }
 inline void Condition::broadcast() {
diff --git a/libutils/include/utils/NativeHandle.h b/libutils/include/utils/NativeHandle.h
index b825168..73fe804 100644
--- a/libutils/include/utils/NativeHandle.h
+++ b/libutils/include/utils/NativeHandle.h
@@ -24,7 +24,7 @@
 
 namespace android {
 
-class NativeHandle: public LightRefBase<NativeHandle> {
+class NativeHandle : public LightRefBase<NativeHandle> {
 public:
     // Create a refcounted wrapper around a native_handle_t, and declare
     // whether the wrapper owns the handle (so that it should clean up the
@@ -41,7 +41,7 @@
     friend class LightRefBase<NativeHandle>;
 
     NativeHandle(native_handle_t* handle, bool ownsHandle);
-    virtual ~NativeHandle();
+    ~NativeHandle();
 
     native_handle_t* mHandle;
     bool mOwnsHandle;
diff --git a/libutils/include/utils/RefBase.h b/libutils/include/utils/RefBase.h
index 36016cd..a61ea58 100644
--- a/libutils/include/utils/RefBase.h
+++ b/libutils/include/utils/RefBase.h
@@ -371,10 +371,8 @@
 
 private:
     friend class ReferenceMover;
-    inline static void renameRefs(size_t /*n*/,
-            const ReferenceRenamer& /*renamer*/) { }
-    inline static void renameRefId(T* /*ref*/,
-            const void* /*old_id*/ , const void* /*new_id*/) { }
+    inline static void renameRefs(size_t /*n*/, const ReferenceRenamer& /*renamer*/) { }
+    inline static void renameRefId(T* /*ref*/, const void* /*old_id*/ , const void* /*new_id*/) { }
 
 private:
     mutable std::atomic<int32_t> mCount;
diff --git a/libutils/include/utils/Singleton.h b/libutils/include/utils/Singleton.h
index a989a47..bdb2332 100644
--- a/libutils/include/utils/Singleton.h
+++ b/libutils/include/utils/Singleton.h
@@ -18,9 +18,12 @@
 #define ANDROID_UTILS_SINGLETON_H
 
 #include <stdint.h>
+
+// some vendor code assumes they have atoi() after including this file.
+#include <stdlib.h>
+
 #include <sys/types.h>
 #include <utils/Mutex.h>
-#include <utils/threads.h>
 #include <cutils/compiler.h>
 
 namespace android {
diff --git a/libutils/include/utils/StrongPointer.h b/libutils/include/utils/StrongPointer.h
index 294e6b6..cdfdd8a 100644
--- a/libutils/include/utils/StrongPointer.h
+++ b/libutils/include/utils/StrongPointer.h
@@ -17,12 +17,6 @@
 #ifndef ANDROID_STRONG_POINTER_H
 #define ANDROID_STRONG_POINTER_H
 
-#include <cutils/atomic.h>
-
-#include <stdint.h>
-#include <sys/types.h>
-#include <stdlib.h>
-
 // ---------------------------------------------------------------------------
 namespace android {
 
diff --git a/libutils/include/utils/Trace.h b/libutils/include/utils/Trace.h
index eeba40d..5e9229c 100644
--- a/libutils/include/utils/Trace.h
+++ b/libutils/include/utils/Trace.h
@@ -19,16 +19,8 @@
 
 #if defined(__ANDROID__)
 
-#include <fcntl.h>
 #include <stdint.h>
-#include <stdio.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
 
-#include <cutils/compiler.h>
-#include <utils/threads.h>
 #include <cutils/trace.h>
 
 // See <cutils/trace.h> for more ATRACE_* macros.
@@ -37,6 +29,7 @@
 #define _PASTE(x, y) x ## y
 #define PASTE(x, y) _PASTE(x,y)
 #define ATRACE_NAME(name) android::ScopedTrace PASTE(___tracer, __LINE__) (ATRACE_TAG, name)
+
 // ATRACE_CALL is an ATRACE_NAME that uses the current function name.
 #define ATRACE_CALL() ATRACE_NAME(__FUNCTION__)
 
@@ -44,14 +37,13 @@
 
 class ScopedTrace {
 public:
-inline ScopedTrace(uint64_t tag, const char* name)
-    : mTag(tag) {
-    atrace_begin(mTag,name);
-}
+    inline ScopedTrace(uint64_t tag, const char* name) : mTag(tag) {
+        atrace_begin(mTag, name);
+    }
 
-inline ~ScopedTrace() {
-    atrace_end(mTag);
-}
+    inline ~ScopedTrace() {
+        atrace_end(mTag);
+    }
 
 private:
     uint64_t mTag;
diff --git a/libutils/misc.cpp b/libutils/misc.cpp
index 216dc14..2608a65 100644
--- a/libutils/misc.cpp
+++ b/libutils/misc.cpp
@@ -22,12 +22,7 @@
 #include <utils/misc.h>
 #include <utils/Log.h>
 
-#include <sys/stat.h>
-#include <string.h>
-#include <stdio.h>
-
 #if !defined(_WIN32)
-# include <pthread.h>
 #endif
 
 #include <utils/Vector.h>
diff --git a/logcat/Android.mk b/logcat/Android.mk
index 723c35e..f564f0f 100644
--- a/logcat/Android.mk
+++ b/logcat/Android.mk
@@ -16,7 +16,7 @@
 include $(CLEAR_VARS)
 
 LOCAL_MODULE := liblogcat
-LOCAL_SRC_FILES := logcat.cpp logcat_system.cpp
+LOCAL_SRC_FILES := logcat.cpp getopt_long.cpp logcat_system.cpp
 LOCAL_SHARED_LIBRARIES := $(logcatLibs)
 LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
 LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
diff --git a/logcat/getopt_long.cpp b/logcat/getopt_long.cpp
new file mode 100644
index 0000000..5f8dd66
--- /dev/null
+++ b/logcat/getopt_long.cpp
@@ -0,0 +1,402 @@
+/* $OpenBSD: getopt_long.c,v 1.26 2013/06/08 22:47:56 millert Exp $ */
+/* $NetBSD: getopt_long.c,v 1.15 2002/01/31 22:43:40 tv Exp $       */
+
+/*
+ * Copyright (c) 2002 Todd C. Miller <Todd.Miller@courtesan.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Sponsored in part by the Defense Advanced Research Projects
+ * Agency (DARPA) and Air Force Research Laboratory, Air Force
+ * Materiel Command, USAF, under agreement number F39502-99-1-0512.
+ */
+/*-
+ * Copyright (c) 2000 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Dieter Baron and Thomas Klausner.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/cdefs.h>
+
+#include <log/getopt.h>
+
+#define PRINT_ERROR ((context->opterr) && (*options != ':'))
+
+#define FLAG_PERMUTE 0x01  // permute non-options to the end of argv
+#define FLAG_ALLARGS 0x02  // treat non-options as args to option "-1"
+
+// return values
+#define BADCH (int)'?'
+#define BADARG ((*options == ':') ? (int)':' : (int)'?')
+#define INORDER (int)1
+
+#define D_PREFIX 0
+#define DD_PREFIX 1
+#define W_PREFIX 2
+
+// Compute the greatest common divisor of a and b.
+static int gcd(int a, int b) {
+    int c = a % b;
+    while (c) {
+        a = b;
+        b = c;
+        c = a % b;
+    }
+    return b;
+}
+
+// Exchange the block from nonopt_start to nonopt_end with the block from
+// nonopt_end to opt_end (keeping the same order of arguments in each block).
+// Returns optind - (nonopt_end - nonopt_start) for convenience.
+static int permute_args(getopt_context* context, char* const* nargv) {
+    // compute lengths of blocks and number and size of cycles
+    int nnonopts = context->nonopt_end - context->nonopt_start;
+    int nopts = context->optind - context->nonopt_end;
+    int ncycle = gcd(nnonopts, nopts);
+    int cyclelen = (context->optind - context->nonopt_start) / ncycle;
+
+    for (int i = 0; i < ncycle; i++) {
+        int cstart = context->nonopt_end + i;
+        int pos = cstart;
+        for (int j = 0; j < cyclelen; j++) {
+            if (pos >= context->nonopt_end) {
+                pos -= nnonopts;
+            } else {
+                pos += nopts;
+            }
+            char* swap = nargv[pos];
+            const_cast<char**>(nargv)[pos] = nargv[cstart];
+            const_cast<char**>(nargv)[cstart] = swap;
+        }
+    }
+    return context->optind - (context->nonopt_end - context->nonopt_start);
+}
+
+// parse_long_options_r --
+//    Parse long options in argc/argv argument vector.
+// Returns -1 if short_too is set and the option does not match long_options.
+static int parse_long_options_r(char* const* nargv, const char* options,
+                                const struct option* long_options, int* idx,
+                                bool short_too, struct getopt_context* context) {
+    const char* current_argv = context->place;
+    const char* current_dash;
+    switch (context->dash_prefix) {
+        case D_PREFIX:
+            current_dash = "-";
+            break;
+        case DD_PREFIX:
+            current_dash = "--";
+            break;
+        case W_PREFIX:
+            current_dash = "-W ";
+            break;
+        default:
+            current_dash = "";
+            break;
+    }
+    context->optind++;
+
+    const char* has_equal;
+    size_t current_argv_len;
+    if (!!(has_equal = strchr(current_argv, '='))) {
+        // argument found (--option=arg)
+        current_argv_len = has_equal - current_argv;
+        has_equal++;
+    } else {
+        current_argv_len = strlen(current_argv);
+    }
+
+    int match = -1;
+    bool exact_match = false;
+    bool second_partial_match = false;
+    for (int i = 0; long_options[i].name; i++) {
+        // find matching long option
+        if (strncmp(current_argv, long_options[i].name, current_argv_len)) {
+            continue;
+        }
+
+        if (strlen(long_options[i].name) == current_argv_len) {
+            // exact match
+            match = i;
+            exact_match = true;
+            break;
+        }
+        // If this is a known short option, don't allow
+        // a partial match of a single character.
+        if (short_too && current_argv_len == 1) continue;
+
+        if (match == -1) {  // first partial match
+            match = i;
+        } else if (long_options[i].has_arg != long_options[match].has_arg ||
+                   long_options[i].flag != long_options[match].flag ||
+                   long_options[i].val != long_options[match].val) {
+            second_partial_match = true;
+        }
+    }
+    if (!exact_match && second_partial_match) {
+        // ambiguous abbreviation
+        if (PRINT_ERROR) {
+            fprintf(context->optstderr ?: stderr,
+                    "option `%s%.*s' is ambiguous", current_dash,
+                    (int)current_argv_len, current_argv);
+        }
+        context->optopt = 0;
+        return BADCH;
+    }
+    if (match != -1) {  // option found
+        if (long_options[match].has_arg == no_argument && has_equal) {
+            if (PRINT_ERROR) {
+                fprintf(context->optstderr ?: stderr,
+                        "option `%s%.*s' doesn't allow an argument",
+                        current_dash, (int)current_argv_len, current_argv);
+            }
+            // XXX: GNU sets optopt to val regardless of flag
+            context->optopt =
+                long_options[match].flag ? 0 : long_options[match].val;
+            return BADCH;
+        }
+        if (long_options[match].has_arg == required_argument ||
+            long_options[match].has_arg == optional_argument) {
+            if (has_equal) {
+                context->optarg = has_equal;
+            } else if (long_options[match].has_arg == required_argument) {
+                // optional argument doesn't use next nargv
+                context->optarg = nargv[context->optind++];
+            }
+        }
+        if ((long_options[match].has_arg == required_argument) &&
+            !context->optarg) {
+            // Missing argument; leading ':' indicates no error
+            // should be generated.
+            if (PRINT_ERROR) {
+                fprintf(context->optstderr ?: stderr,
+                        "option `%s%s' requires an argument", current_dash,
+                        current_argv);
+            }
+            // XXX: GNU sets optopt to val regardless of flag
+            context->optopt =
+                long_options[match].flag ? 0 : long_options[match].val;
+            context->optind--;
+            return BADARG;
+        }
+    } else {  // unknown option
+        if (short_too) {
+            context->optind--;
+            return -1;
+        }
+        if (PRINT_ERROR) {
+            fprintf(context->optstderr ?: stderr, "unrecognized option `%s%s'",
+                    current_dash, current_argv);
+        }
+        context->optopt = 0;
+        return BADCH;
+    }
+    if (idx) *idx = match;
+    if (long_options[match].flag) {
+        *long_options[match].flag = long_options[match].val;
+        return 0;
+    }
+    return long_options[match].val;
+}
+
+// getopt_long_r --
+//    Parse argc/argv argument vector.
+int getopt_long_r(int nargc, char* const* nargv, const char* options,
+                  const struct option* long_options, int* idx,
+                  struct getopt_context* context) {
+    if (!options) return -1;
+
+    // XXX Some GNU programs (like cvs) set optind to 0 instead of
+    // XXX using optreset.  Work around this braindamage.
+    if (!context->optind) context->optind = context->optreset = 1;
+
+    // Disable GNU extensions if options string begins with a '+'.
+    int flags = FLAG_PERMUTE;
+    if (*options == '-') {
+        flags |= FLAG_ALLARGS;
+    } else if (*options == '+') {
+        flags &= ~FLAG_PERMUTE;
+    }
+    if (*options == '+' || *options == '-') options++;
+
+    context->optarg = nullptr;
+    if (context->optreset) context->nonopt_start = context->nonopt_end = -1;
+start:
+    if (context->optreset || !*context->place) {  // update scanning pointer
+        context->optreset = 0;
+        if (context->optind >= nargc) {  // end of argument vector
+            context->place = EMSG;
+            if (context->nonopt_end != -1) {
+                // do permutation, if we have to
+                context->optind = permute_args(context, nargv);
+            } else if (context->nonopt_start != -1) {
+                // If we skipped non-options, set optind to the first of them.
+                context->optind = context->nonopt_start;
+            }
+            context->nonopt_start = context->nonopt_end = -1;
+            return -1;
+        }
+        if (*(context->place = nargv[context->optind]) != '-' ||
+            context->place[1] == '\0') {
+            context->place = EMSG;  // found non-option
+            if (flags & FLAG_ALLARGS) {
+                // GNU extension: return non-option as argument to option 1
+                context->optarg = nargv[context->optind++];
+                return INORDER;
+            }
+            if (!(flags & FLAG_PERMUTE)) {
+                // If no permutation wanted, stop parsing at first non-option.
+                return -1;
+            }
+            // do permutation
+            if (context->nonopt_start == -1) {
+                context->nonopt_start = context->optind;
+            } else if (context->nonopt_end != -1) {
+                context->nonopt_start = permute_args(context, nargv);
+                context->nonopt_end = -1;
+            }
+            context->optind++;
+            // process next argument
+            goto start;
+        }
+        if (context->nonopt_start != -1 && context->nonopt_end == -1) {
+            context->nonopt_end = context->optind;
+        }
+
+        // If we have "-" do nothing, if "--" we are done.
+        if (context->place[1] != '\0' && *++(context->place) == '-' &&
+            context->place[1] == '\0') {
+            context->optind++;
+            context->place = EMSG;
+            // We found an option (--), so if we skipped
+            // non-options, we have to permute.
+            if (context->nonopt_end != -1) {
+                context->optind = permute_args(context, nargv);
+            }
+            context->nonopt_start = context->nonopt_end = -1;
+            return -1;
+        }
+    }
+
+    int optchar;
+    // Check long options if:
+    //  1) we were passed some
+    //  2) the arg is not just "-"
+    //  3) either the arg starts with -- we are getopt_long_only()
+    if (long_options && context->place != nargv[context->optind] &&
+        (*context->place == '-')) {
+        bool short_too = false;
+        context->dash_prefix = D_PREFIX;
+        if (*context->place == '-') {
+            context->place++;  // --foo long option
+            context->dash_prefix = DD_PREFIX;
+        } else if (*context->place != ':' && strchr(options, *context->place)) {
+            short_too = true;  // could be short option too
+        }
+
+        optchar = parse_long_options_r(nargv, options, long_options, idx,
+                                       short_too, context);
+        if (optchar != -1) {
+            context->place = EMSG;
+            return optchar;
+        }
+    }
+
+    const char* oli;  // option letter list index
+    if ((optchar = (int)*(context->place)++) == (int)':' ||
+        (optchar == (int)'-' && *context->place != '\0') ||
+        !(oli = strchr(options, optchar))) {
+        // If the user specified "-" and  '-' isn't listed in
+        // options, return -1 (non-option) as per POSIX.
+        // Otherwise, it is an unknown option character (or ':').
+        if (optchar == (int)'-' && *context->place == '\0') return -1;
+        if (!*context->place) context->optind++;
+        if (PRINT_ERROR) {
+            fprintf(context->optstderr ?: stderr, "invalid option -- %c",
+                    optchar);
+        }
+        context->optopt = optchar;
+        return BADCH;
+    }
+
+    static const char recargchar[] = "option requires an argument -- %c";
+    if (long_options && optchar == 'W' && oli[1] == ';') {
+        // -W long-option
+        if (*context->place) {                      // no space
+            ;                                       // NOTHING
+        } else if (++(context->optind) >= nargc) {  // no arg
+            context->place = EMSG;
+            if (PRINT_ERROR) {
+                fprintf(context->optstderr ?: stderr, recargchar, optchar);
+            }
+            context->optopt = optchar;
+            return BADARG;
+        } else {  // white space
+            context->place = nargv[context->optind];
+        }
+        context->dash_prefix = W_PREFIX;
+        optchar = parse_long_options_r(nargv, options, long_options, idx, false,
+                                       context);
+        context->place = EMSG;
+        return optchar;
+    }
+    if (*++oli != ':') {  // doesn't take argument
+        if (!*context->place) context->optind++;
+    } else {  // takes (optional) argument
+        context->optarg = nullptr;
+        if (*context->place) {  // no white space
+            context->optarg = context->place;
+        } else if (oli[1] != ':') {              // arg not optional
+            if (++(context->optind) >= nargc) {  // no arg
+                context->place = EMSG;
+                if (PRINT_ERROR) {
+                    fprintf(context->optstderr ?: stderr, recargchar, optchar);
+                }
+                context->optopt = optchar;
+                return BADARG;
+            }
+            context->optarg = nargv[context->optind];
+        }
+        context->place = EMSG;
+        context->optind++;
+    }
+    // dump back option letter
+    return optchar;
+}
diff --git a/logcat/include/log/getopt.h b/logcat/include/log/getopt.h
new file mode 100644
index 0000000..0da2b10
--- /dev/null
+++ b/logcat/include/log/getopt.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2017 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 _LOG_GETOPT_H_
+#define _LOG_GETOPT_H_
+
+#ifndef __ANDROID_USE_LIBLOG_LOGCAT_INTERFACE
+#ifndef __ANDROID_API__
+#define __ANDROID_USE_LIBLOG_LOGCAT_INTERFACE 1
+#elif __ANDROID_API__ > 24 /* > Nougat */
+#define __ANDROID_USE_LIBLOG_LOGCAT_INTERFACE 1
+#else
+#define __ANDROID_USE_LIBLOG_LOGCAT_INTERFACE 0
+#endif
+#endif
+
+#if __ANDROID_USE_LIBLOG_LOGCAT_INTERFACE
+
+#include <getopt.h>
+#include <sys/cdefs.h>
+
+struct getopt_context {
+    int opterr;
+    int optind;
+    int optopt;
+    int optreset;
+    const char* optarg;
+    FILE* optstderr; /* NULL defaults to stderr */
+    /* private */
+    const char* place;
+    int nonopt_start;
+    int nonopt_end;
+    int dash_prefix;
+    /* expansion space */
+    int __extra__;
+    void* __stuff__;
+};
+
+#define EMSG ""
+#define NO_PREFIX (-1)
+
+#define INIT_GETOPT_CONTEXT(context) \
+    context = { 1, 1, '?', 0, NULL, NULL, EMSG, -1, -1, NO_PREFIX, 0, NULL }
+
+__BEGIN_DECLS
+int getopt_long_r(int nargc, char* const* nargv, const char* options,
+                  const struct option* long_options, int* idx,
+                  struct getopt_context* context);
+
+__END_DECLS
+
+#endif /* __ANDROID_USE_LIBLOG_LOGCAT_INTERFACE */
+
+#endif /* !_LOG_GETOPT_H_ */
diff --git a/logcat/logcat.cpp b/logcat/logcat.cpp
index 077332a..4da5030 100644
--- a/logcat/logcat.cpp
+++ b/logcat/logcat.cpp
@@ -20,7 +20,6 @@
 #include <dirent.h>
 #include <errno.h>
 #include <fcntl.h>
-#include <getopt.h>
 #include <math.h>
 #include <pthread.h>
 #include <sched.h>
@@ -47,6 +46,7 @@
 #include <cutils/sched_policy.h>
 #include <cutils/sockets.h>
 #include <log/event_tag_map.h>
+#include <log/getopt.h>
 #include <log/logcat.h>
 #include <log/logprint.h>
 #include <private/android_logger.h>
@@ -56,6 +56,25 @@
 
 #define DEFAULT_MAX_ROTATED_LOGS 4
 
+struct log_device_t {
+    const char* device;
+    bool binary;
+    struct logger* logger;
+    struct logger_list* logger_list;
+    bool printed;
+
+    log_device_t* next;
+
+    log_device_t(const char* d, bool b) {
+        device = d;
+        binary = b;
+        next = nullptr;
+        printed = false;
+        logger = nullptr;
+        logger_list = nullptr;
+    }
+};
+
 struct android_logcat_context_internal {
     // status
     volatile std::atomic_int retval;  // valid if thread_stopped set
@@ -91,15 +110,15 @@
     int printBinary;
     int devCount;  // >1 means multiple
     pcrecpp::RE* regex;
+    log_device_t* devices;
+    EventTagMap* eventTagMap;
     // 0 means "infinite"
     size_t maxCount;
     size_t printCount;
+
     bool printItAnyways;
     bool debug;
-
-    // static variables
     bool hasOpenedEventTagMap;
-    EventTagMap* eventTagMap;
 };
 
 // Creates a context associated with this logcat instance
@@ -127,25 +146,6 @@
 // logd prefixes records with a length field
 #define RECORD_LENGTH_FIELD_SIZE_BYTES sizeof(uint32_t)
 
-struct log_device_t {
-    const char* device;
-    bool binary;
-    struct logger* logger;
-    struct logger_list* logger_list;
-    bool printed;
-
-    log_device_t* next;
-
-    log_device_t(const char* d, bool b) {
-        device = d;
-        binary = b;
-        next = nullptr;
-        printed = false;
-        logger = nullptr;
-        logger_list = nullptr;
-    }
-};
-
 namespace android {
 
 enum helpType { HELP_FALSE, HELP_TRUE, HELP_FORMAT };
@@ -635,19 +635,17 @@
 }
 
 // Find last logged line in <outputFileName>, or <outputFileName>.1
-static log_time lastLogTime(char* outputFileName) {
+static log_time lastLogTime(const char* outputFileName) {
     log_time retval(log_time::EPOCH);
     if (!outputFileName) return retval;
 
     std::string directory;
-    char* file = strrchr(outputFileName, '/');
+    const char* file = strrchr(outputFileName, '/');
     if (!file) {
         directory = ".";
         file = outputFileName;
     } else {
-        *file = '\0';
-        directory = outputFileName;
-        *file = '/';
+        directory = std::string(outputFileName, file - outputFileName);
         ++file;
     }
 
@@ -736,11 +734,10 @@
     bool printStatistics = false;
     bool printDividers = false;
     unsigned long setLogSize = 0;
-    char* setPruneList = nullptr;
-    char* setId = nullptr;
+    const char* setPruneList = nullptr;
+    const char* setId = nullptr;
     int mode = ANDROID_LOG_RDONLY;
     std::string forceFilters;
-    log_device_t* devices = nullptr;
     log_device_t* dev;
     struct logger_list* logger_list;
     size_t tail_lines = 0;
@@ -855,8 +852,11 @@
     // net for stability dealing with possible mistaken inputs.
     static const char delimiters[] = ",:; \t\n\r\f";
 
-    // danger: getopt is _not_ reentrant
-    optind = 1;
+    struct getopt_context optctx;
+    INIT_GETOPT_CONTEXT(optctx);
+    optctx.opterr = !!context->error;
+    optctx.optstderr = context->error;
+
     for (;;) {
         int ret;
 
@@ -899,9 +899,9 @@
         };
         // clang-format on
 
-        ret = getopt_long(argc, argv,
-                          ":cdDLt:T:gG:sQf:r:n:v:b:BSpP:m:e:", long_options,
-                          &option_index);
+        ret = getopt_long_r(argc, argv,
+                            ":cdDLt:T:gG:sQf:r:n:v:b:BSpP:m:e:", long_options,
+                            &option_index, &optctx);
         if (ret < 0) break;
 
         switch (ret) {
@@ -909,9 +909,10 @@
                 // only long options
                 if (long_options[option_index].name == pid_str) {
                     // ToDo: determine runtime PID_MAX?
-                    if (!getSizeTArg(optarg, &pid, 1)) {
+                    if (!getSizeTArg(optctx.optarg, &pid, 1)) {
                         logcat_panic(context, HELP_TRUE, "%s %s out of range\n",
-                                     long_options[option_index].name, optarg);
+                                     long_options[option_index].name,
+                                     optctx.optarg);
                         goto exit;
                     }
                     break;
@@ -921,9 +922,11 @@
                             ANDROID_LOG_NONBLOCK;
                     // ToDo: implement API that supports setting a wrap timeout
                     size_t dummy = ANDROID_LOG_WRAP_DEFAULT_TIMEOUT;
-                    if (optarg && !getSizeTArg(optarg, &dummy, 1)) {
+                    if (optctx.optarg &&
+                        !getSizeTArg(optctx.optarg, &dummy, 1)) {
                         logcat_panic(context, HELP_TRUE, "%s %s out of range\n",
-                                     long_options[option_index].name, optarg);
+                                     long_options[option_index].name,
+                                     optctx.optarg);
                         goto exit;
                     }
                     if ((dummy != ANDROID_LOG_WRAP_DEFAULT_TIMEOUT) &&
@@ -944,7 +947,8 @@
                     break;
                 }
                 if (long_options[option_index].name == id_str) {
-                    setId = (optarg && optarg[0]) ? optarg : nullptr;
+                    setId = (optctx.optarg && optctx.optarg[0]) ? optctx.optarg
+                                                                : nullptr;
                 }
                 break;
 
@@ -972,12 +976,13 @@
                 mode |= ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK;
             // FALLTHRU
             case 'T':
-                if (strspn(optarg, "0123456789") != strlen(optarg)) {
-                    char* cp = parseTime(tail_time, optarg);
+                if (strspn(optctx.optarg, "0123456789") !=
+                    strlen(optctx.optarg)) {
+                    char* cp = parseTime(tail_time, optctx.optarg);
                     if (!cp) {
                         logcat_panic(context, HELP_FALSE,
                                      "-%c \"%s\" not in time format\n", ret,
-                                     optarg);
+                                     optctx.optarg);
                         goto exit;
                     }
                     if (*cp) {
@@ -987,16 +992,16 @@
                             fprintf(
                                 context->error,
                                 "WARNING: -%c \"%s\"\"%c%s\" time truncated\n",
-                                ret, optarg, c, cp + 1);
+                                ret, optctx.optarg, c, cp + 1);
                         }
                         *cp = c;
                     }
                 } else {
-                    if (!getSizeTArg(optarg, &tail_lines, 1)) {
+                    if (!getSizeTArg(optctx.optarg, &tail_lines, 1)) {
                         if (context->error) {
                             fprintf(context->error,
                                     "WARNING: -%c %s invalid, setting to 1\n",
-                                    ret, optarg);
+                                    ret, optctx.optarg);
                         }
                         tail_lines = 1;
                     }
@@ -1008,22 +1013,22 @@
                 break;
 
             case 'e':
-                context->regex = new pcrecpp::RE(optarg);
+                context->regex = new pcrecpp::RE(optctx.optarg);
                 break;
 
             case 'm': {
                 char* end = nullptr;
-                if (!getSizeTArg(optarg, &context->maxCount)) {
+                if (!getSizeTArg(optctx.optarg, &context->maxCount)) {
                     logcat_panic(context, HELP_FALSE,
                                  "-%c \"%s\" isn't an "
                                  "integer greater than zero\n",
-                                 ret, optarg);
+                                 ret, optctx.optarg);
                     goto exit;
                 }
             } break;
 
             case 'g':
-                if (!optarg) {
+                if (!optctx.optarg) {
                     getLogSize = true;
                     break;
                 }
@@ -1031,8 +1036,8 @@
 
             case 'G': {
                 char* cp;
-                if (strtoll(optarg, &cp, 0) > 0) {
-                    setLogSize = strtoll(optarg, &cp, 0);
+                if (strtoll(optctx.optarg, &cp, 0) > 0) {
+                    setLogSize = strtoll(optctx.optarg, &cp, 0);
                 } else {
                     setLogSize = 0;
                 }
@@ -1065,42 +1070,42 @@
             } break;
 
             case 'p':
-                if (!optarg) {
+                if (!optctx.optarg) {
                     getPruneList = true;
                     break;
                 }
             // FALLTHRU
 
             case 'P':
-                setPruneList = optarg;
+                setPruneList = optctx.optarg;
                 break;
 
             case 'b': {
-                std::unique_ptr<char, void (*)(void*)> buffers(strdup(optarg),
-                                                               free);
-                optarg = buffers.get();
+                std::unique_ptr<char, void (*)(void*)> buffers(
+                    strdup(optctx.optarg), free);
+                char* arg = buffers.get();
                 unsigned idMask = 0;
                 char* sv = nullptr;  // protect against -ENOMEM above
-                while (!!(optarg = strtok_r(optarg, delimiters, &sv))) {
-                    if (!strcmp(optarg, "default")) {
+                while (!!(arg = strtok_r(arg, delimiters, &sv))) {
+                    if (!strcmp(arg, "default")) {
                         idMask |= (1 << LOG_ID_MAIN) | (1 << LOG_ID_SYSTEM) |
                                   (1 << LOG_ID_CRASH);
-                    } else if (!strcmp(optarg, "all")) {
+                    } else if (!strcmp(arg, "all")) {
                         allSelected = true;
                         idMask = (unsigned)-1;
                     } else {
-                        log_id_t log_id = android_name_to_log_id(optarg);
+                        log_id_t log_id = android_name_to_log_id(arg);
                         const char* name = android_log_id_to_name(log_id);
 
-                        if (!!strcmp(name, optarg)) {
+                        if (!!strcmp(name, arg)) {
                             logcat_panic(context, HELP_TRUE,
-                                         "unknown buffer %s\n", optarg);
+                                         "unknown buffer %s\n", arg);
                             goto exit;
                         }
                         if (log_id == LOG_ID_SECURITY) allSelected = false;
                         idMask |= (1 << log_id);
                     }
-                    optarg = nullptr;
+                    arg = nullptr;
                 }
 
                 for (int i = LOG_ID_MIN; i < LOG_ID_MAX; ++i) {
@@ -1111,7 +1116,7 @@
                     if (!(idMask & (1 << i))) continue;
 
                     bool found = false;
-                    for (dev = devices; dev; dev = dev->next) {
+                    for (dev = context->devices; dev; dev = dev->next) {
                         if (!strcmp(name, dev->device)) {
                             found = true;
                             break;
@@ -1128,7 +1133,7 @@
                         dev->next = d;
                         dev = d;
                     } else {
-                        devices = dev = d;
+                        context->devices = dev = d;
                     }
                     context->devCount++;
                 }
@@ -1140,47 +1145,51 @@
 
             case 'f':
                 if ((tail_time == log_time::EPOCH) && !tail_lines) {
-                    tail_time = lastLogTime(optarg);
+                    tail_time = lastLogTime(optctx.optarg);
                 }
                 // redirect output to a file
-                context->outputFileName = optarg;
+                context->outputFileName = optctx.optarg;
                 break;
 
             case 'r':
-                if (!getSizeTArg(optarg, &context->logRotateSizeKBytes, 1)) {
+                if (!getSizeTArg(optctx.optarg, &context->logRotateSizeKBytes,
+                                 1)) {
                     logcat_panic(context, HELP_TRUE,
-                                 "Invalid parameter \"%s\" to -r\n", optarg);
+                                 "Invalid parameter \"%s\" to -r\n",
+                                 optctx.optarg);
                     goto exit;
                 }
                 break;
 
             case 'n':
-                if (!getSizeTArg(optarg, &context->maxRotatedLogs, 1)) {
+                if (!getSizeTArg(optctx.optarg, &context->maxRotatedLogs, 1)) {
                     logcat_panic(context, HELP_TRUE,
-                                 "Invalid parameter \"%s\" to -n\n", optarg);
+                                 "Invalid parameter \"%s\" to -n\n",
+                                 optctx.optarg);
                     goto exit;
                 }
                 break;
 
             case 'v': {
-                if (!strcmp(optarg, "help") || !strcmp(optarg, "--help")) {
+                if (!strcmp(optctx.optarg, "help") ||
+                    !strcmp(optctx.optarg, "--help")) {
                     show_format_help(context);
                     context->retval = EXIT_SUCCESS;
                     goto exit;
                 }
-                std::unique_ptr<char, void (*)(void*)> formats(strdup(optarg),
-                                                               free);
-                optarg = formats.get();
+                std::unique_ptr<char, void (*)(void*)> formats(
+                    strdup(optctx.optarg), free);
+                char* arg = formats.get();
                 unsigned idMask = 0;
                 char* sv = nullptr;  // protect against -ENOMEM above
-                while (!!(optarg = strtok_r(optarg, delimiters, &sv))) {
-                    err = setLogFormat(context, optarg);
+                while (!!(arg = strtok_r(arg, delimiters, &sv))) {
+                    err = setLogFormat(context, arg);
                     if (err < 0) {
                         logcat_panic(context, HELP_FORMAT,
-                                     "Invalid parameter \"%s\" to -v\n", optarg);
+                                     "Invalid parameter \"%s\" to -v\n", arg);
                         goto exit;
                     }
-                    optarg = nullptr;
+                    arg = nullptr;
                     if (err) hasSetLogFormat = true;
                 }
             } break;
@@ -1249,12 +1258,12 @@
 
             case ':':
                 logcat_panic(context, HELP_TRUE,
-                             "Option -%c needs an argument\n", optopt);
+                             "Option -%c needs an argument\n", optctx.optopt);
                 goto exit;
 
             default:
                 logcat_panic(context, HELP_TRUE, "Unrecognized Option %c\n",
-                             optopt);
+                             optctx.optopt);
                 goto exit;
         }
     }
@@ -1277,8 +1286,8 @@
         context->printItAnyways = false;
     }
 
-    if (!devices) {
-        dev = devices = new log_device_t("main", false);
+    if (!context->devices) {
+        dev = context->devices = new log_device_t("main", false);
         context->devCount = 1;
         if (android_name_to_log_id("system") == LOG_ID_SYSTEM) {
             dev = dev->next = new log_device_t("system", false);
@@ -1343,7 +1352,7 @@
                          "Invalid filter expression in logcat args\n");
             goto exit;
         }
-    } else if (argc == optind) {
+    } else if (argc == optctx.optind) {
         // Add from environment variable
         const char* env_tags_orig = android::getenv(context, "ANDROID_LOG_TAGS");
 
@@ -1359,7 +1368,7 @@
         }
     } else {
         // Add from commandline
-        for (int i = optind ; i < argc ; i++) {
+        for (int i = optctx.optind ; i < argc ; i++) {
             // skip stderr redirections of _all_ kinds
             if ((argv[i][0] == '2') && (argv[i][1] == '>')) continue;
             // skip stdout redirections of _all_ kinds
@@ -1374,7 +1383,7 @@
         }
     }
 
-    dev = devices;
+    dev = context->devices;
     if (tail_time != log_time::EPOCH) {
         logger_list = android_logger_list_alloc_time(mode, tail_time, pid);
     } else {
@@ -1585,7 +1594,7 @@
         }
 
         log_device_t* d;
-        for (d = devices; d; d = d->next) {
+        for (d = context->devices; d; d = d->next) {
             if (android_name_to_log_id(d->device) == log_msg.id()) break;
         }
         if (!d) {
@@ -1607,6 +1616,11 @@
     }
 
 close:
+    // Short and sweet. Implemented generic version in android_logcat_destroy.
+    while (!!(dev = context->devices)) {
+        context->devices = dev->next;
+        delete dev;
+    }
     android_logger_list_free(logger_list);
 
 exit:
@@ -1780,6 +1794,20 @@
 
     android_closeEventTagMap(context->eventTagMap);
 
+    // generic cleanup of devices list to handle all possible dirty cases
+    log_device_t* dev;
+    while (!!(dev = context->devices)) {
+        struct logger_list* logger_list = dev->logger_list;
+        if (logger_list) {
+            for (log_device_t* d = dev; d; d = d->next) {
+                if (d->logger_list == logger_list) d->logger_list = nullptr;
+            }
+            android_logger_list_free(logger_list);
+        }
+        context->devices = dev->next;
+        delete dev;
+    }
+
     int retval = context->retval;
 
     free(context);
diff --git a/logd/LogBuffer.cpp b/logd/LogBuffer.cpp
index e03731b..0df6de0 100644
--- a/logd/LogBuffer.cpp
+++ b/logd/LogBuffer.cpp
@@ -182,7 +182,10 @@
     if (!avcr) return DIFFERENT;
     lenr -= avcr - msgr;
     if (lenl != lenr) return DIFFERENT;
-    if (fastcmp<memcmp>(avcl + strlen(avc),
+    // TODO: After b/35468874 is addressed, revisit "lenl > strlen(avc)"
+    // condition, it might become superflous.
+    if (lenl > strlen(avc) &&
+        fastcmp<memcmp>(avcl + strlen(avc),
                         avcr + strlen(avc),
                         lenl - strlen(avc))) return DIFFERENT;
     return SAME;
diff --git a/rootdir/etc/public.libraries.android.txt b/rootdir/etc/public.libraries.android.txt
index 4081982..bcdecf2 100644
--- a/rootdir/etc/public.libraries.android.txt
+++ b/rootdir/etc/public.libraries.android.txt
@@ -13,10 +13,12 @@
 liblog.so
 libmediandk.so
 libm.so
+libnativewindow.so
 libOpenMAXAL.so
 libOpenSLES.so
 libRS.so
 libstdc++.so
+libsync.so
 libvulkan.so
 libwebviewchromium_plat_support.so
 libz.so
diff --git a/rootdir/etc/public.libraries.wear.txt b/rootdir/etc/public.libraries.wear.txt
index 9f0cde1..f4da09d 100644
--- a/rootdir/etc/public.libraries.wear.txt
+++ b/rootdir/etc/public.libraries.wear.txt
@@ -13,9 +13,11 @@
 liblog.so
 libmediandk.so
 libm.so
+libnativewindow.so
 libOpenMAXAL.so
 libOpenSLES.so
 libRS.so
 libstdc++.so
+libsync.so
 libvulkan.so
 libz.so
diff --git a/rootdir/init.rc b/rootdir/init.rc
index c6546b9..085ecaf 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -290,6 +290,9 @@
     # /data, which in turn can only be loaded when system properties are present.
     trigger post-fs-data
 
+    # Now we can start zygote for devices with file based encryption
+    trigger zygote-start
+
     # Load persist properties and override properties (if enabled) from /data.
     trigger load_persist_props_action
 
@@ -299,6 +302,12 @@
     trigger early-boot
     trigger boot
 
+on post-fs-data && property:ro.crypto.state=encrypted && property:ro.crypto.type=file
+    start netd
+
+on zygote-start && property:ro.crypto.state=encrypted && property:ro.crypto.type=file
+    start zygote
+
 on post-fs
     start logd
     # once everything is setup, no need to modify /
@@ -565,7 +574,6 @@
     chown system system /sys/class/leds/red/device/grpfreq
     chown system system /sys/class/leds/red/device/grppwm
     chown system system /sys/class/leds/red/device/blink
-    chown system system /sys/class/timed_output/vibrator/enable
     chown system system /sys/module/sco/parameters/disable_esco
     chown system system /sys/kernel/ipv4/tcp_wmem_min
     chown system system /sys/kernel/ipv4/tcp_wmem_def