Add mDNS device discovery for adb client
am: 13a269ea24

Change-Id: Ib5f80b3ccc9db7c6fe6f5c989e82083d734ce4df
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/Android.mk b/adb/Android.mk
index ef29695..b5b03ea 100644
--- a/adb/Android.mk
+++ b/adb/Android.mk
@@ -124,12 +124,11 @@
     adbd_auth.cpp \
     jdwp_service.cpp \
 
-LOCAL_C_INCLUDES := system/core/qemu_pipe/include
 LOCAL_SANITIZE := $(adb_target_sanitize)
 
 # Even though we're building a static library (and thus there's no link step for
 # this to take effect), this adds the includes to our path.
-LOCAL_STATIC_LIBRARIES := libcrypto_utils libcrypto libqemu_pipe libbase
+LOCAL_STATIC_LIBRARIES := libcrypto_utils libcrypto libbase
 
 LOCAL_WHOLE_STATIC_LIBRARIES := libadbd_usb
 
@@ -362,7 +361,6 @@
 LOCAL_STATIC_LIBRARIES := \
     libadbd \
     libbase \
-    libqemu_pipe \
     libbootloader_message \
     libfs_mgr \
     libfec \
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_local.cpp b/adb/transport_local.cpp
index 12b98ba..4198a52 100644
--- a/adb/transport_local.cpp
+++ b/adb/transport_local.cpp
@@ -289,7 +289,7 @@
 #define open    adb_open
 #define read    adb_read
 #define write   adb_write
-#include <qemu_pipe.h>
+#include <system/qemu_pipe.h>
 #undef open
 #undef read
 #undef write
diff --git a/debuggerd/Android.bp b/debuggerd/Android.bp
index 8d2ea68..af84be9 100644
--- a/debuggerd/Android.bp
+++ b/debuggerd/Android.bp
@@ -8,17 +8,35 @@
         "-Os",
     ],
 
+    // util.cpp gets async signal safe logging via libc_logging,
+    // which defines its interface in bionic private headers.
+    include_dirs: ["bionic/libc"],
+
     local_include_dirs: ["include"],
 }
 
+// Utility library to tombstoned and get an output fd.
+cc_library_static {
+    name: "libtombstoned_client",
+    defaults: ["debuggerd_defaults"],
+    srcs: [
+        "tombstoned_client.cpp",
+        "util.cpp",
+    ],
+
+    whole_static_libs: [
+        "libc_logging",
+        "libcutils",
+        "libbase",
+    ],
+}
+
+// Core implementation, linked into libdebuggerd_handler and the dynamic linker.
 cc_library_static {
     name: "libdebuggerd_handler_core",
     defaults: ["debuggerd_defaults"],
     srcs: ["handler/debuggerd_handler.cpp"],
 
-    // libdebuggerd_handler gets async signal safe logging via libc_logging,
-    // which defines its interface in bionic private headers.
-    include_dirs: ["bionic/libc"],
     whole_static_libs: [
         "libc_logging",
         "libdebuggerd",
@@ -27,6 +45,7 @@
     export_include_dirs: ["include"],
 }
 
+// Implementation with a no-op fallback.
 cc_library_static {
     name: "libdebuggerd_handler",
     defaults: ["debuggerd_defaults"],
@@ -39,15 +58,18 @@
     export_include_dirs: ["include"],
 }
 
+// Fallback implementation.
 cc_library_static {
     name: "libdebuggerd_handler_fallback",
     defaults: ["debuggerd_defaults"],
-    srcs: ["handler/debuggerd_fallback.cpp"],
+    srcs: [
+        "handler/debuggerd_fallback.cpp",
+    ],
 
-    // libdebuggerd_handler gets async signal safe logging via libc_logging,
-    // which defines its interface in bionic private headers.
-    include_dirs: ["bionic/libc"],
-    static_libs: [
+    whole_static_libs: [
+        "libdebuggerd_handler_core",
+        "libtombstoned_client",
+        "libbase",
         "libdebuggerd",
         "libbacktrace",
         "libunwind",
@@ -70,6 +92,7 @@
         "libbase",
         "libcutils",
     ],
+
     export_include_dirs: ["include"],
 }
 
@@ -187,6 +210,7 @@
     },
 
     static_libs: [
+        "libtombstoned_client",
         "libdebuggerd",
         "libcutils",
     ],
diff --git a/debuggerd/crash_dump.cpp b/debuggerd/crash_dump.cpp
index 0e15472..6585424 100644
--- a/debuggerd/crash_dump.cpp
+++ b/debuggerd/crash_dump.cpp
@@ -48,6 +48,7 @@
 
 #include "debuggerd/handler.h"
 #include "debuggerd/protocol.h"
+#include "debuggerd/tombstoned.h"
 #include "debuggerd/util.h"
 
 using android::base::unique_fd;
@@ -128,55 +129,6 @@
   return true;
 }
 
