Merge "Address old review comments in adb_auth_host.cpp."
diff --git a/adb/Android.mk b/adb/Android.mk
index 6188184..0babf1d 100644
--- a/adb/Android.mk
+++ b/adb/Android.mk
@@ -319,6 +319,7 @@
 LOCAL_C_INCLUDES += system/extras/ext4_utils
 
 LOCAL_SANITIZE := $(adb_target_sanitize)
+LOCAL_STRIP_MODULE := keep_symbols
 LOCAL_STATIC_LIBRARIES := \
     libadbd \
     libbase \
@@ -333,6 +334,7 @@
     libbase \
     libcrypto_utils_static \
     libcrypto_static \
-    libminijail
+    libminijail \
+    libdebuggerd_client \
 
 include $(BUILD_EXECUTABLE)
diff --git a/adb/daemon/main.cpp b/adb/daemon/main.cpp
index 916bedf..b0a0162 100644
--- a/adb/daemon/main.cpp
+++ b/adb/daemon/main.cpp
@@ -32,6 +32,7 @@
 #include <libminijail.h>
 
 #include "cutils/properties.h"
+#include "debuggerd/client.h"
 #include "private/android_filesystem_config.h"
 #include "selinux/android.h"
 
@@ -247,6 +248,7 @@
 
     close_stdin();
 
+    debuggerd_init(nullptr);
     adb_trace_init(argv);
 
     D("Handling main()");
diff --git a/adb/shell_service.cpp b/adb/shell_service.cpp
index b038fda..10b2502 100644
--- a/adb/shell_service.cpp
+++ b/adb/shell_service.cpp
@@ -160,9 +160,14 @@
     pid_t pid() const { return pid_; }
 
     // Sets up FDs, forks a subprocess, starts the subprocess manager thread,
-    // and exec's the child. Returns false on failure.
+    // and exec's the child. Returns false and sets error on failure.
     bool ForkAndExec(std::string* _Nonnull error);
 
+    // Start the subprocess manager thread. Consumes the subprocess, regardless of success.
+    // Returns false and sets error on failure.
+    static bool StartThread(std::unique_ptr<Subprocess> subprocess,
+                            std::string* _Nonnull error);
+
   private:
     // Opens the file at |pts_name|.
     int OpenPtyChildFd(const char* pts_name, unique_fd* error_sfd);
@@ -390,14 +395,19 @@
         }
     }
 
-    if (!adb_thread_create(ThreadHandler, this)) {
+    D("subprocess parent: completed");
+    return true;
+}
+
+bool Subprocess::StartThread(std::unique_ptr<Subprocess> subprocess, std::string* error) {
+    Subprocess* raw = subprocess.release();
+    if (!adb_thread_create(ThreadHandler, raw)) {
         *error =
             android::base::StringPrintf("failed to create subprocess thread: %s", strerror(errno));
-        kill(pid_, SIGKILL);
+        kill(raw->pid_, SIGKILL);
         return false;
     }
 
-    D("subprocess parent: completed");
     return true;
 }
 
@@ -441,6 +451,7 @@
     adb_thread_setname(android::base::StringPrintf(
             "shell srvc %d", subprocess->local_socket_fd()));
 
+    D("passing data streams for PID %d", subprocess->pid());
     subprocess->PassDataStreams();
 
     D("deleting Subprocess for PID %d", subprocess->pid());
@@ -733,7 +744,7 @@
       protocol == SubprocessProtocol::kNone ? "none" : "shell",
       terminal_type, name);
 
-    Subprocess* subprocess = new Subprocess(name, terminal_type, type, protocol);
+    auto subprocess = std::make_unique<Subprocess>(name, terminal_type, type, protocol);
     if (!subprocess) {
         LOG(ERROR) << "failed to allocate new subprocess";
         return ReportError(protocol, "failed to allocate new subprocess");
@@ -742,11 +753,17 @@
     std::string error;
     if (!subprocess->ForkAndExec(&error)) {
         LOG(ERROR) << "failed to start subprocess: " << error;
-        delete subprocess;
         return ReportError(protocol, error);
     }
 
-    D("subprocess creation successful: local_socket_fd=%d, pid=%d",
-      subprocess->local_socket_fd(), subprocess->pid());
-    return subprocess->local_socket_fd();
+    unique_fd local_socket(dup(subprocess->local_socket_fd()));
+    D("subprocess creation successful: local_socket_fd=%d, pid=%d", local_socket.get(),
+      subprocess->pid());
+
+    if (!Subprocess::StartThread(std::move(subprocess), &error)) {
+        LOG(ERROR) << "failed to start subprocess management thread: " << error;
+        return ReportError(protocol, error);
+    }
+
+    return local_socket.release();
 }
diff --git a/adb/transport_local.cpp b/adb/transport_local.cpp
index 31b5ad6..d918cc7 100644
--- a/adb/transport_local.cpp
+++ b/adb/transport_local.cpp
@@ -235,16 +235,20 @@
 /* This is relevant only for ADB daemon running inside the emulator. */
 /*
  * Redefine open and write for qemu_pipe.h that contains inlined references
- * to those routines. We will redifine them back after qemu_pipe.h inclusion.
+ * to those routines. We will redefine them back after qemu_pipe.h inclusion.
  */
 #undef open
+#undef read
 #undef write
 #define open    adb_open
+#define read    adb_read
 #define write   adb_write
-#include <hardware/qemu_pipe.h>
+#include <system/qemu_pipe.h>
 #undef open
+#undef read
 #undef write
 #define open    ___xxx_open
+#define read    ___xxx_read
 #define write   ___xxx_write
 
 /* A worker thread that monitors host connections, and registers a transport for
@@ -292,7 +296,7 @@
     D("transport: qemu_socket_thread() starting");
 
     /* adb QEMUD service connection request. */