-static bool tombstoned_connect(pid_t pid, unique_fd* tombstoned_socket, unique_fd* output_fd) {
-  unique_fd sockfd(socket_local_client(kTombstonedCrashSocketName,
-                                       ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_SEQPACKET));
-  if (sockfd == -1) {
-    PLOG(ERROR) << "failed to connect to tombstoned";
-    return false;
-  }
-
-  TombstonedCrashPacket packet = {};
-  packet.packet_type = CrashPacketType::kDumpRequest;
-  packet.packet.dump_request.pid = pid;
-  if (TEMP_FAILURE_RETRY(write(sockfd, &packet, sizeof(packet))) != sizeof(packet)) {
-    PLOG(ERROR) << "failed to write DumpRequest packet";
-    return false;
-  }
-
-  unique_fd tmp_output_fd;
-  ssize_t rc = recv_fd(sockfd, &packet, sizeof(packet), &tmp_output_fd);
-  if (rc == -1) {
-    PLOG(ERROR) << "failed to read response to DumpRequest packet";
-    return false;
-  } else if (rc != sizeof(packet)) {
-    LOG(ERROR) << "read DumpRequest response packet of incorrect length (expected "
-               << sizeof(packet) << ", got " << rc << ")";
-    return false;
-  }
-
-  // Make the fd O_APPEND so that our output is guaranteed to be at the end of a file.
-  // (This also makes selinux rules consistent, because selinux distinguishes between writing to
-  // a regular fd, and writing to an fd with O_APPEND).
-  int flags = fcntl(tmp_output_fd.get(), F_GETFL);
-  if (fcntl(tmp_output_fd.get(), F_SETFL, flags | O_APPEND) != 0) {
-    PLOG(WARNING) << "failed to set output fd flags";
-  }
-
-  *tombstoned_socket = std::move(sockfd);
-  *output_fd = std::move(tmp_output_fd);
-  return true;
-}
-
-static bool tombstoned_notify_completion(int tombstoned_socket) {
-  TombstonedCrashPacket packet = {};
-  packet.packet_type = CrashPacketType::kCompletedDump;
-  if (TEMP_FAILURE_RETRY(write(tombstoned_socket, &packet, sizeof(packet))) != sizeof(packet)) {
-    return false;
-  }
-  return true;
-}
-
 static void signal_handler(int) {
   // We can't log easily, because the heap might be corrupt.
   // Just die and let the surrounding log context explain things.
diff --git a/debuggerd/handler/debuggerd_fallback.cpp b/debuggerd/handler/debuggerd_fallback.cpp
index 77ad6ac..5c6c59c 100644
--- a/debuggerd/handler/debuggerd_fallback.cpp
+++ b/debuggerd/handler/debuggerd_fallback.cpp
@@ -26,23 +26,206 @@
  * SUCH DAMAGE.
  */
 
+#include <dirent.h>
+#include <fcntl.h>
+#include <poll.h>
+#include <pthread.h>
 #include <stddef.h>
 #include <sys/ucontext.h>
+#include <syscall.h>
 #include <unistd.h>
 
+#include <atomic>
+
+#include <android-base/file.h>
+#include <android-base/unique_fd.h>
+
+#include "debuggerd/handler.h"
+#include "debuggerd/tombstoned.h"
+#include "debuggerd/util.h"
+
+#include "backtrace.h"
 #include "tombstone.h"
 
-extern "C" void __linker_use_fallback_allocator();
+#include "private/libc_logging.h"
 
-extern "C" bool debuggerd_fallback(ucontext_t* ucontext, siginfo_t* siginfo, void* abort_message) {
-  // This is incredibly sketchy to do inside of a signal handler, especially when libbacktrace
-  // uses the C++ standard library throughout, but this code runs in the linker, so we'll be using
-  // the linker's malloc instead of the libc one. Switch it out for a replacement, just in case.
-  //
-  // This isn't the default method of dumping because it can fail in cases such as memory space
-  // exhaustion.
-  __linker_use_fallback_allocator();
-  engrave_tombstone_ucontext(-1, getpid(), gettid(), reinterpret_cast<uintptr_t>(abort_message),
-                             siginfo, ucontext);
-  return true;
+using android::base::unique_fd;
+
+extern "C" void __linker_enable_fallback_allocator();
+extern "C" void __linker_disable_fallback_allocator();
+
+// This is incredibly sketchy to do inside of a signal handler, especially when libbacktrace
+// uses the C++ standard library throughout, but this code runs in the linker, so we'll be using
+// the linker's malloc instead of the libc one. Switch it out for a replacement, just in case.
+//
+// This isn't the default method of dumping because it can fail in cases such as address space
+// exhaustion.
+static void debuggerd_fallback_trace(int output_fd, ucontext_t* ucontext) {
+  __linker_enable_fallback_allocator();
+  dump_backtrace_ucontext(output_fd, ucontext);
+  __linker_disable_fallback_allocator();
+}
+
+static void debuggerd_fallback_tombstone(int output_fd, ucontext_t* ucontext, siginfo_t* siginfo,
+                                         void* abort_message) {
+  __linker_enable_fallback_allocator();
+  engrave_tombstone_ucontext(output_fd, reinterpret_cast<uintptr_t>(abort_message), siginfo,
+                             ucontext);
+  __linker_disable_fallback_allocator();
+}
+
+static void iterate_siblings(bool (*callback)(pid_t, int), int output_fd) {
+  pid_t current_tid = gettid();
+  char buf[BUFSIZ];
+  snprintf(buf, sizeof(buf), "/proc/%d/task", current_tid);
+  DIR* dir = opendir(buf);
+
+  if (!dir) {
+    __libc_format_log(ANDROID_LOG_ERROR, "libc", "failed to open %s: %s", buf, strerror(errno));
+    return;
+  }
+
+  struct dirent* ent;
+  while ((ent = readdir(dir))) {
+    char* end;
+    long tid = strtol(ent->d_name, &end, 10);
+    if (end == ent->d_name || *end != '\0') {
+      continue;
+    }
+
+    if (tid != current_tid) {
+      callback(tid, output_fd);
+    }
+  }
+  closedir(dir);
+}
+
+static bool forward_output(int src_fd, int dst_fd) {
+  // Make sure the thread actually got the signal.
+  struct pollfd pfd = {
+    .fd = src_fd, .events = POLLIN,
+  };
+
+  // Wait for up to a second for output to start flowing.
+  if (poll(&pfd, 1, 1000) != 1) {
+    return false;
+  }
+
+  while (true) {
+    char buf[512];
+    ssize_t rc = TEMP_FAILURE_RETRY(read(src_fd, buf, sizeof(buf)));
+    if (rc == 0) {
+      return true;
+    } else if (rc < 0) {
+      return false;
+    }
+
+    if (!android::base::WriteFully(dst_fd, buf, rc)) {
+      // We failed to write to tombstoned, but there's not much we can do.
+      // Keep reading from src_fd to keep things going.
+      continue;
+    }
+  }
+}
+
+static void trace_handler(siginfo_t* info, ucontext_t* ucontext) {
+  static std::atomic<int> trace_output_fd(-1);
+
+  if (info->si_value.sival_int == ~0) {
+    // Asked to dump by the original signal recipient.
+    debuggerd_fallback_trace(trace_output_fd, ucontext);
+
+    int tmp = trace_output_fd.load();
+    trace_output_fd.store(-1);
+    close(tmp);
+    return;
+  }
+
+  // Only allow one thread to perform a trace at a time.
+  static pthread_mutex_t trace_mutex = PTHREAD_MUTEX_INITIALIZER;
+  int ret = pthread_mutex_trylock(&trace_mutex);
+  if (ret != 0) {
+    __libc_format_log(ANDROID_LOG_INFO, "libc", "pthread_mutex_try_lock failed: %s", strerror(ret));
+    return;
+  }
+
+  // Fetch output fd from tombstoned.
+  unique_fd tombstone_socket, output_fd;
+  if (!tombstoned_connect(getpid(), &tombstone_socket, &output_fd)) {
+    goto exit;
+  }
+
+  dump_backtrace_header(output_fd.get());
+
+  // Dump our own stack.
+  debuggerd_fallback_trace(output_fd.get(), ucontext);
+
+  // Send a signal to all of our siblings, asking them to dump their stack.
+  iterate_siblings(
+    [](pid_t tid, int output_fd) {
+      // Use a pipe, to be able to detect situations where the thread gracefully exits before
+      // receiving our signal.
+      unique_fd pipe_read, pipe_write;
+      if (!Pipe(&pipe_read, &pipe_write)) {
+        __libc_format_log(ANDROID_LOG_ERROR, "libc", "failed to create pipe: %s", strerror(errno));
+        return false;
+      }
+
+      trace_output_fd.store(pipe_write.get());
+
+      siginfo_t siginfo = {};
+      siginfo.si_code = SI_QUEUE;
+      siginfo.si_value.sival_int = ~0;
+      siginfo.si_pid = getpid();
+      siginfo.si_uid = getuid();
+
+      if (syscall(__NR_rt_tgsigqueueinfo, getpid(), tid, DEBUGGER_SIGNAL, &siginfo) != 0) {
+        __libc_format_log(ANDROID_LOG_ERROR, "libc", "failed to send trace signal to %d: %s", tid,
+                          strerror(errno));
+        return false;
+      }
+
+      bool success = forward_output(pipe_read.get(), output_fd);
+      if (success) {
+        // The signaled thread has closed trace_output_fd already.
+        (void)pipe_write.release();
+      } else {
+        trace_output_fd.store(-1);
+      }
+
+      return true;
+    },
+    output_fd.get());
+
+  dump_backtrace_footer(output_fd.get());
+  tombstoned_notify_completion(tombstone_socket.get());
+
+exit:
+  pthread_mutex_unlock(&trace_mutex);
+}
+
+static void crash_handler(siginfo_t* info, ucontext_t* ucontext, void* abort_message) {
+  // Only allow one thread to handle a crash.
+  static pthread_mutex_t crash_mutex = PTHREAD_MUTEX_INITIALIZER;
+  int ret = pthread_mutex_lock(&crash_mutex);
+  if (ret != 0) {
+    __libc_format_log(ANDROID_LOG_INFO, "libc", "pthread_mutex_lock failed: %s", strerror(ret));
+    return;
+  }
+
+  unique_fd tombstone_socket, output_fd;
+  bool tombstoned_connected = tombstoned_connect(getpid(), &tombstone_socket, &output_fd);
+  debuggerd_fallback_tombstone(output_fd.get(), ucontext, info, abort_message);
+  if (tombstoned_connected) {
+    tombstoned_notify_completion(tombstone_socket.get());
+  }
+}
+
+extern "C" void debuggerd_fallback_handler(siginfo_t* info, ucontext_t* ucontext,
+                                           void* abort_message) {
+  if (info->si_signo == DEBUGGER_SIGNAL) {
+    return trace_handler(info, ucontext);
+  } else {
+    return crash_handler(info, ucontext, abort_message);
+  }
 }
diff --git a/debuggerd/handler/debuggerd_fallback_nop.cpp b/debuggerd/handler/debuggerd_fallback_nop.cpp
index 9b3053f..331301f 100644
--- a/debuggerd/handler/debuggerd_fallback_nop.cpp
+++ b/debuggerd/handler/debuggerd_fallback_nop.cpp
@@ -26,10 +26,5 @@
  * SUCH DAMAGE.
  */
 
-#include <stddef.h>
-#include <sys/ucontext.h>
-#include <unistd.h>
-
-extern "C" bool debuggerd_fallback(ucontext_t*, siginfo_t*, void*) {
-  return false;
+extern "C" void debuggerd_fallback_handler(struct siginfo_t*, struct ucontext_t*, void*) {
 }
diff --git a/debuggerd/handler/debuggerd_handler.cpp b/debuggerd/handler/debuggerd_handler.cpp
index 67c26e2..c09c2f3 100644
--- a/debuggerd/handler/debuggerd_handler.cpp
+++ b/debuggerd/handler/debuggerd_handler.cpp
@@ -62,7 +62,7 @@
 
 #define CRASH_DUMP_PATH "/system/bin/" CRASH_DUMP_NAME
 
-extern "C" bool debuggerd_fallback(ucontext_t*, siginfo_t*, void*);
+extern "C" void debuggerd_fallback_handler(siginfo_t*, ucontext_t*, void*);
 
 static debuggerd_callbacks_t g_callbacks;
 
@@ -323,21 +323,11 @@
       fatal_errno("failed to resend signal during crash");
     }
   }
-
-  if (info->si_signo == DEBUGGER_SIGNAL) {
-    pthread_mutex_unlock(&crash_mutex);
-  }
 }
 
 // Handler that does crash dumping by forking and doing the processing in the child.
 // Do this by ptracing the relevant thread, and then execing debuggerd to do the actual dump.
 static void debuggerd_signal_handler(int signal_number, siginfo_t* info, void* context) {
-  int ret = pthread_mutex_lock(&crash_mutex);
-  if (ret != 0) {
-    __libc_format_log(ANDROID_LOG_INFO, "libc", "pthread_mutex_lock failed: %s", strerror(ret));
-    return;
-  }
-
   // It's possible somebody cleared the SA_SIGINFO flag, which would mean
   // our "info" arg holds an undefined value.
   if (!have_siginfo(signal_number)) {
@@ -359,24 +349,29 @@
     // check to allow all si_code values in calls coming from inside the house.
   }
 
-  log_signal_summary(signal_number, info);
-
   void* abort_message = nullptr;
   if (g_callbacks.get_abort_message) {
     abort_message = g_callbacks.get_abort_message();
   }
 
   if (prctl(PR_GET_NO_NEW_PRIVS, 0, 0, 0, 0) == 1) {
-    ucontext_t* ucontext = static_cast<ucontext_t*>(context);
-    if (signal_number == DEBUGGER_SIGNAL || !debuggerd_fallback(ucontext, info, abort_message)) {
-      // The process has NO_NEW_PRIVS enabled, so we can't transition to the crash_dump context.
-      __libc_format_log(ANDROID_LOG_INFO, "libc",
-                        "Suppressing debuggerd output because prctl(PR_GET_NO_NEW_PRIVS)==1");
-    }
+    // This check might be racy if another thread sets NO_NEW_PRIVS, but this should be unlikely,
+    // you can only set NO_NEW_PRIVS to 1, and the effect should be at worst a single missing
+    // ANR trace.
+    debuggerd_fallback_handler(info, static_cast<ucontext_t*>(context), abort_message);
     resend_signal(info, false);
     return;
   }
 
+  // Only allow one thread to handle a signal at a time.
+  int ret = pthread_mutex_lock(&crash_mutex);
+  if (ret != 0) {
+    __libc_format_log(ANDROID_LOG_INFO, "libc", "pthread_mutex_lock failed: %s", strerror(ret));
+    return;
+  }
+
+  log_signal_summary(signal_number, info);
+
   // Populate si_value with the abort message address, if found.
   if (abort_message) {
     info->si_value.sival_ptr = abort_message;
@@ -427,6 +422,11 @@
   }
 
   resend_signal(info, thread_info.crash_dump_started);
+  if (info->si_signo == DEBUGGER_SIGNAL) {
+    // If the signal is fatal, don't unlock the mutex to prevent other crashing threads from
+    // starting to dump right before our death.
+    pthread_mutex_unlock(&crash_mutex);
+  }
 }
 
 void debuggerd_init(debuggerd_callbacks_t* callbacks) {
diff --git a/debuggerd/include/debuggerd/tombstoned.h b/debuggerd/include/debuggerd/tombstoned.h
new file mode 100644
index 0000000..d158d50
--- /dev/null
+++ b/debuggerd/include/debuggerd/tombstoned.h
@@ -0,0 +1,26 @@
+#pragma once
+
+/*
+ * Copyright 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.
+ */
+
+#include <sys/types.h>
+
+#include <android-base/unique_fd.h>
+
+bool tombstoned_connect(pid_t pid, android::base::unique_fd* tombstoned_socket,
+                        android::base::unique_fd* output_fd);
+
+bool tombstoned_notify_completion(int tombstoned_socket);
diff --git a/debuggerd/libdebuggerd/backtrace.cpp b/debuggerd/libdebuggerd/backtrace.cpp
index 0664442..df49aef 100644
--- a/debuggerd/libdebuggerd/backtrace.cpp
+++ b/debuggerd/libdebuggerd/backtrace.cpp
@@ -67,15 +67,15 @@
   _LOG(log, logtype::BACKTRACE, "\n----- end %d -----\n", pid);
 }
 