-    snprintf(con_name, sizeof(con_name), "qemud:adb:%d", port);
+    snprintf(con_name, sizeof(con_name), "pipe:qemud:adb:%d", port);
 
     /* Connect to the adb QEMUD service. */
     fd = qemu_pipe_open(con_name);
diff --git a/base/logging.cpp b/base/logging.cpp
index 1741871..769c266 100644
--- a/base/logging.cpp
+++ b/base/logging.cpp
@@ -21,6 +21,7 @@
 #include "android-base/logging.h"
 
 #include <libgen.h>
+#include <time.h>
 
 // For getprogname(3) or program_invocation_short_name.
 #if defined(__ANDROID__) || defined(__APPLE__)
@@ -186,12 +187,24 @@
 
 void StderrLogger(LogId, LogSeverity severity, const char*, const char* file,
                   unsigned int line, const char* message) {
+  struct tm now;
+  time_t t = time(nullptr);
+
+#if defined(_WIN32)
+  localtime_s(&now, &t);
+#else
+  localtime_r(&t, &now);
+#endif
+
+  char timestamp[32];
+  strftime(timestamp, sizeof(timestamp), "%m-%d %H:%M:%S", &now);
+
   static const char log_characters[] = "VDIWEF";
   static_assert(arraysize(log_characters) - 1 == FATAL + 1,
                 "Mismatch in size of log_characters and values in LogSeverity");
   char severity_char = log_characters[severity];
-  fprintf(stderr, "%s %c %5d %5d %s:%u] %s\n", ProgramInvocationName(),
-          severity_char, getpid(), GetThreadId(), file, line, message);
+  fprintf(stderr, "%s %c %s %5d %5d %s:%u] %s\n", ProgramInvocationName(),
+          severity_char, timestamp, getpid(), GetThreadId(), file, line, message);
 }
 
 
diff --git a/debuggerd/Android.bp b/debuggerd/Android.bp
new file mode 100644
index 0000000..8a63f3f
--- /dev/null
+++ b/debuggerd/Android.bp
@@ -0,0 +1,19 @@
+cc_library_static {
+  name: "libdebuggerd_client",
+  srcs: ["client/debuggerd_client.cpp"],
+
+  cflags: [
+    "-Wall",
+    "-Wextra",
+    "-Werror",
+    "-Os",
+  ],
+
+  local_include_dirs: ["include"],
+  export_include_dirs: ["include"],
+
+  // libdebuggerd_client gets async signal safe logging via libc_logging,
+  // which defines its interface in bionic private headers.
+  include_dirs: ["bionic/libc"],
+  static_libs: ["libc_logging"],
+}
diff --git a/debuggerd/Android.mk b/debuggerd/Android.soong.mk
similarity index 73%
rename from debuggerd/Android.mk
rename to debuggerd/Android.soong.mk
index 9ce94c5..19c7298 100644
--- a/debuggerd/Android.mk
+++ b/debuggerd/Android.soong.mk
@@ -8,6 +8,10 @@
     -Wunused \
     -Werror \
 
+ifeq ($(TARGET_IS_64_BIT),true)
+common_cppflags += -DTARGET_IS_64_BIT
+endif
+
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES:= \
@@ -26,15 +30,12 @@
 LOCAL_SRC_FILES_x86    := x86/machine.cpp
 LOCAL_SRC_FILES_x86_64 := x86_64/machine.cpp
 
+LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
 LOCAL_CPPFLAGS := $(common_cppflags)
 
 LOCAL_INIT_RC_32 := debuggerd.rc
 LOCAL_INIT_RC_64 := debuggerd64.rc
 
-ifeq ($(TARGET_IS_64_BIT),true)
-LOCAL_CPPFLAGS += -DTARGET_IS_64_BIT
-endif
-
 LOCAL_SHARED_LIBRARIES := \
     libbacktrace \
     libbase \
@@ -51,7 +52,7 @@
 
 include $(BUILD_EXECUTABLE)
 
-
+crasher_cppflags := $(common_cppflags) -fstack-protector-all -Wno-free-nonheap-object -Wno-date-time
 
 include $(CLEAR_VARS)
 LOCAL_SRC_FILES := crasher.cpp
@@ -63,8 +64,7 @@
 LOCAL_SRC_FILES_x86_64 := x86_64/crashglue.S
 LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES)
 LOCAL_MODULE_TAGS := optional
-LOCAL_CPPFLAGS := $(common_cppflags) -fstack-protector-all -Wno-free-nonheap-object -Wno-date-time
-#LOCAL_FORCE_STATIC_EXECUTABLE := true
+LOCAL_CPPFLAGS := $(crasher_cppflags)
 LOCAL_SHARED_LIBRARIES := libcutils liblog
 
 # The arm emulator has VFP but not VFPv3-D32.
@@ -79,6 +79,34 @@
 
 include $(BUILD_EXECUTABLE)
 
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := crasher.cpp
+LOCAL_SRC_FILES_arm    := arm/crashglue.S
+LOCAL_SRC_FILES_arm64  := arm64/crashglue.S
+LOCAL_SRC_FILES_mips   := mips/crashglue.S
+LOCAL_SRC_FILES_mips64 := mips64/crashglue.S
+LOCAL_SRC_FILES_x86    := x86/crashglue.S
+LOCAL_SRC_FILES_x86_64 := x86_64/crashglue.S
+LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES)
+LOCAL_MODULE_TAGS := optional
+LOCAL_CPPFLAGS := $(crasher_cppflags) -DSTATIC_CRASHER
+LOCAL_FORCE_STATIC_EXECUTABLE := true
+LOCAL_SHARED_LIBRARIES := libcutils liblog
+
+# The arm emulator has VFP but not VFPv3-D32.
+ifeq ($(ARCH_ARM_HAVE_VFP_D32),true)
+LOCAL_ASFLAGS_arm += -DHAS_VFP_D32
+endif
+
+LOCAL_MODULE := static_crasher
+LOCAL_MODULE_STEM_32 := static_crasher
+LOCAL_MODULE_STEM_64 := static_crasher64
+LOCAL_MULTILIB := both
+
+LOCAL_STATIC_LIBRARIES := libdebuggerd_client libcutils liblog
+
+include $(BUILD_EXECUTABLE)
+
 debuggerd_test_src_files := \
     utility.cpp \
     test/dump_memory_test.cpp \