-static void dump_thread(log_t* log, BacktraceMap* map, pid_t pid, pid_t tid) {
-  char path[PATH_MAX];
-  char threadnamebuf[1024];
-  char* threadname = NULL;
+static void log_thread_name(log_t* log, pid_t tid) {
   FILE* fp;
+  char buf[1024];
+  char path[PATH_MAX];
+  char* threadname = NULL;
 
   snprintf(path, sizeof(path), "/proc/%d/comm", tid);
   if ((fp = fopen(path, "r"))) {
-    threadname = fgets(threadnamebuf, sizeof(threadnamebuf), fp);
+    threadname = fgets(buf, sizeof(buf), fp);
     fclose(fp);
     if (threadname) {
       size_t len = strlen(threadname);
@@ -84,8 +84,11 @@
       }
     }
   }
-
   _LOG(log, logtype::BACKTRACE, "\n\"%s\" sysTid=%d\n", threadname ? threadname : "<unknown>", tid);
+}
+
+static void dump_thread(log_t* log, BacktraceMap* map, pid_t pid, pid_t tid) {
+  log_thread_name(log, tid);
 
   std::unique_ptr<Backtrace> backtrace(Backtrace::Create(pid, tid, map));
   if (backtrace->Unwind(0)) {
@@ -112,6 +115,41 @@
   dump_process_footer(&log, pid);
 }
 
+void dump_backtrace_ucontext(int output_fd, ucontext_t* ucontext) {
+  pid_t pid = getpid();
+  pid_t tid = gettid();
+
+  log_t log;
+  log.tfd = output_fd;
+  log.amfd_data = nullptr;
+
+  log_thread_name(&log, tid);
+
+  std::unique_ptr<Backtrace> backtrace(Backtrace::Create(pid, tid));
+  if (backtrace->Unwind(0, ucontext)) {
+    dump_backtrace_to_log(backtrace.get(), &log, "  ");
+  } else {
+    ALOGE("Unwind failed: tid = %d: %s", tid,
+          backtrace->GetErrorString(backtrace->GetError()).c_str());
+  }
+}
+
+void dump_backtrace_header(int output_fd) {
+  log_t log;
+  log.tfd = output_fd;
+  log.amfd_data = nullptr;
+
+  dump_process_header(&log, getpid());
+}
+
+void dump_backtrace_footer(int output_fd) {
+  log_t log;
+  log.tfd = output_fd;
+  log.amfd_data = nullptr;
+
+  dump_process_footer(&log, getpid());
+}
+
 void dump_backtrace_to_log(Backtrace* backtrace, log_t* log, const char* prefix) {
   for (size_t i = 0; i < backtrace->NumFrames(); i++) {
     _LOG(log, logtype::BACKTRACE, "%s%s\n", prefix, backtrace->FormatFrameData(i).c_str());
diff --git a/debuggerd/libdebuggerd/include/backtrace.h b/debuggerd/libdebuggerd/include/backtrace.h
index acd5eaa..5bfdac8 100644
--- a/debuggerd/libdebuggerd/include/backtrace.h
+++ b/debuggerd/libdebuggerd/include/backtrace.h
@@ -18,6 +18,7 @@
 #define _DEBUGGERD_BACKTRACE_H
 
 #include <sys/types.h>
+#include <sys/ucontext.h>
 
 #include <set>
 #include <string>
@@ -35,4 +36,8 @@
 /* Dumps the backtrace in the backtrace data structure to the log. */
 void dump_backtrace_to_log(Backtrace* backtrace, log_t* log, const char* prefix);
 
+void dump_backtrace_ucontext(int output_fd, ucontext_t* ucontext);
+void dump_backtrace_header(int output_fd);
+void dump_backtrace_footer(int output_fd);
+
 #endif // _DEBUGGERD_BACKTRACE_H
diff --git a/debuggerd/libdebuggerd/include/tombstone.h b/debuggerd/libdebuggerd/include/tombstone.h
index aed71de..8e60278 100644
--- a/debuggerd/libdebuggerd/include/tombstone.h
+++ b/debuggerd/libdebuggerd/include/tombstone.h
@@ -39,7 +39,13 @@
                        const std::set<pid_t>* siblings, uintptr_t abort_msg_address,
                        std::string* amfd_data);
 
-void engrave_tombstone_ucontext(int tombstone_fd, pid_t pid, pid_t tid, uintptr_t abort_msg_address,
-                                siginfo_t* siginfo, ucontext_t* ucontext);
+void engrave_tombstone_ucontext(int tombstone_fd, uintptr_t abort_msg_address, siginfo_t* siginfo,
+                                ucontext_t* ucontext);
+
+// Compatibility shim.
+static void engrave_tombstone_ucontext(int tombstone_fd, pid_t, pid_t, uintptr_t abort_msg_address,
+                                       siginfo_t* siginfo, ucontext_t* ucontext) {
+  engrave_tombstone_ucontext(tombstone_fd, abort_msg_address, siginfo, ucontext);
+}
 
 #endif // _DEBUGGERD_TOMBSTONE_H
diff --git a/debuggerd/libdebuggerd/tombstone.cpp b/debuggerd/libdebuggerd/tombstone.cpp
index 4686bfd..c05ccc3 100644
--- a/debuggerd/libdebuggerd/tombstone.cpp
+++ b/debuggerd/libdebuggerd/tombstone.cpp
@@ -751,8 +751,11 @@
   dump_crash(&log, map, open_files, pid, tid, siblings, abort_msg_address);
 }
 
-void engrave_tombstone_ucontext(int tombstone_fd, pid_t pid, pid_t tid, uintptr_t abort_msg_address,
-                                siginfo_t* siginfo, ucontext_t* ucontext) {
+void engrave_tombstone_ucontext(int tombstone_fd, uintptr_t abort_msg_address, siginfo_t* siginfo,
+                                ucontext_t* ucontext) {
+  pid_t pid = getpid();
+  pid_t tid = gettid();
+
   log_t log;
   log.current_tid = tid;
   log.crashed_tid = tid;
diff --git a/debuggerd/tombstoned_client.cpp b/debuggerd/tombstoned_client.cpp
new file mode 100644
index 0000000..03b4a20
--- /dev/null
+++ b/debuggerd/tombstoned_client.cpp
@@ -0,0 +1,86 @@
+/*
+ * Copyright 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.
+ */
+
+#include "debuggerd/tombstoned.h"
+
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <utility>
+
+#include <android-base/unique_fd.h>
+#include <cutils/sockets.h>
+
+#include "debuggerd/protocol.h"
+#include "debuggerd/util.h"
+#include "private/libc_logging.h"
+
+using android::base::unique_fd;
+
+bool tombstoned_connect(pid_t pid, unique_fd* tombstoned_socket, unique_fd* output_fd) {
+  unique_fd sockfd(socket_local_client(kTombstonedCrashSocketName,
+                                       ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_SEQPACKET));
+  if (sockfd == -1) {
+    __libc_format_log(ANDROID_LOG_ERROR, "libc", "failed to connect to tombstoned: %s",
+                      strerror(errno));
+    return false;
+  }
+
+  TombstonedCrashPacket packet = {};
+  packet.packet_type = CrashPacketType::kDumpRequest;
+  packet.packet.dump_request.pid = pid;
+  if (TEMP_FAILURE_RETRY(write(sockfd, &packet, sizeof(packet))) != sizeof(packet)) {
+    __libc_format_log(ANDROID_LOG_ERROR, "libc", "failed to write DumpRequest packet: %s",
+                      strerror(errno));
+    return false;
+  }
+
+  unique_fd tmp_output_fd;
+  ssize_t rc = recv_fd(sockfd, &packet, sizeof(packet), &tmp_output_fd);
+  if (rc == -1) {
+    __libc_format_log(ANDROID_LOG_ERROR, "libc",
+                      "failed to read response to DumpRequest packet: %s", strerror(errno));
+    return false;
+  } else if (rc != sizeof(packet)) {
+    __libc_format_log(
+      ANDROID_LOG_ERROR, "libc",
+      "received DumpRequest response packet of incorrect length (expected %zu, got %zd)",
+      sizeof(packet), rc);
+    return false;
+  }
+
+  // Make the fd O_APPEND so that our output is guaranteed to be at the end of a file.
+  // (This also makes selinux rules consistent, because selinux distinguishes between writing to
+  // a regular fd, and writing to an fd with O_APPEND).
+  int flags = fcntl(tmp_output_fd.get(), F_GETFL);
+  if (fcntl(tmp_output_fd.get(), F_SETFL, flags | O_APPEND) != 0) {
+    __libc_format_log(ANDROID_LOG_WARN, "libc", "failed to set output fd flags: %s",
+                      strerror(errno));
+  }
+
+  *tombstoned_socket = std::move(sockfd);
+  *output_fd = std::move(tmp_output_fd);
+  return true;
+}
+
+bool tombstoned_notify_completion(int tombstoned_socket) {
+  TombstonedCrashPacket packet = {};
+  packet.packet_type = CrashPacketType::kCompletedDump;
+  if (TEMP_FAILURE_RETRY(write(tombstoned_socket, &packet, sizeof(packet))) != sizeof(packet)) {
+    return false;
+  }
+  return true;
+}
diff --git a/debuggerd/util.cpp b/debuggerd/util.cpp
index 738abdf..4c015d7 100644
--- a/debuggerd/util.cpp
+++ b/debuggerd/util.cpp
@@ -22,8 +22,13 @@
 
 #include <android-base/unique_fd.h>
 #include <cutils/sockets.h>
+#include <debuggerd/protocol.h>
 
-ssize_t send_fd(int sockfd, const void* data, size_t len, android::base::unique_fd fd) {
+#include "private/libc_logging.h"
+
+using android::base::unique_fd;
+
+ssize_t send_fd(int sockfd, const void* data, size_t len, unique_fd fd) {
   char cmsg_buf[CMSG_SPACE(sizeof(int))];
 
   iovec iov = { .iov_base = const_cast<void*>(data), .iov_len = len };
@@ -39,8 +44,7 @@
   return TEMP_FAILURE_RETRY(sendmsg(sockfd, &msg, 0));
 }
 
-ssize_t recv_fd(int sockfd, void* _Nonnull data, size_t len,
-                android::base::unique_fd* _Nullable out_fd) {
+ssize_t recv_fd(int sockfd, void* _Nonnull data, size_t len, unique_fd* _Nullable out_fd) {
   char cmsg_buf[CMSG_SPACE(sizeof(int))];
 
   iovec iov = { .iov_base = const_cast<void*>(data), .iov_len = len };
@@ -61,7 +65,7 @@
     return -1;
   }
 
-  android::base::unique_fd fd;
+  unique_fd fd;
   bool received_fd = msg.msg_controllen == sizeof(cmsg_buf);
   if (received_fd) {
     fd.reset(*reinterpret_cast<int*>(CMSG_DATA(cmsg)));
@@ -85,7 +89,7 @@
   return result;
 }
 
-bool Pipe(android::base::unique_fd* read, android::base::unique_fd* write) {
+bool Pipe(unique_fd* read, unique_fd* write) {
   int pipefds[2];
   if (pipe(pipefds) != 0) {
     return false;
diff --git a/fingerprintd/FingerprintDaemonProxy.cpp b/fingerprintd/FingerprintDaemonProxy.cpp
index 1c7da30..b3c0cd7 100644
--- a/fingerprintd/FingerprintDaemonProxy.cpp
+++ b/fingerprintd/FingerprintDaemonProxy.cpp
@@ -31,7 +31,7 @@
 FingerprintDaemonProxy* FingerprintDaemonProxy::sInstance = NULL;
 
 // Supported fingerprint HAL version
-static const uint16_t kVersion = HARDWARE_MODULE_API_VERSION(2, 0);
+static const uint16_t kVersion = HARDWARE_MODULE_API_VERSION(2, 1);
 
 FingerprintDaemonProxy::FingerprintDaemonProxy() : mModule(NULL), mDevice(NULL), mCallback(NULL) {
 
diff --git a/gatekeeperd/gatekeeperd.cpp b/gatekeeperd/gatekeeperd.cpp
index d4a92e5..96bda07 100644
--- a/gatekeeperd/gatekeeperd.cpp
+++ b/gatekeeperd/gatekeeperd.cpp
@@ -166,7 +166,14 @@
                     enrolled_password_handle, enrolled_password_handle_length);
         }
 
-        if (ret == 0) {
+        if (ret == GATEKEEPER_RESPONSE_OK && (*enrolled_password_handle == nullptr ||
+            *enrolled_password_handle_length != sizeof(password_handle_t))) {
+            ret = GATEKEEPER_RESPONSE_ERROR;
+            ALOGE("HAL: password_handle=%p size_of_handle=%" PRIu32 "\n",
+                  *enrolled_password_handle, *enrolled_password_handle_length);
+        }
+
+        if (ret == GATEKEEPER_RESPONSE_OK) {
             gatekeeper::password_handle_t *handle =
                     reinterpret_cast<gatekeeper::password_handle_t *>(*enrolled_password_handle);
             store_sid(uid, handle->user_id);
diff --git a/healthd/Android.mk b/healthd/Android.mk
index 7c5e35b..b292725 100644
--- a/healthd/Android.mk
+++ b/healthd/Android.mk
@@ -21,6 +21,10 @@
 include $(BUILD_STATIC_LIBRARY)
 
 include $(CLEAR_VARS)
+ifeq ($(strip $(BOARD_CHARGER_ENABLE_SUSPEND)),true)
+LOCAL_CFLAGS += -DCHARGER_ENABLE_SUSPEND
+LOCAL_SHARED_LIBRARIES += libsuspend
+endif
 LOCAL_SRC_FILES := \
     healthd_mode_android.cpp \
     healthd_mode_charger.cpp \
@@ -90,6 +94,14 @@
 
 LOCAL_C_INCLUDES := bootable/recovery $(LOCAL_PATH)/include
 
+ifneq ($(BOARD_PERIODIC_CHORES_INTERVAL_FAST),)
+LOCAL_CFLAGS += -DBOARD_PERIODIC_CHORES_INTERVAL_FAST=$(BOARD_PERIODIC_CHORES_INTERVAL_FAST)
+endif
+
+ifneq ($(BOARD_PERIODIC_CHORES_INTERVAL_SLOW),)
+LOCAL_CFLAGS += -DBOARD_PERIODIC_CHORES_INTERVAL_SLOW=$(BOARD_PERIODIC_CHORES_INTERVAL_SLOW)
+endif
+
 LOCAL_STATIC_LIBRARIES := \
     libhealthd_internal \
     libbatterymonitor \
diff --git a/healthd/healthd.cpp b/healthd/healthd.cpp
index 20a6bf6..aa6735d 100644
--- a/healthd/healthd.cpp
+++ b/healthd/healthd.cpp
@@ -35,9 +35,19 @@
 
 using namespace android;
 
-// Periodic chores intervals in seconds
-#define DEFAULT_PERIODIC_CHORES_INTERVAL_FAST (60 * 1)
-#define DEFAULT_PERIODIC_CHORES_INTERVAL_SLOW (60 * 10)
+#ifndef BOARD_PERIODIC_CHORES_INTERVAL_FAST
+  // Periodic chores fast interval in seconds
+  #define DEFAULT_PERIODIC_CHORES_INTERVAL_FAST (60 * 1)
+#else
+  #define DEFAULT_PERIODIC_CHORES_INTERVAL_FAST (BOARD_PERIODIC_CHORES_INTERVAL_FAST)
+#endif
+
+#ifndef BOARD_PERIODIC_CHORES_INTERVAL_SLOW
+  // Periodic chores fast interval in seconds
+  #define DEFAULT_PERIODIC_CHORES_INTERVAL_SLOW (60 * 10)
+#else
+  #define DEFAULT_PERIODIC_CHORES_INTERVAL_SLOW (BOARD_PERIODIC_CHORES_INTERVAL_SLOW)
+#endif
 
 static struct healthd_config healthd_config = {
     .periodic_chores_interval_fast = DEFAULT_PERIODIC_CHORES_INTERVAL_FAST,
@@ -143,10 +153,14 @@
     struct android::BatteryProperties* /*props*/) {
 }
 
-int healthd_register_event(int fd, void (*handler)(uint32_t)) {
+int healthd_register_event(int fd, void (*handler)(uint32_t), EventWakeup wakeup) {
     struct epoll_event ev;
 
-    ev.events = EPOLLIN | EPOLLWAKEUP;
+    ev.events = EPOLLIN;
+
+    if (wakeup == EVENT_WAKEUP_FD)
+        ev.events |= EPOLLWAKEUP;
+
     ev.data.ptr = (void *)handler;
     if (epoll_ctl(epollfd, EPOLL_CTL_ADD, fd, &ev) == -1) {
         KLOG_ERROR(LOG_TAG,
@@ -252,7 +266,7 @@
     }
 
     fcntl(uevent_fd, F_SETFL, O_NONBLOCK);
-    if (healthd_register_event(uevent_fd, uevent_event))
+    if (healthd_register_event(uevent_fd, uevent_event, EVENT_WAKEUP_FD))
         KLOG_ERROR(LOG_TAG,
                    "register for uevent events failed\n");
 }
@@ -275,7 +289,7 @@
         return;
     }
 
-    if (healthd_register_event(wakealarm_fd, wakealarm_event))
+    if (healthd_register_event(wakealarm_fd, wakealarm_event, EVENT_WAKEUP_FD))
         KLOG_ERROR(LOG_TAG,
                    "Registration of wakealarm event failed\n");
 
@@ -283,17 +297,22 @@
 }
 
 static void healthd_mainloop(void) {
+    int nevents = 0;
     while (1) {
         struct epoll_event events[eventct];
-        int nevents;
         int timeout = awake_poll_interval;
         int mode_timeout;
 
+        /* Don't wait for first timer timeout to run periodic chores */
+        if (!nevents)
+            periodic_chores();
+
+        healthd_mode_ops->heartbeat();
+
         mode_timeout = healthd_mode_ops->preparetowait();
         if (timeout < 0 || (mode_timeout > 0 && mode_timeout < timeout))
             timeout = mode_timeout;
         nevents = epoll_wait(epollfd, events, eventct, timeout);
-
         if (nevents == -1) {
             if (errno == EINTR)
                 continue;
@@ -305,11 +324,6 @@
             if (events[n].data.ptr)
                 (*(void (*)(int))events[n].data.ptr)(events[n].events);
         }
-
-        if (!nevents)
-            periodic_chores();
-
-        healthd_mode_ops->heartbeat();
     }
 
     return;
diff --git a/healthd/healthd_mode_charger.cpp b/healthd/healthd_mode_charger.cpp
index 2f69372..91774c6 100644
--- a/healthd/healthd_mode_charger.cpp
+++ b/healthd/healthd_mode_charger.cpp
@@ -343,14 +343,19 @@
 
 static void draw_percent(const animation& anim)
 {
-    if (anim.cur_level <= 0 || anim.cur_status != BATTERY_STATUS_CHARGING) return;
+    int cur_level = anim.cur_level;
+    if (anim.cur_status == BATTERY_STATUS_FULL) {
+        cur_level = 100;
+    }
+
+    if (cur_level <= 0) return;
 
     const animation::text_field& field = anim.text_percent;
     if (field.font == nullptr || field.font->char_width == 0 || field.font->char_height == 0) {
         return;
     }
 
-    std::string str = base::StringPrintf("%d%%", anim.cur_level);
+    std::string str = base::StringPrintf("%d%%", cur_level);
 
     int x, y;
     determine_xy(field, str.size(), &x, &y);
@@ -840,7 +845,7 @@
                             std::placeholders::_2));
     if (!ret) {
         epollfd = ev_get_epollfd();
-        healthd_register_event(epollfd, charger_event_handler);
+        healthd_register_event(epollfd, charger_event_handler, EVENT_WAKEUP_FD);
     }
 
     struct animation* anim = init_animation();
diff --git a/healthd/include/healthd/healthd.h b/healthd/include/healthd/healthd.h
index 34ea55f..17efbd6 100644
--- a/healthd/include/healthd/healthd.h
+++ b/healthd/include/healthd/healthd.h
@@ -73,9 +73,14 @@
     bool (*screen_on)(android::BatteryProperties *props);
 };
 
+enum EventWakeup {
+    EVENT_NO_WAKEUP_FD,
+    EVENT_WAKEUP_FD,
+};
+
 // Global helper functions
 
-int healthd_register_event(int fd, void (*handler)(uint32_t));
+int healthd_register_event(int fd, void (*handler)(uint32_t), EventWakeup wakeup = EVENT_NO_WAKEUP_FD);
 void healthd_battery_update();
 android::status_t healthd_get_property(int id,
     struct android::BatteryProperty *val);
diff --git a/include/system/qemu_pipe.h b/include/system/qemu_pipe.h
new file mode 100644
index 0000000..af25079
--- /dev/null
+++ b/include/system/qemu_pipe.h
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2011 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 ANDROID_INCLUDE_SYSTEM_QEMU_PIPE_H
+#define ANDROID_INCLUDE_SYSTEM_QEMU_PIPE_H
+
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <errno.h>
+
+// Define QEMU_PIPE_DEBUG if you want to print error messages when an error
+// occurs during pipe operations. The macro should simply take a printf-style
+// formatting string followed by optional arguments.
+#ifndef QEMU_PIPE_DEBUG
+#  define  QEMU_PIPE_DEBUG(...)   (void)0
+#endif
+
+// Try to open a new Qemu fast-pipe. This function returns a file descriptor
+// that can be used to communicate with a named service managed by the
+// emulator.
+//
+// This file descriptor can be used as a standard pipe/socket descriptor.
+//
+// 'pipeName' is the name of the emulator service you want to connect to,
+// and must begin with 'pipe:' (e.g. 'pipe:camera' or 'pipe:opengles').
+//
+// On success, return a valid file descriptor, or -1/errno on failure. E.g.:
+//
+// EINVAL  -> unknown/unsupported pipeName
+// ENOSYS  -> fast pipes not available in this system.
+//
+// ENOSYS should never happen, except if you're trying to run within a
+// misconfigured emulator.
+//
+// You should be able to open several pipes to the same pipe service,
+// except for a few special cases (e.g. GSM modem), where EBUSY will be
+// returned if more than one client tries to connect to it.
+static __inline__ int qemu_pipe_open(const char* pipeName) {
+    // Sanity check.
+    if (!pipeName || memcmp(pipeName, "pipe:", 5) != 0) {
+        errno = EINVAL;
+        return -1;
+    }
+
+    int fd = TEMP_FAILURE_RETRY(open("/dev/qemu_pipe", O_RDWR));
+    if (fd < 0) {
+        QEMU_PIPE_DEBUG("%s: Could not open /dev/qemu_pipe: %s", __FUNCTION__,
+                        strerror(errno));
+        return -1;
+    }
+
+    // Write the pipe name, *including* the trailing zero which is necessary.
+    size_t pipeNameLen = strlen(pipeName);
+    ssize_t ret = TEMP_FAILURE_RETRY(write(fd, pipeName, pipeNameLen + 1U));
+    if (ret != (ssize_t)pipeNameLen + 1) {
+        QEMU_PIPE_DEBUG("%s: Could not connect to %s pipe service: %s",
+                        __FUNCTION__, pipeName, strerror(errno));
+        if (ret == 0) {
+            errno = ECONNRESET;
+        } else if (ret > 0) {
+            errno = EINVAL;
+        }
+        return -1;
+    }
+    return fd;
+}
+
+// Send a framed message |buff| of |len| bytes through the |fd| descriptor.
+// This really adds a 4-hexchar prefix describing the payload size.
+// Returns 0 on success, and -1 on error.
+static int __inline__ qemu_pipe_frame_send(int fd,
+                                           const void* buff,
+                                           size_t len) {
+    char header[5];
+    snprintf(header, sizeof(header), "%04zx", len);
+    ssize_t ret = TEMP_FAILURE_RETRY(write(fd, header, 4));
+    if (ret != 4) {
+        QEMU_PIPE_DEBUG("Can't write qemud frame header: %s", strerror(errno));
+        return -1;
+    }
+    ret = TEMP_FAILURE_RETRY(write(fd, buff, len));
+    if (ret != (ssize_t)len) {
+        QEMU_PIPE_DEBUG("Can't write qemud frame payload: %s", strerror(errno));
+        return -1;
+    }
+    return 0;
+}
+
+// Read a frame message from |fd|, and store it into |buff| of |len| bytes.
+// If the framed message is larger than |len|, then this returns -1 and the
+// content is lost. Otherwise, this returns the size of the message. NOTE:
+// empty messages are possible in a framed wire protocol and do not mean
+// end-of-stream.
+static int __inline__ qemu_pipe_frame_recv(int fd, void* buff, size_t len) {
+    char header[5];
+    ssize_t ret = TEMP_FAILURE_RETRY(read(fd, header, 4));
+    if (ret != 4) {
+        QEMU_PIPE_DEBUG("Can't read qemud frame header: %s", strerror(errno));
+        return -1;
+    }
+    header[4] = '\0';
+    size_t size;
+    if (sscanf(header, "%04zx", &size) != 1) {
+        QEMU_PIPE_DEBUG("Malformed qemud frame header: [%.*s]", 4, header);
+        return -1;
+    }
+    if (size > len) {
+        QEMU_PIPE_DEBUG("Oversized qemud frame (% bytes, expected <= %)", size,
+                        len);
+        return -1;
+    }
+    ret = TEMP_FAILURE_RETRY(read(fd, buff, size));
+    if (ret != (ssize_t)size) {
+        QEMU_PIPE_DEBUG("Could not read qemud frame payload: %s",
+                        strerror(errno));
+        return -1;
+    }
+    return size;
+}
+
+#endif /* ANDROID_INCLUDE_HARDWARE_QEMUD_PIPE_H */
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/init.cpp b/init/init.cpp
index 81f228c..5ab421b 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -715,6 +715,44 @@
     }
 }
 
+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; }
@@ -734,8 +772,32 @@
     // 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";
 
+    // Determine the highest policy language version supported by the kernel
+    set_selinuxmnt("/sys/fs/selinux");
+    int max_policy_version = security_policyvers();
+    if (max_policy_version == -1) {
+        PLOG(ERROR) << "Failed to determine highest policy version supported by kernel";
+        return false;
+    }
+
     // We store the output of the compilation on /dev because this is the most convenient tmpfs
     // storage mount available this early in the boot sequence.
     char compiled_sepolicy[] = "/dev/sepolicy.XXXXXX";
@@ -745,14 +807,20 @@
         return false;
     }
 
-    const char* compile_args[] = {"/system/bin/secilc", plat_policy_cil_file, "-M", "true", "-c",
-                                  "30",  // TODO: pass in SELinux policy version from build system
-                                  "/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
-                                  nullptr};
+    // clang-format off
+    const char* compile_args[] = {
+        "/system/bin/secilc",
+        plat_policy_cil_file,
+        "-M", "true",
+        // Target the highest policy language version supported by the kernel
+        "-c", std::to_string(max_policy_version).c_str(),
+        "/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
+        nullptr};
+    // clang-format on
 
     if (!fork_execve_and_wait_for_completion(compile_args[0], (char**)compile_args, (char**)ENV)) {
         unlink(compiled_sepolicy);
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/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/libsuspend/autosuspend_wakeup_count.c b/libsuspend/autosuspend_wakeup_count.c
index 2da204a..4dedf7f 100644
--- a/libsuspend/autosuspend_wakeup_count.c
+++ b/libsuspend/autosuspend_wakeup_count.c
@@ -24,7 +24,6 @@
 #include <stddef.h>
 #include <stdbool.h>
 #include <string.h>
-#include <sys/param.h>
 #include <sys/stat.h>
 #include <sys/types.h>
 #include <unistd.h>
@@ -36,24 +35,12 @@
 #define SYS_POWER_STATE "/sys/power/state"
 #define SYS_POWER_WAKEUP_COUNT "/sys/power/wakeup_count"
 
-#define BASE_SLEEP_TIME 100000
-
 static int state_fd;
 static int wakeup_count_fd;
 static pthread_t suspend_thread;
 static sem_t suspend_lockout;
 static const char *sleep_state = "mem";
 static void (*wakeup_func)(bool success) = NULL;
-static int sleep_time = BASE_SLEEP_TIME;
-
-static void update_sleep_time(bool success) {
-    if (success) {
-        sleep_time = BASE_SLEEP_TIME;
-        return;
-    }
-    // double sleep time after each failure up to one minute
-    sleep_time = MIN(sleep_time * 2, 60000000);
-}
 
 static void *suspend_thread_func(void *arg __attribute__((unused)))
 {
@@ -61,12 +48,10 @@
     char wakeup_count[20];
     int wakeup_count_len;
     int ret;
-    bool success = true;
+    bool success;
 
     while (1) {
-        update_sleep_time(success);
-        usleep(sleep_time);
-        success = false;
+        usleep(100000);
         ALOGV("%s: read wakeup_count\n", __func__);
         lseek(wakeup_count_fd, 0, SEEK_SET);
         wakeup_count_len = TEMP_FAILURE_RETRY(read(wakeup_count_fd, wakeup_count,
@@ -90,6 +75,7 @@
             continue;
         }
 
+        success = true;
         ALOGV("%s: write %*s to wakeup_count\n", __func__, wakeup_count_len, wakeup_count);
         ret = TEMP_FAILURE_RETRY(write(wakeup_count_fd, wakeup_count, wakeup_count_len));
         if (ret < 0) {
@@ -98,8 +84,8 @@
         } else {
             ALOGV("%s: write %s to %s\n", __func__, sleep_state, SYS_POWER_STATE);
             ret = TEMP_FAILURE_RETRY(write(state_fd, sleep_state, strlen(sleep_state)));
-            if (ret >= 0) {
-                success = true;
+            if (ret < 0) {
+                success = false;
             }
             void (*func)(bool success) = wakeup_func;
             if (func != NULL) {
diff --git a/logcat/logcat.cpp b/logcat/logcat.cpp
index 3cd36f9..4da5030 100644
--- a/logcat/logcat.cpp
+++ b/logcat/logcat.cpp
@@ -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 };
@@ -738,7 +738,6 @@
     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;
@@ -1117,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;
@@ -1134,7 +1133,7 @@
                         dev->next = d;
                         dev = d;
                     } else {
-                        devices = dev = d;
+                        context->devices = dev = d;
                     }
                     context->devCount++;
                 }
@@ -1287,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);
@@ -1384,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 {
@@ -1595,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) {
@@ -1617,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:
@@ -1790,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/qemu_pipe/Android.mk b/qemu_pipe/Android.mk
deleted file mode 100644
index 6e0144c..0000000
--- a/qemu_pipe/Android.mk
+++ /dev/null
@@ -1,19 +0,0 @@
-# Copyright 2011 The Android Open Source Project
-
-LOCAL_PATH:= $(call my-dir)
-
-common_static_libraries := \
-    libbase
-include $(CLEAR_VARS)
-LOCAL_CLANG := true
-LOCAL_SANITIZE := integer
-LOCAL_SRC_FILES:= \
-    qemu_pipe.cpp
-LOCAL_C_INCLUDES := \
-    $(LOCAL_PATH)/include \
-    system/base/include
-LOCAL_MODULE:= libqemu_pipe
-LOCAL_STATIC_LIBRARIES := $(common_static_libraries)
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
-LOCAL_CFLAGS := -Werror
-include $(BUILD_STATIC_LIBRARY)
diff --git a/qemu_pipe/include/qemu_pipe.h b/qemu_pipe/include/qemu_pipe.h
deleted file mode 100644
index 0987498..0000000
--- a/qemu_pipe/include/qemu_pipe.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2011 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 ANDROID_CORE_INCLUDE_QEMU_PIPE_H
-#define ANDROID_CORE_INCLUDE_QEMU_PIPE_H
-
-#include <stddef.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-// Try to open a new Qemu fast-pipe. This function returns a file descriptor
-// that can be used to communicate with a named service managed by the
-// emulator.
-//
-// This file descriptor can be used as a standard pipe/socket descriptor.
-//
-// 'pipeName' is the name of the emulator service you want to connect to,
-// and should begin with 'pipe:' (e.g. 'pipe:camera' or 'pipe:opengles').
-// For backward compatibility, the 'pipe:' prefix can be omitted, and in
-// that case, qemu_pipe_open will add it for you.
-
-// On success, return a valid file descriptor, or -1/errno on failure. E.g.:
-//
-// EINVAL  -> unknown/unsupported pipeName
-// ENOSYS  -> fast pipes not available in this system.
-//
-// ENOSYS should never happen, except if you're trying to run within a
-// misconfigured emulator.
-//
-// You should be able to open several pipes to the same pipe service,
-// except for a few special cases (e.g. GSM modem), where EBUSY will be
-// returned if more than one client tries to connect to it.
-int qemu_pipe_open(const char* pipeName);
-
-// Send a framed message |buff| of |len| bytes through the |fd| descriptor.
-// This really adds a 4-hexchar prefix describing the payload size.
-// Returns 0 on success, and -1 on error.
-int qemu_pipe_frame_send(int fd, const void* buff, size_t len);
-
-// Read a frame message from |fd|, and store it into |buff| of |len| bytes.
-// If the framed message is larger than |len|, then this returns -1 and the
-// content is lost. Otherwise, this returns the size of the message. NOTE:
-// empty messages are possible in a framed wire protocol and do not mean
-// end-of-stream.
-int qemu_pipe_frame_recv(int fd, void* buff, size_t len);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* ANDROID_CORE_INCLUDE_QEMU_PIPE_H */
diff --git a/qemu_pipe/qemu_pipe.cpp b/qemu_pipe/qemu_pipe.cpp
deleted file mode 100644
index beeccb0..0000000
--- a/qemu_pipe/qemu_pipe.cpp
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "qemu_pipe.h"
-
-#include <unistd.h>
-#include <fcntl.h>
-#include <string.h>
-#include <errno.h>
-#include <stdio.h>
-
-#include <android-base/file.h>
-
-using android::base::ReadFully;
-using android::base::WriteFully;
-
-// Define QEMU_PIPE_DEBUG if you want to print error messages when an error
-// occurs during pipe operations. The macro should simply take a printf-style
-// formatting string followed by optional arguments.
-#ifndef QEMU_PIPE_DEBUG
-#  define  QEMU_PIPE_DEBUG(...)   (void)0
-#endif
-
-int qemu_pipe_open(const char* pipeName) {
-    // Sanity check.
-    if (!pipeName) {
-        errno = EINVAL;
-        return -1;
-    }
-
-    int fd = TEMP_FAILURE_RETRY(open("/dev/qemu_pipe", O_RDWR));
-    if (fd < 0) {
-        QEMU_PIPE_DEBUG("%s: Could not open /dev/qemu_pipe: %s", __FUNCTION__,
-                        strerror(errno));
-        return -1;
-    }
-
-    // Write the pipe name, *including* the trailing zero which is necessary.
-    size_t pipeNameLen = strlen(pipeName);
-    if (WriteFully(fd, pipeName, pipeNameLen + 1U)) {
-        return fd;
-    }
-
-    // now, add 'pipe:' prefix and try again
-    // Note: host side will wait for the trailing '\0' to start
-    // service lookup.
-    const char pipe_prefix[] = "pipe:";
-    if (WriteFully(fd, pipe_prefix, strlen(pipe_prefix)) &&
-            WriteFully(fd, pipeName, pipeNameLen + 1U)) {
-        return fd;
-    }
-    QEMU_PIPE_DEBUG("%s: Could not write to %s pipe service: %s",
-            __FUNCTION__, pipeName, strerror(errno));
-    close(fd);
-    return -1;
-}
-
-int qemu_pipe_frame_send(int fd, const void* buff, size_t len) {
-    char header[5];
-    snprintf(header, sizeof(header), "%04zx", len);
-    if (!WriteFully(fd, header, 4)) {
-        QEMU_PIPE_DEBUG("Can't write qemud frame header: %s", strerror(errno));
-        return -1;
-    }
-    if (!WriteFully(fd, buff, len)) {
-        QEMU_PIPE_DEBUG("Can't write qemud frame payload: %s", strerror(errno));
-        return -1;
-    }
-    return 0;
-}
-
-int qemu_pipe_frame_recv(int fd, void* buff, size_t len) {
-    char header[5];
-    if (!ReadFully(fd, header, 4)) {
-        QEMU_PIPE_DEBUG("Can't read qemud frame header: %s", strerror(errno));
-        return -1;
-    }
-    header[4] = '\0';
-    size_t size;
-    if (sscanf(header, "%04zx", &size) != 1) {
-        QEMU_PIPE_DEBUG("Malformed qemud frame header: [%.*s]", 4, header);
-        return -1;
-    }
-    if (size > len) {
-        QEMU_PIPE_DEBUG("Oversized qemud frame (% bytes, expected <= %)", size,
-                        len);
-        return -1;
-    }
-    if (!ReadFully(fd, buff, size)) {
-        QEMU_PIPE_DEBUG("Could not read qemud frame payload: %s",
-                        strerror(errno));
-        return -1;
-    }
-    return size;
-}
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 757e1ff..4a91189 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
 
@@ -490,6 +493,13 @@
     # Set indication (checked by vold) that we have finished this action
     #setprop vold.post_fs_data_done 1
 
+# This trigger will be triggered before 'zygote-start' since there is no zygote-start defined in
+# current init.rc. It is recommended to put unnecessary data/ initialization from post-fs-data
+# to start-zygote to unblock zygote start.
+on zygote-start && property:ro.crypto.state=encrypted && property:ro.crypto.type=file
+   start netd
+   start zygote
+
 on boot
     # basic network init
     ifup lo
@@ -564,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