diff --git a/debuggerd/client/debuggerd_client.cpp b/debuggerd/client/debuggerd_client.cpp
new file mode 100644
index 0000000..44e92fe
--- /dev/null
+++ b/debuggerd/client/debuggerd_client.cpp
@@ -0,0 +1,311 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "debuggerd/client.h"
+
+#include <errno.h>
+#include <inttypes.h>
+#include <pthread.h>
+#include <signal.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <sys/prctl.h>
+#include <sys/socket.h>
+#include <sys/syscall.h>
+#include <sys/un.h>
+#include <unistd.h>
+
+#include "private/libc_logging.h"
+
+#if defined(TARGET_IS_64_BIT) && !defined(__LP64__)
+#define SOCKET_NAME "android:debuggerd32"
+#else
+#define SOCKET_NAME "android:debuggerd"
+#endif
+
+// see man(2) prctl, specifically the section about PR_GET_NAME
+#define MAX_TASK_NAME_LEN (16)
+
+static debuggerd_callbacks_t g_callbacks;
+
+static int socket_abstract_client(const char* name, int type) {
+  sockaddr_un addr;
+
+  // Test with length +1 for the *initial* '\0'.
+  size_t namelen = strlen(name);
+  if ((namelen + 1) > sizeof(addr.sun_path)) {
+    errno = EINVAL;
+    return -1;
+  }
+
+  // This is used for abstract socket namespace, we need
+  // an initial '\0' at the start of the Unix socket path.
+  //
+  // Note: The path in this case is *not* supposed to be
+  // '\0'-terminated. ("man 7 unix" for the gory details.)
+  memset(&addr, 0, sizeof(addr));
+  addr.sun_family = AF_LOCAL;
+  addr.sun_path[0] = 0;
+  memcpy(addr.sun_path + 1, name, namelen);
+
+  socklen_t alen = namelen + offsetof(sockaddr_un, sun_path) + 1;
+
+  int s = socket(AF_LOCAL, type, 0);
+  if (s == -1) {
+    return -1;
+  }
+
+  int rc = TEMP_FAILURE_RETRY(connect(s, reinterpret_cast<sockaddr*>(&addr), alen));
+  if (rc == -1) {
+    close(s);
+    return -1;
+  }
+
+  return s;
+}
+
+/*
+ * Writes a summary of the signal to the log file.  We do this so that, if
+ * for some reason we're not able to contact debuggerd, there is still some
+ * indication of the failure in the log.
+ *
+ * We could be here as a result of native heap corruption, or while a
+ * mutex is being held, so we don't want to use any libc functions that
+ * could allocate memory or hold a lock.
+ */
+static void log_signal_summary(int signum, const siginfo_t* info) {
+  const char* signal_name = "???";
+  bool has_address = false;
+  switch (signum) {
+    case SIGABRT:
+      signal_name = "SIGABRT";
+      break;
+    case SIGBUS:
+      signal_name = "SIGBUS";
+      has_address = true;
+      break;
+    case SIGFPE:
+      signal_name = "SIGFPE";
+      has_address = true;
+      break;
+    case SIGILL:
+      signal_name = "SIGILL";
+      has_address = true;
+      break;
+    case SIGSEGV:
+      signal_name = "SIGSEGV";
+      has_address = true;
+      break;
+#if defined(SIGSTKFLT)
+    case SIGSTKFLT:
+      signal_name = "SIGSTKFLT";
+      break;
+#endif
+    case SIGTRAP:
+      signal_name = "SIGTRAP";
+      break;
+  }
+
+  char thread_name[MAX_TASK_NAME_LEN + 1];  // one more for termination
+  if (prctl(PR_GET_NAME, reinterpret_cast<unsigned long>(thread_name), 0, 0, 0) != 0) {
+    strcpy(thread_name, "<name unknown>");
+  } else {
+    // short names are null terminated by prctl, but the man page
+    // implies that 16 byte names are not.
+    thread_name[MAX_TASK_NAME_LEN] = 0;
+  }
+
+  // "info" will be null if the siginfo_t information was not available.
+  // Many signals don't have an address or a code.
+  char code_desc[32];  // ", code -6"
+  char addr_desc[32];  // ", fault addr 0x1234"
+  addr_desc[0] = code_desc[0] = 0;
+  if (info != nullptr) {
+    // For a rethrown signal, this si_code will be right and the one debuggerd shows will
+    // always be SI_TKILL.
+    __libc_format_buffer(code_desc, sizeof(code_desc), ", code %d", info->si_code);
+    if (has_address) {
+      __libc_format_buffer(addr_desc, sizeof(addr_desc), ", fault addr %p", info->si_addr);
+    }
+  }
+  __libc_format_log(ANDROID_LOG_FATAL, "libc", "Fatal signal %d (%s)%s%s in tid %d (%s)", signum,
+                    signal_name, code_desc, addr_desc, gettid(), thread_name);
+}
+
+/*
+ * Returns true if the handler for signal "signum" has SA_SIGINFO set.
+ */
+static bool have_siginfo(int signum) {
+  struct sigaction old_action, new_action;
+
+  memset(&new_action, 0, sizeof(new_action));
+  new_action.sa_handler = SIG_DFL;
+  new_action.sa_flags = SA_RESTART;
+  sigemptyset(&new_action.sa_mask);
+
+  if (sigaction(signum, &new_action, &old_action) < 0) {
+    __libc_format_log(ANDROID_LOG_WARN, "libc", "Failed testing for SA_SIGINFO: %s",
+                      strerror(errno));
+    return false;
+  }
+  bool result = (old_action.sa_flags & SA_SIGINFO) != 0;
+
+  if (sigaction(signum, &old_action, nullptr) == -1) {
+    __libc_format_log(ANDROID_LOG_WARN, "libc", "Restore failed in test for SA_SIGINFO: %s",
+                      strerror(errno));
+  }
+  return result;
+}
+
+static void send_debuggerd_packet(siginfo_t* info) {
+  // Mutex to prevent multiple crashing threads from trying to talk
+  // to debuggerd at the same time.
+  static pthread_mutex_t crash_mutex = PTHREAD_MUTEX_INITIALIZER;
+  int ret = pthread_mutex_trylock(&crash_mutex);
+  if (ret != 0) {
+    if (ret == EBUSY) {
+      __libc_format_log(ANDROID_LOG_INFO, "libc",
+                        "Another thread contacted debuggerd first; not contacting debuggerd.");
+      // This will never complete since the lock is never released.
+      pthread_mutex_lock(&crash_mutex);
+    } else {
+      __libc_format_log(ANDROID_LOG_INFO, "libc", "pthread_mutex_trylock failed: %s", strerror(ret));
+    }
+    return;
+  }
+
+  int s = socket_abstract_client(SOCKET_NAME, SOCK_STREAM | SOCK_CLOEXEC);
+  if (s == -1) {
+    __libc_format_log(ANDROID_LOG_FATAL, "libc", "Unable to open connection to debuggerd: %s",
+                      strerror(errno));
+    return;
+  }
+
+  // debuggerd knows our pid from the credentials on the
+  // local socket but we need to tell it the tid of the crashing thread.
+  // debuggerd will be paranoid and verify that we sent a tid
+  // that's actually in our process.
+  debugger_msg_t msg;
+  msg.action = DEBUGGER_ACTION_CRASH;
+  msg.tid = gettid();
+  msg.abort_msg_address = 0;
+
+  if (g_callbacks.get_abort_message) {
+    msg.abort_msg_address = reinterpret_cast<uintptr_t>(g_callbacks.get_abort_message());
+  }
+
+  msg.original_si_code = (info != nullptr) ? info->si_code : 0;
+  ret = TEMP_FAILURE_RETRY(write(s, &msg, sizeof(msg)));
+  if (ret == sizeof(msg)) {
+    char debuggerd_ack;
+    ret = TEMP_FAILURE_RETRY(read(s, &debuggerd_ack, 1));
+    int saved_errno = errno;
+    if (g_callbacks.post_dump) {
+      g_callbacks.post_dump();
+    }
+    errno = saved_errno;
+  } else {
+    // read or write failed -- broken connection?
+    __libc_format_log(ANDROID_LOG_FATAL, "libc", "Failed while talking to debuggerd: %s",
+                      strerror(errno));
+  }
+
+  close(s);
+}
+
+/*
+ * Catches fatal signals so we can ask debuggerd to ptrace us before
+ * we crash.
+ */
+static void debuggerd_signal_handler(int signal_number, siginfo_t* info, void*) {
+  // It's possible somebody cleared the SA_SIGINFO flag, which would mean
+  // our "info" arg holds an undefined value.
+  if (!have_siginfo(signal_number)) {
+    info = nullptr;
+  }
+
+  log_signal_summary(signal_number, info);
+
+  send_debuggerd_packet(info);
+
+  // We need to return from the signal handler so that debuggerd can dump the
+  // thread that crashed, but returning here does not guarantee that the signal
+  // will be thrown again, even for SIGSEGV and friends, since the signal could
+  // have been sent manually. Resend the signal with rt_tgsigqueueinfo(2) to
+  // preserve the SA_SIGINFO contents.
+  signal(signal_number, SIG_DFL);
+
+  struct siginfo si;
+  if (!info) {
+    memset(&si, 0, sizeof(si));
+    si.si_code = SI_USER;
+    si.si_pid = getpid();
+    si.si_uid = getuid();
+    info = &si;
+  } else if (info->si_code >= 0 || info->si_code == SI_TKILL) {
+    // rt_tgsigqueueinfo(2)'s documentation appears to be incorrect on kernels
+    // that contain commit 66dd34a (3.9+). The manpage claims to only allow
+    // negative si_code values that are not SI_TKILL, but 66dd34a changed the
+    // check to allow all si_code values in calls coming from inside the house.
+  }
+
+  int rc = syscall(SYS_rt_tgsigqueueinfo, getpid(), gettid(), signal_number, info);
+  if (rc != 0) {
+    __libc_format_log(ANDROID_LOG_FATAL, "libc", "failed to resend signal during crash: %s",
+                      strerror(errno));
+    _exit(0);
+  }
+}
+
+void debuggerd_init(debuggerd_callbacks_t* callbacks) {
+  if (callbacks) {
+    g_callbacks = *callbacks;
+  }
+
+  struct sigaction action;
+  memset(&action, 0, sizeof(action));
+  sigemptyset(&action.sa_mask);
+  action.sa_sigaction = debuggerd_signal_handler;
+  action.sa_flags = SA_RESTART | SA_SIGINFO;
+
+  // Use the alternate signal stack if available so we can catch stack overflows.
+  action.sa_flags |= SA_ONSTACK;
+
+  sigaction(SIGABRT, &action, nullptr);
+  sigaction(SIGBUS, &action, nullptr);
+  sigaction(SIGFPE, &action, nullptr);
+  sigaction(SIGILL, &action, nullptr);
+  sigaction(SIGSEGV, &action, nullptr);
+#if defined(SIGSTKFLT)
+  sigaction(SIGSTKFLT, &action, nullptr);
+#endif
+  sigaction(SIGTRAP, &action, nullptr);
+}
diff --git a/debuggerd/crasher.cpp b/debuggerd/crasher.cpp
index bdeaf0b..a37df33 100644
--- a/debuggerd/crasher.cpp
+++ b/debuggerd/crasher.cpp
@@ -16,6 +16,10 @@
 #include <cutils/sockets.h>
 #include <log/log.h>
 
+#if defined(STATIC_CRASHER)
+#include "debuggerd/client.h"
+#endif
+
 #ifndef __unused
 #define __unused __attribute__((__unused__))
 #endif
@@ -43,7 +47,7 @@
 // Assign local array address to global variable to force stack guards.
 // Use another noinline function to corrupt the stack.
 __attribute__ ((noinline)) static int smash_stack(volatile int* plen) {
-    printf("crasher: deliberately corrupting stack...\n");
+    printf("%s: deliberately corrupting stack...\n", __progname);
 
     char buf[128];
     smash_stack_dummy_buf = buf;
@@ -135,7 +139,7 @@
 
 static int do_action(const char* arg)
 {
-    fprintf(stderr,"crasher: init pid=%d tid=%d\n", getpid(), gettid());
+    fprintf(stderr, "%s: init pid=%d tid=%d\n", __progname, getpid(), gettid());
 
     if (!strncmp(arg, "thread-", strlen("thread-"))) {
         return do_action_on_thread(arg + strlen("thread-"));
@@ -209,9 +213,26 @@
 
 int main(int argc, char **argv)
 {
-    fprintf(stderr,"crasher: built at " __TIME__ "!@\n");
+    fprintf(stderr, "%s: built at " __TIME__ "!@\n", __progname);
 
-    if(argc > 1) {
+#if defined(STATIC_CRASHER)
+    debuggerd_callbacks_t callbacks = {
+      .get_abort_message = []() {
+        static struct {
+          size_t size;
+          char msg[32];
+        } msg;
+
+        msg.size = strlen("dummy abort message");
+        memcpy(msg.msg, "dummy abort message", strlen("dummy abort message"));
+        return reinterpret_cast<abort_msg_t*>(&msg);
+      },
+      .post_dump = nullptr
+    };
+    debuggerd_init(&callbacks);
+#endif
+
+    if (argc > 1) {
         return do_action(argv[1]);
     } else {
         crash1();
diff --git a/debuggerd/debuggerd.cpp b/debuggerd/debuggerd.cpp
index d87594c..a82fd07 100644
--- a/debuggerd/debuggerd.cpp
+++ b/debuggerd/debuggerd.cpp
@@ -562,7 +562,7 @@
   // won't necessarily have stopped by the time ptrace() returns.  (We
   // currently assume it does.)  We write to the file descriptor to
   // ensure that it can run as soon as we call PTRACE_CONT below.
-  // See details in bionic/libc/linker/debugger.c, in function
+  // See details in client/debuggerd_client.cpp, in function
   // debugger_signal_handler().
 
   // Attach to the target process.
diff --git a/debuggerd/include/debuggerd/client.h b/debuggerd/include/debuggerd/client.h
new file mode 100644
index 0000000..41b7b3a
--- /dev/null
+++ b/debuggerd/include/debuggerd/client.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <stdint.h>
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+// On 32-bit devices, DEBUGGER_SOCKET_NAME is a 32-bit debuggerd.
+// On 64-bit devices, DEBUGGER_SOCKET_NAME is a 64-bit debuggerd.
+#define DEBUGGER_SOCKET_NAME "android:debuggerd"
+
+// Used only on 64-bit devices for debuggerd32.
+#define DEBUGGER32_SOCKET_NAME "android:debuggerd32"
+
+__BEGIN_DECLS
+
+typedef enum {
+  // dump a crash
+  DEBUGGER_ACTION_CRASH,
+  // dump a tombstone file
+  DEBUGGER_ACTION_DUMP_TOMBSTONE,
+  // dump a backtrace only back to the socket
+  DEBUGGER_ACTION_DUMP_BACKTRACE,
+} debugger_action_t;
+
+// Make sure that all values have a fixed size so that this structure
+// is the same for 32 bit and 64 bit processes.
+typedef struct __attribute__((packed)) {
+  int32_t action;
+  pid_t tid;
+  uint64_t abort_msg_address;
+  int32_t original_si_code;
+} debugger_msg_t;
+
+// These callbacks are called in a signal handler, and thus must be async signal safe.
+// If null, the callbacks will not be called.
+typedef struct {
+  struct abort_msg_t* (*get_abort_message)();
+  void (*post_dump)();
+} debuggerd_callbacks_t;
+
+void debuggerd_init(debuggerd_callbacks_t* callbacks);
+
+__END_DECLS
diff --git a/healthd/Android.mk b/healthd/Android.mk
index 127f39e..deebed5 100644
--- a/healthd/Android.mk
+++ b/healthd/Android.mk
@@ -17,7 +17,7 @@
 LOCAL_MODULE := libbatterymonitor
 LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
 LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
-LOCAL_STATIC_LIBRARIES := libutils libbinder
+LOCAL_STATIC_LIBRARIES := libutils libbase libbinder
 include $(BUILD_STATIC_LIBRARY)
 
 include $(CLEAR_VARS)
@@ -60,7 +60,7 @@
 
 LOCAL_C_INCLUDES := bootable/recovery $(LOCAL_PATH)/include
 
-LOCAL_STATIC_LIBRARIES := libbatterymonitor libbatteryservice libbinder
+LOCAL_STATIC_LIBRARIES := libbatterymonitor libbatteryservice libbinder libbase
 
 ifneq ($(strip $(LOCAL_CHARGER_NO_UI)),true)
 LOCAL_STATIC_LIBRARIES += libminui libpng libz
diff --git a/healthd/BatteryMonitor.cpp b/healthd/BatteryMonitor.cpp
index 69647de..d1c547d 100644
--- a/healthd/BatteryMonitor.cpp
+++ b/healthd/BatteryMonitor.cpp
@@ -28,6 +28,8 @@
 #include <unistd.h>
 #include <memory>
 
+#include <android-base/file.h>
+#include <android-base/strings.h>
 #include <batteryservice/BatteryService.h>
 #include <cutils/klog.h>
 #include <cutils/properties.h>
@@ -121,34 +123,15 @@
     return ret;
 }
 
-int BatteryMonitor::readFromFile(const String8& path, char* buf, size_t size) {
-    char *cp = NULL;
-
-    if (path.isEmpty())
-        return -1;
-    int fd = open(path.string(), O_RDONLY, 0);
-    if (fd == -1) {
-        KLOG_ERROR(LOG_TAG, "Could not open '%s'\n", path.string());
-        return -1;
+int BatteryMonitor::readFromFile(const String8& path, std::string* buf) {
+    if (android::base::ReadFileToString(String8::std_string(path), buf)) {
+        *buf = android::base::Trim(*buf);
     }
-
-    ssize_t count = TEMP_FAILURE_RETRY(read(fd, buf, size));
-    if (count > 0)
-            cp = (char *)memrchr(buf, '\n', count);
-
-    if (cp)
-        *cp = '\0';
-    else
-        buf[0] = '\0';
-
-    close(fd);
-    return count;
+    return buf->length();
 }
 
 BatteryMonitor::PowerSupplyType BatteryMonitor::readPowerSupplyType(const String8& path) {
-    const int SIZE = 128;
-    char buf[SIZE];
-    int length = readFromFile(path, buf, SIZE);
+    std::string buf;
     BatteryMonitor::PowerSupplyType ret;
     struct sysfsStringEnumMap supplyTypeMap[] = {
             { "Unknown", ANDROID_POWER_SUPPLY_TYPE_UNKNOWN },
@@ -167,12 +150,12 @@
             { NULL, 0 },
     };
 
-    if (length <= 0)
+    if (readFromFile(path, &buf) <= 0)
         return ANDROID_POWER_SUPPLY_TYPE_UNKNOWN;
 
-    ret = (BatteryMonitor::PowerSupplyType)mapSysfsString(buf, supplyTypeMap);
+    ret = (BatteryMonitor::PowerSupplyType)mapSysfsString(buf.c_str(), supplyTypeMap);
     if (ret < 0) {
-        KLOG_WARNING(LOG_TAG, "Unknown power supply type '%s'\n", buf);
+        KLOG_WARNING(LOG_TAG, "Unknown power supply type '%s'\n", buf.c_str());
         ret = ANDROID_POWER_SUPPLY_TYPE_UNKNOWN;
     }
 
@@ -180,27 +163,23 @@
 }
 
 bool BatteryMonitor::getBooleanField(const String8& path) {
-    const int SIZE = 16;
-    char buf[SIZE];
-
+    std::string buf;
     bool value = false;
-    if (readFromFile(path, buf, SIZE) > 0) {
-        if (buf[0] != '0') {
+
+    if (readFromFile(path, &buf) > 0)
+        if (buf[0] != '0')
             value = true;
-        }
-    }
 
     return value;
 }
 
 int BatteryMonitor::getIntField(const String8& path) {
-    const int SIZE = 128;
-    char buf[SIZE];
-
+    std::string buf;
     int value = 0;
-    if (readFromFile(path, buf, SIZE) > 0) {
-        value = strtol(buf, NULL, 0);
-    }
+
+    if (readFromFile(path, &buf) > 0)
+        value = std::stoi(buf.c_str(), NULL, 0);
+
     return value;
 }
 
@@ -241,18 +220,16 @@
         props.batteryHealth = BATTERY_HEALTH_GOOD;
     }
 
-    const int SIZE = 128;
-    char buf[SIZE];
-    String8 btech;
+    std::string buf;
 
-    if (readFromFile(mHealthdConfig->batteryStatusPath, buf, SIZE) > 0)
-        props.batteryStatus = getBatteryStatus(buf);
+    if (readFromFile(mHealthdConfig->batteryStatusPath, &buf) > 0)
+        props.batteryStatus = getBatteryStatus(buf.c_str());
 
-    if (readFromFile(mHealthdConfig->batteryHealthPath, buf, SIZE) > 0)
-        props.batteryHealth = getBatteryHealth(buf);
+    if (readFromFile(mHealthdConfig->batteryHealthPath, &buf) > 0)
+        props.batteryHealth = getBatteryHealth(buf.c_str());
 
-    if (readFromFile(mHealthdConfig->batteryTechnologyPath, buf, SIZE) > 0)
-        props.batteryTechnology = String8(buf);
+    if (readFromFile(mHealthdConfig->batteryTechnologyPath, &buf) > 0)
+        props.batteryTechnology = String8(buf.c_str());
 
     unsigned int i;
 
@@ -261,33 +238,31 @@
         path.appendFormat("%s/%s/online", POWER_SUPPLY_SYSFS_PATH,
                           mChargerNames[i].string());
 
-        if (readFromFile(path, buf, SIZE) > 0) {
-            if (buf[0] != '0') {
-                path.clear();
-                path.appendFormat("%s/%s/type", POWER_SUPPLY_SYSFS_PATH,
-                                  mChargerNames[i].string());
-                switch(readPowerSupplyType(path)) {
-                case ANDROID_POWER_SUPPLY_TYPE_AC:
-                    props.chargerAcOnline = true;
-                    break;
-                case ANDROID_POWER_SUPPLY_TYPE_USB:
-                    props.chargerUsbOnline = true;
-                    break;
-                case ANDROID_POWER_SUPPLY_TYPE_WIRELESS:
-                    props.chargerWirelessOnline = true;
-                    break;
-                default:
-                    KLOG_WARNING(LOG_TAG, "%s: Unknown power supply type\n",
-                                 mChargerNames[i].string());
-                }
-                path.clear();
-                path.appendFormat("%s/%s/current_max", POWER_SUPPLY_SYSFS_PATH,
-                                  mChargerNames[i].string());
-                if (access(path.string(), R_OK) == 0) {
-                    int maxChargingCurrent = getIntField(path);
-                    if (props.maxChargingCurrent < maxChargingCurrent) {
-                        props.maxChargingCurrent = maxChargingCurrent;
-                    }
+        if (getIntField(path)) {
+            path.clear();
+            path.appendFormat("%s/%s/type", POWER_SUPPLY_SYSFS_PATH,
+                              mChargerNames[i].string());
+            switch(readPowerSupplyType(path)) {
+            case ANDROID_POWER_SUPPLY_TYPE_AC:
+                props.chargerAcOnline = true;
+                break;
+            case ANDROID_POWER_SUPPLY_TYPE_USB:
+                props.chargerUsbOnline = true;
+                break;
+            case ANDROID_POWER_SUPPLY_TYPE_WIRELESS:
+                props.chargerWirelessOnline = true;
+                break;
+            default:
+                KLOG_WARNING(LOG_TAG, "%s: Unknown power supply type\n",
+                             mChargerNames[i].string());
+            }
+            path.clear();
+            path.appendFormat("%s/%s/current_max", POWER_SUPPLY_SYSFS_PATH,
+                              mChargerNames[i].string());
+            if (access(path.string(), R_OK) == 0) {
+                int maxChargingCurrent = getIntField(path);
+                if (props.maxChargingCurrent < maxChargingCurrent) {
+                    props.maxChargingCurrent = maxChargingCurrent;
                 }
             }
         }
@@ -343,10 +318,9 @@
 int BatteryMonitor::getChargeStatus() {
     int result = BATTERY_STATUS_UNKNOWN;
     if (!mHealthdConfig->batteryStatusPath.isEmpty()) {
-        char buf[128];
-        if (readFromFile(mHealthdConfig->batteryStatusPath, buf, sizeof(buf)) > 0) {
-            result = getBatteryStatus(buf);
-        }
+        std::string buf;
+        if (readFromFile(mHealthdConfig->batteryStatusPath, &buf) > 0)
+            result = getBatteryStatus(buf.c_str());
     }
     return result;
 }
diff --git a/healthd/include/healthd/BatteryMonitor.h b/healthd/include/healthd/BatteryMonitor.h
index 440f2e4..8865a7d 100644
--- a/healthd/include/healthd/BatteryMonitor.h
+++ b/healthd/include/healthd/BatteryMonitor.h
@@ -55,7 +55,7 @@
 
     int getBatteryStatus(const char* status);
     int getBatteryHealth(const char* status);
-    int readFromFile(const String8& path, char* buf, size_t size);
+    int readFromFile(const String8& path, std::string* buf);
     PowerSupplyType readPowerSupplyType(const String8& path);
     bool getBooleanField(const String8& path);
     int getIntField(const String8& path);
diff --git a/include/android/log.h b/include/android/log.h
index 1c171b7..2956e6e 100644
--- a/include/android/log.h
+++ b/include/android/log.h
@@ -124,7 +124,7 @@
 void __android_log_assert(const char *cond, const char *tag,
                           const char *fmt, ...)
 #if defined(__GNUC__)
-    __attribute__ ((noreturn))
+    __attribute__ ((__noreturn__))
 #ifdef __USE_MINGW_ANSI_STDIO
 #if __USE_MINGW_ANSI_STDIO
     __attribute__ ((format(gnu_printf, 3, 4)))
diff --git a/include/cutils/debugger.h b/include/cutils/debugger.h
index 285e1af..20e8796 100644
--- a/include/cutils/debugger.h
+++ b/include/cutils/debugger.h
@@ -20,32 +20,10 @@
 #include <sys/cdefs.h>
 #include <sys/types.h>
 
+#include "debuggerd/client.h"
+
 __BEGIN_DECLS
 
-#define DEBUGGER_SOCKET_NAME "android:debuggerd"
-#define DEBUGGER32_SOCKET_NAME "android:debuggerd32"
-#define DEBUGGER64_SOCKET_NAME DEBUGGER_SOCKET_NAME
-
-typedef enum {
-    // dump a crash
-    DEBUGGER_ACTION_CRASH,
-    // dump a tombstone file
-    DEBUGGER_ACTION_DUMP_TOMBSTONE,
-    // dump a backtrace only back to the socket
-    DEBUGGER_ACTION_DUMP_BACKTRACE,
-} debugger_action_t;
-
-// Make sure that all values have a fixed size so that this structure
-// is the same for 32 bit and 64 bit processes.
-// NOTE: Any changes to this structure must also be reflected in
-//       bionic/linker/debugger.cpp.
-typedef struct __attribute__((packed)) {
-    int32_t action;
-    pid_t tid;
-    uint64_t abort_msg_address;
-    int32_t original_si_code;
-} debugger_msg_t;
-
 /* Dumps a process backtrace, registers, and stack to a tombstone file (requires root).
  * Stores the tombstone path in the provided buffer.
  * Returns 0 on success, -1 on error.
diff --git a/include/system/qemu_pipe.h b/include/system/qemu_pipe.h
new file mode 100644
index 0000000..d403f8d
--- /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), "%04x", 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 != 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/libcutils/Android.mk b/libcutils/Android.mk
index 822a7d3..e29c9ad 100644
--- a/libcutils/Android.mk
+++ b/libcutils/Android.mk
@@ -117,7 +117,8 @@
         arch-x86_64/android_memset32.S \
 
 LOCAL_C_INCLUDES := $(libcutils_c_includes)
-LOCAL_STATIC_LIBRARIES := liblog
+LOCAL_EXPORT_STATIC_LIBRARY_HEADERS := libdebuggerd_client
+LOCAL_STATIC_LIBRARIES := liblog libdebuggerd_client
 ifneq ($(ENABLE_CPUSETS),)
 LOCAL_CFLAGS += -DUSE_CPUSETS
 endif
@@ -134,6 +135,8 @@
 # TODO: remove liblog as whole static library, once we don't have prebuilt that requires
 # liblog symbols present in libcutils.
 LOCAL_WHOLE_STATIC_LIBRARIES := libcutils liblog
+LOCAL_EXPORT_STATIC_LIBRARY_HEADERS := libdebuggerd_client
+LOCAL_STATIC_LIBRARIES := libdebuggerd_client
 LOCAL_SHARED_LIBRARIES := liblog
 ifneq ($(ENABLE_CPUSETS),)
 LOCAL_CFLAGS += -DUSE_CPUSETS
diff --git a/libpixelflinger/Android.mk b/libpixelflinger/Android.mk
index 9a937f8..55891db 100644
--- a/libpixelflinger/Android.mk
+++ b/libpixelflinger/Android.mk
@@ -74,10 +74,6 @@
 		    external/safe-iop/include
 LOCAL_SHARED_LIBRARIES := libcutils liblog libutils
 
-# Really this should go away entirely or at least not depend on
-# libhardware, but this at least gets us built.
-LOCAL_SHARED_LIBRARIES += libhardware_legacy
-LOCAL_CFLAGS += -DWITH_LIB_HARDWARE
 include $(BUILD_SHARED_LIBRARY)
 
 include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/libpixelflinger/codeflinger/ARMAssembler.cpp b/libpixelflinger/codeflinger/ARMAssembler.cpp
index 92243da..849512a 100644
--- a/libpixelflinger/codeflinger/ARMAssembler.cpp
+++ b/libpixelflinger/codeflinger/ARMAssembler.cpp
@@ -22,10 +22,6 @@
 #include <cutils/log.h>
 #include <cutils/properties.h>
 
-#if defined(WITH_LIB_HARDWARE)
-#include <hardware_legacy/qemu_tracing.h>
-#endif
-
 #include <private/pixelflinger/ggl_context.h>
 
 #include "ARMAssembler.h"
@@ -48,9 +44,6 @@
 {
     mBase = mPC = (uint32_t *)assembly->base();
     mDuration = ggl_system_time();
-#if defined(WITH_LIB_HARDWARE)
-    mQemuTracing = true;
-#endif
 }
 
 ARMAssembler::~ARMAssembler()
@@ -184,13 +177,6 @@
     const char * const format = "generated %s (%d ins) at [%p:%p] in %lld ns\n";
     ALOGI(format, name, int(pc()-base()), base(), pc(), duration);
 
-#if defined(WITH_LIB_HARDWARE)
-    if (__builtin_expect(mQemuTracing, 0)) {
-        int err = qemu_add_mapping(uintptr_t(base()), name);
-        mQemuTracing = (err >= 0);
-    }
-#endif
-
     char value[PROPERTY_VALUE_MAX];
     property_get("debug.pf.disasm", value, "0");
     if (atoi(value) != 0) {
diff --git a/libpixelflinger/codeflinger/ARMAssembler.h b/libpixelflinger/codeflinger/ARMAssembler.h
index e0c7646..7178c65 100644
--- a/libpixelflinger/codeflinger/ARMAssembler.h
+++ b/libpixelflinger/codeflinger/ARMAssembler.h
@@ -167,9 +167,6 @@
     uint32_t*       mPC;
     uint32_t*       mPrologPC;
     int64_t         mDuration;
-#if defined(WITH_LIB_HARDWARE)
-    bool            mQemuTracing;
-#endif
     
     struct branch_target_t {
         inline branch_target_t() : label(0), pc(0) { }
diff --git a/libpixelflinger/codeflinger/MIPS64Assembler.cpp b/libpixelflinger/codeflinger/MIPS64Assembler.cpp
index 672040b..b9f31ff 100644
--- a/libpixelflinger/codeflinger/MIPS64Assembler.cpp
+++ b/libpixelflinger/codeflinger/MIPS64Assembler.cpp
@@ -33,10 +33,6 @@
 #include <cutils/log.h>
 #include <cutils/properties.h>
 
-#if defined(WITH_LIB_HARDWARE)
-#include <hardware_legacy/qemu_tracing.h>
-#endif
-
 #include <private/pixelflinger/ggl_context.h>
 
 #include "MIPS64Assembler.h"
diff --git a/libpixelflinger/codeflinger/MIPSAssembler.cpp b/libpixelflinger/codeflinger/MIPSAssembler.cpp
index 5497fae..ae06a13 100644
--- a/libpixelflinger/codeflinger/MIPSAssembler.cpp
+++ b/libpixelflinger/codeflinger/MIPSAssembler.cpp
@@ -55,10 +55,6 @@
 #include <cutils/log.h>
 #include <cutils/properties.h>
 
-#if defined(WITH_LIB_HARDWARE)
-#include <hardware_legacy/qemu_tracing.h>
-#endif
-
 #include <private/pixelflinger/ggl_context.h>
 
 #include "MIPSAssembler.h"
@@ -1411,13 +1407,6 @@
     const char * const format = "generated %s (%d ins) at [%p:%p] in %lld ns\n";
     ALOGI(format, name, int(pc()-base()), base(), pc(), duration);
 
-#if defined(WITH_LIB_HARDWARE)
-    if (__builtin_expect(mQemuTracing, 0)) {
-        int err = qemu_add_mapping(uintptr_t(base()), name);
-        mQemuTracing = (err >= 0);
-    }
-#endif
-
     char value[PROPERTY_VALUE_MAX];
     value[0] = '\0';
 
diff --git a/libpixelflinger/codeflinger/MIPSAssembler.h b/libpixelflinger/codeflinger/MIPSAssembler.h
index b53fefb..c1178b6 100644
--- a/libpixelflinger/codeflinger/MIPSAssembler.h
+++ b/libpixelflinger/codeflinger/MIPSAssembler.h
@@ -410,9 +410,6 @@
     uint32_t*       mPC;
     uint32_t*       mPrologPC;
     int64_t         mDuration;
-#if defined(WITH_LIB_HARDWARE)
-    bool            mQemuTracing;
-#endif
 
     struct branch_target_t {
         inline branch_target_t() : label(0), pc(0) { }