Merge "Revert "Revert "Adding e4crypt support"""
diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp
index a25d316..e35cc70 100644
--- a/fastboot/fastboot.cpp
+++ b/fastboot/fastboot.cpp
@@ -528,7 +528,7 @@
 
 static struct sparse_file **load_sparse_files(int fd, int max_size)
 {
-    struct sparse_file* s = sparse_file_import_auto(fd, false);
+    struct sparse_file* s = sparse_file_import_auto(fd, false, true);
     if (!s) {
         die("cannot sparse read file\n");
     }
diff --git a/fs_mgr/Android.mk b/fs_mgr/Android.mk
index 61bf1ee..1179eaa 100644
--- a/fs_mgr/Android.mk
+++ b/fs_mgr/Android.mk
@@ -35,6 +35,7 @@
 LOCAL_UNSTRIPPED_PATH := $(TARGET_ROOT_OUT_UNSTRIPPED)
 
 LOCAL_STATIC_LIBRARIES := libfs_mgr liblogwrap libcutils liblog libc libmincrypt libext4_utils_static
+LOCAL_CXX_STL := libc++_static
 
 LOCAL_CFLAGS := -Werror
 
diff --git a/include/backtrace/Backtrace.h b/include/backtrace/Backtrace.h
index 8c39acb..290682a 100644
--- a/include/backtrace/Backtrace.h
+++ b/include/backtrace/Backtrace.h
@@ -44,9 +44,6 @@
   uintptr_t func_offset;  // pc relative to the start of the function, only valid if func_name is not NULL.
 };
 
-// Forward declarations.
-class BacktraceImpl;
-
 #if defined(__APPLE__)
 struct __darwin_ucontext;
 typedef __darwin_ucontext ucontext_t;
@@ -72,7 +69,7 @@
   virtual ~Backtrace();
 
   // Get the current stack trace and store in the backtrace_ structure.
-  virtual bool Unwind(size_t num_ignore_frames, ucontext_t* context = NULL);
+  virtual bool Unwind(size_t num_ignore_frames, ucontext_t* context = NULL) = 0;
 
   // Get the function name and offset into the function given the pc.
   // If the string is empty, then no valid function name was found.
@@ -95,9 +92,9 @@
   virtual std::string FormatFrameData(size_t frame_num);
   virtual std::string FormatFrameData(const backtrace_frame_data_t* frame);
 
-  pid_t Pid() { return pid_; }
-  pid_t Tid() { return tid_; }
-  size_t NumFrames() { return frames_.size(); }
+  pid_t Pid() const { return pid_; }
+  pid_t Tid() const { return tid_; }
+  size_t NumFrames() const { return frames_.size(); }
 
   const backtrace_frame_data_t* GetFrame(size_t frame_num) {
     if (frame_num >= frames_.size()) {
@@ -117,7 +114,11 @@
   BacktraceMap* GetMap() { return map_; }
 
 protected:
-  Backtrace(BacktraceImpl* impl, pid_t pid, BacktraceMap* map);
+  Backtrace(pid_t pid, pid_t tid, BacktraceMap* map);
+
+  // The name returned is not demangled, GetFunctionName() takes care of
+  // demangling the name.
+  virtual std::string GetFunctionNameRaw(uintptr_t pc, uintptr_t* offset) = 0;
 
   virtual bool VerifyReadWordArgs(uintptr_t ptr, word_t* out_value);
 
@@ -130,10 +131,6 @@
   bool map_shared_;
 
   std::vector<backtrace_frame_data_t> frames_;
-
-  BacktraceImpl* impl_;
-
-  friend class BacktraceImpl;
 };
 
 #endif // _BACKTRACE_BACKTRACE_H
diff --git a/include/cutils/trace.h b/include/cutils/trace.h
index 59ff6c1..9d039e6 100644
--- a/include/cutils/trace.h
+++ b/include/cutils/trace.h
@@ -80,7 +80,6 @@
 #error ATRACE_TAG must be defined to be one of the tags defined in cutils/trace.h
 #endif
 
-#ifdef HAVE_ANDROID_OS
 /**
  * Opens the trace file for writing and reads the property for initial tags.
  * The atrace.tags.enableflags property sets the tags to trace.
@@ -248,19 +247,6 @@
     }
 }
 
-#else // not HAVE_ANDROID_OS
-
-#define ATRACE_INIT()
-#define ATRACE_GET_ENABLED_TAGS()
-#define ATRACE_ENABLED() 0
-#define ATRACE_BEGIN(name)
-#define ATRACE_END()
-#define ATRACE_ASYNC_BEGIN(name, cookie)
-#define ATRACE_ASYNC_END(name, cookie)
-#define ATRACE_INT(name, value)
-
-#endif // not HAVE_ANDROID_OS
-
 __END_DECLS
 
 #endif // _LIBS_CUTILS_TRACE_H
diff --git a/include/private/android_filesystem_capability.h b/include/private/android_filesystem_capability.h
index 0505cda..b92d3db 100644
--- a/include/private/android_filesystem_capability.h
+++ b/include/private/android_filesystem_capability.h
@@ -105,7 +105,9 @@
 #define CAP_MAC_ADMIN 33
 #define CAP_SYSLOG 34
 #define CAP_WAKE_ALARM 35
-#define CAP_LAST_CAP CAP_WAKE_ALARM
+#define CAP_BLOCK_SUSPEND 36
+#define CAP_AUDIT_READ 37
+#define CAP_LAST_CAP CAP_AUDIT_READ
 #define cap_valid(x) ((x) >= 0 && (x) <= CAP_LAST_CAP)
 #define CAP_TO_INDEX(x) ((x) >> 5)
 #define CAP_TO_MASK(x) (1 << ((x) & 31))
diff --git a/include/private/android_filesystem_config.h b/include/private/android_filesystem_config.h
index a3d11a7..74e5c82 100644
--- a/include/private/android_filesystem_config.h
+++ b/include/private/android_filesystem_config.h
@@ -249,6 +249,7 @@
 
     /* the following files have enhanced capabilities and ARE included in user builds. */
     { 00750, AID_ROOT,      AID_SHELL,     (1 << CAP_SETUID) | (1 << CAP_SETGID), "system/bin/run-as" },
+    { 00700, AID_SYSTEM,    AID_SHELL,     (1 << CAP_BLOCK_SUSPEND), "system/bin/inputflinger" },
 
     { 00750, AID_ROOT,      AID_ROOT,      0, "system/bin/uncrypt" },
     { 00750, AID_ROOT,      AID_ROOT,      0, "system/bin/install-recovery.sh" },
diff --git a/include/system/graphics.h b/include/system/graphics.h
index c9f5950..c0f03fa 100644
--- a/include/system/graphics.h
+++ b/include/system/graphics.h
@@ -244,6 +244,56 @@
     HAL_PIXEL_FORMAT_RAW10 = 0x25,
 
     /*
+     * Android RAW12 format:
+     *
+     * This format is exposed outside of camera HAL to applications.
+     *
+     * RAW12 is a single-channel, 12-bit per pixel, densely packed in each row,
+     * unprocessed format, usually representing raw Bayer-pattern images coming from
+     * an image sensor.
+     *
+     * In an image buffer with this format, starting from the first pixel of each
+     * row, each two consecutive pixels are packed into 3 bytes (24 bits). The first
+     * and second byte contains the top 8 bits of first and second pixel. The third
+     * byte contains the 4 least significant bits of the two pixels, the exact layout
+     * data for each two consecutive pixels is illustrated below (Pi[j] stands for
+     * the jth bit of the ith pixel):
+     *
+     *           bit 7                                            bit 0
+     *          ======|======|======|======|======|======|======|======|
+     * Byte 0: |P0[11]|P0[10]|P0[ 9]|P0[ 8]|P0[ 7]|P0[ 6]|P0[ 5]|P0[ 4]|
+     *         |------|------|------|------|------|------|------|------|
+     * Byte 1: |P1[11]|P1[10]|P1[ 9]|P1[ 8]|P1[ 7]|P1[ 6]|P1[ 5]|P1[ 4]|
+     *         |------|------|------|------|------|------|------|------|
+     * Byte 2: |P1[ 3]|P1[ 2]|P1[ 1]|P1[ 0]|P0[ 3]|P0[ 2]|P0[ 1]|P0[ 0]|
+     *          =======================================================
+     *
+     * This format assumes:
+     * - a width multiple of 4 pixels
+     * - an even height
+     * - a vertical stride equal to the height
+     * - strides are specified in bytes, not in pixels
+     *
+     *   size = stride * height
+     *
+     * When stride is equal to width * (12 / 8), there will be no padding bytes at
+     * the end of each row, the entire image data is densely packed. When stride is
+     * larger than width * (12 / 8), padding bytes will be present at the end of
+     * each row (including the last row).
+     *
+     * This format must be accepted by the gralloc module when used with the
+     * following usage flags:
+     *    - GRALLOC_USAGE_HW_CAMERA_*
+     *    - GRALLOC_USAGE_SW_*
+     *    - GRALLOC_USAGE_RENDERSCRIPT
+     *
+     * When used with ANativeWindow, the dataSpace field should be
+     * HAL_DATASPACE_ARBITRARY, as raw image sensor buffers require substantial
+     * extra metadata to define.
+     */
+    HAL_PIXEL_FORMAT_RAW12 = 0x26,
+
+    /*
      * Android opaque RAW format:
      *
      * This format is exposed outside of the camera HAL to applications.
diff --git a/init/init_parser.cpp b/init/init_parser.cpp
index 4e18e20..593f0c5 100644
--- a/init/init_parser.cpp
+++ b/init/init_parser.cpp
@@ -122,7 +122,6 @@
         break;
     case 'c':
         if (!strcmp(s, "opy")) return K_copy;
-        if (!strcmp(s, "apability")) return K_capability;
         if (!strcmp(s, "lass")) return K_class;
         if (!strcmp(s, "lass_start")) return K_class_start;
         if (!strcmp(s, "lass_stop")) return K_class_stop;
@@ -776,8 +775,6 @@
 
     kw = lookup_keyword(args[0]);
     switch (kw) {
-    case K_capability:
-        break;
     case K_class:
         if (nargs != 2) {
             parse_error(state, "class option requires a classname\n");
diff --git a/init/keywords.h b/init/keywords.h
index 34cb2ad..4bd0ba6 100644
--- a/init/keywords.h
+++ b/init/keywords.h
@@ -45,7 +45,6 @@
 enum {
     K_UNKNOWN,
 #endif
-    KEYWORD(capability,  OPTION,  0, 0)
     KEYWORD(class,       OPTION,  0, 0)
     KEYWORD(class_start, COMMAND, 1, do_class_start)
     KEYWORD(class_stop,  COMMAND, 1, do_class_stop)
diff --git a/libbacktrace/Android.build.mk b/libbacktrace/Android.build.mk
index d7eaa68..35fed6d 100644
--- a/libbacktrace/Android.build.mk
+++ b/libbacktrace/Android.build.mk
@@ -19,28 +19,37 @@
 LOCAL_MODULE := $(module)
 LOCAL_MODULE_TAGS := $(module_tag)
 LOCAL_MULTILIB := $($(module)_multilib)
+ifeq ($(LOCAL_MULTILIB),both)
+ifneq ($(build_target),$(filter $(build_target),SHARED_LIBRARY STATIC_LIBRRARY))
+  LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+  LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
+endif
+endif
 
 LOCAL_ADDITIONAL_DEPENDENCIES := \
     $(LOCAL_PATH)/Android.mk \
     $(LOCAL_PATH)/Android.build.mk \
 
 LOCAL_CFLAGS := \
-    $(common_cflags) \
+    $(libbacktrace_common_cflags) \
     $($(module)_cflags) \
     $($(module)_cflags_$(build_type)) \
 
+LOCAL_CLANG_CFLAGS += \
+    $(libbacktrace_common_clang_cflags) \
+
 LOCAL_CONLYFLAGS += \
-    $(common_conlyflags) \
+    $(libbacktrace_common_conlyflags) \
     $($(module)_conlyflags) \
     $($(module)_conlyflags_$(build_type)) \
 
 LOCAL_CPPFLAGS += \
-    $(common_cppflags) \
+    $(libbacktrace_common_cppflags) \
     $($(module)_cppflags) \
     $($(module)_cppflags_$(build_type)) \
 
 LOCAL_C_INCLUDES := \
-    $(common_c_includes) \
+    $(libbacktrace_common_c_includes) \
     $($(module)_c_includes) \
     $($(module)_c_includes_$(build_type)) \
 
diff --git a/libbacktrace/Android.mk b/libbacktrace/Android.mk
old mode 100755
new mode 100644
index f3b28dd..b875efd
--- a/libbacktrace/Android.mk
+++ b/libbacktrace/Android.mk
@@ -16,16 +16,20 @@
 
 LOCAL_PATH:= $(call my-dir)
 
-common_cflags := \
+libbacktrace_common_cflags := \
 	-Wall \
 	-Werror \
 
-common_conlyflags := \
+libbacktrace_common_conlyflags := \
 	-std=gnu99 \
 
-common_cppflags := \
+libbacktrace_common_cppflags := \
 	-std=gnu++11 \
 
+# The latest clang (r230699) does not allow SP/PC to be declared in inline asm lists.
+libbacktrace_common_clang_cflags += \
+    -Wno-inline-asm
+
 build_host := false
 ifeq ($(HOST_OS),linux)
 ifeq ($(HOST_ARCH),$(filter $(HOST_ARCH),x86 x86_64))
@@ -37,20 +41,21 @@
 # The libbacktrace library.
 #-------------------------------------------------------------------------
 libbacktrace_src_files := \
-	BacktraceImpl.cpp \
+	Backtrace.cpp \
+	BacktraceCurrent.cpp \
 	BacktraceMap.cpp \
-	BacktraceThread.cpp \
+	BacktracePtrace.cpp \
 	thread_utils.c \
-
-libbacktrace_shared_libraries_target := \
-	libcutils \
-
-libbacktrace_src_files += \
+	ThreadEntry.cpp \
 	UnwindCurrent.cpp \
 	UnwindMap.cpp \
 	UnwindPtrace.cpp \
 
+libbacktrace_shared_libraries_target := \
+	libcutils \
+
 libbacktrace_shared_libraries := \
+	libbase \
 	libunwind \
 	libunwind-ptrace \
 
@@ -86,6 +91,7 @@
 module_tag := debug
 build_type := target
 build_target := SHARED_LIBRARY
+libbacktrace_test_multilib := both
 include $(LOCAL_PATH)/Android.build.mk
 build_type := host
 include $(LOCAL_PATH)/Android.build.mk
@@ -124,6 +130,7 @@
 module_tag := debug
 build_type := target
 build_target := NATIVE_TEST
+backtrace_test_multilib := both
 include $(LOCAL_PATH)/Android.build.mk
 build_type := host
 include $(LOCAL_PATH)/Android.build.mk
diff --git a/libbacktrace/Backtrace.cpp b/libbacktrace/Backtrace.cpp
new file mode 100644
index 0000000..91ca8b7
--- /dev/null
+++ b/libbacktrace/Backtrace.cpp
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2013 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 <inttypes.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <ucontext.h>
+
+#include <string>
+
+#include <base/stringprintf.h>
+
+#include <backtrace/Backtrace.h>
+#include <backtrace/BacktraceMap.h>
+
+#include "BacktraceLog.h"
+#include "thread_utils.h"
+#include "UnwindCurrent.h"
+#include "UnwindPtrace.h"
+
+using android::base::StringPrintf;
+
+//-------------------------------------------------------------------------
+// Backtrace functions.
+//-------------------------------------------------------------------------
+Backtrace::Backtrace(pid_t pid, pid_t tid, BacktraceMap* map)
+    : pid_(pid), tid_(tid), map_(map), map_shared_(true) {
+  if (map_ == nullptr) {
+    map_ = BacktraceMap::Create(pid);
+    map_shared_ = false;
+  }
+}
+
+Backtrace::~Backtrace() {
+  if (map_ && !map_shared_) {
+    delete map_;
+    map_ = nullptr;
+  }
+}
+
+extern "C" char* __cxa_demangle(const char* mangled, char* buf, size_t* len,
+                                int* status);
+
+std::string Backtrace::GetFunctionName(uintptr_t pc, uintptr_t* offset) {
+  std::string func_name = GetFunctionNameRaw(pc, offset);
+  if (!func_name.empty()) {
+#if defined(__APPLE__)
+    // Mac OS' __cxa_demangle demangles "f" as "float"; last tested on 10.7.
+    if (func_name[0] != '_') {
+      return func_name;
+    }
+#endif
+    char* name = __cxa_demangle(func_name.c_str(), 0, 0, 0);
+    if (name) {
+      func_name = name;
+      free(name);
+    }
+  }
+  return func_name;
+}
+
+bool Backtrace::VerifyReadWordArgs(uintptr_t ptr, word_t* out_value) {
+  if (ptr & (sizeof(word_t)-1)) {
+    BACK_LOGW("invalid pointer %p", reinterpret_cast<void*>(ptr));
+    *out_value = static_cast<word_t>(-1);
+    return false;
+  }
+  return true;
+}
+
+std::string Backtrace::FormatFrameData(size_t frame_num) {
+  if (frame_num >= frames_.size()) {
+    return "";
+  }
+  return FormatFrameData(&frames_[frame_num]);
+}
+
+std::string Backtrace::FormatFrameData(const backtrace_frame_data_t* frame) {
+  const char* map_name;
+  if (BacktraceMap::IsValid(frame->map) && !frame->map.name.empty()) {
+    map_name = frame->map.name.c_str();
+  } else {
+    map_name = "<unknown>";
+  }
+
+  uintptr_t relative_pc;
+  if (BacktraceMap::IsValid(frame->map)) {
+    relative_pc = frame->pc - frame->map.start;
+  } else {
+    relative_pc = frame->pc;
+  }
+
+  std::string line(StringPrintf("#%02zu pc %" PRIPTR "  %s", frame->num, relative_pc, map_name));
+  if (!frame->func_name.empty()) {
+    line += " (" + frame->func_name;
+    if (frame->func_offset) {
+      line += StringPrintf("+%" PRIuPTR, frame->func_offset);
+    }
+    line += ')';
+  }
+
+  return line;
+}
+
+void Backtrace::FillInMap(uintptr_t pc, backtrace_map_t* map) {
+  map_->FillIn(pc, map);
+}
+
+Backtrace* Backtrace::Create(pid_t pid, pid_t tid, BacktraceMap* map) {
+  if (pid == BACKTRACE_CURRENT_PROCESS) {
+    pid = getpid();
+    if (tid == BACKTRACE_CURRENT_THREAD) {
+      tid = gettid();
+    }
+  } else if (tid == BACKTRACE_CURRENT_THREAD) {
+    tid = pid;
+  }
+
+  if (pid == getpid()) {
+    return new UnwindCurrent(pid, tid, map);
+  } else {
+    return new UnwindPtrace(pid, tid, map);
+  }
+}
diff --git a/libbacktrace/BacktraceCurrent.cpp b/libbacktrace/BacktraceCurrent.cpp
new file mode 100644
index 0000000..fd1f4da
--- /dev/null
+++ b/libbacktrace/BacktraceCurrent.cpp
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2013 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.
+ */
+
+#define _GNU_SOURCE 1
+#include <errno.h>
+#include <stdint.h>
+#include <string.h>
+#include <sys/param.h>
+#include <sys/ptrace.h>
+#include <sys/types.h>
+#include <ucontext.h>
+#include <unistd.h>
+
+#include <string>
+
+#include <backtrace/Backtrace.h>
+#include <backtrace/BacktraceMap.h>
+
+#include "BacktraceCurrent.h"
+#include "BacktraceLog.h"
+#include "ThreadEntry.h"
+#include "thread_utils.h"
+
+bool BacktraceCurrent::ReadWord(uintptr_t ptr, word_t* out_value) {
+  if (!VerifyReadWordArgs(ptr, out_value)) {
+    return false;
+  }
+
+  backtrace_map_t map;
+  FillInMap(ptr, &map);
+  if (BacktraceMap::IsValid(map) && map.flags & PROT_READ) {
+    *out_value = *reinterpret_cast<word_t*>(ptr);
+    return true;
+  } else {
+    BACK_LOGW("pointer %p not in a readable map", reinterpret_cast<void*>(ptr));
+    *out_value = static_cast<word_t>(-1);
+    return false;
+  }
+}
+
+size_t BacktraceCurrent::Read(uintptr_t addr, uint8_t* buffer, size_t bytes) {
+  backtrace_map_t map;
+  FillInMap(addr, &map);
+  if (!BacktraceMap::IsValid(map) || !(map.flags & PROT_READ)) {
+    return 0;
+  }
+  bytes = MIN(map.end - addr, bytes);
+  memcpy(buffer, reinterpret_cast<uint8_t*>(addr), bytes);
+  return bytes;
+}
+
+bool BacktraceCurrent::Unwind(size_t num_ignore_frames, ucontext_t* ucontext) {
+  if (ucontext) {
+    return UnwindFromContext(num_ignore_frames, ucontext);
+  }
+
+  if (Tid() != gettid()) {
+    return UnwindThread(num_ignore_frames);
+  }
+
+  return UnwindFromContext(num_ignore_frames, nullptr);
+}
+
+bool BacktraceCurrent::DiscardFrame(const backtrace_frame_data_t& frame) {
+  if (BacktraceMap::IsValid(frame.map)) {
+    const std::string library = basename(frame.map.name.c_str());
+    if (library == "libunwind.so" || library == "libbacktrace.so") {
+      return true;
+    }
+  }
+  return false;
+}
+
+static pthread_mutex_t g_sigaction_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+static void SignalHandler(int, siginfo_t*, void* sigcontext) {
+  ThreadEntry* entry = ThreadEntry::Get(getpid(), gettid(), false);
+  if (!entry) {
+    BACK_LOGW("Unable to find pid %d tid %d information", getpid(), gettid());
+    return;
+  }
+
+  entry->CopyUcontextFromSigcontext(sigcontext);
+
+  // Indicate the ucontext is now valid.
+  entry->Wake();
+
+  // Pause the thread until the unwind is complete. This avoids having
+  // the thread run ahead causing problems.
+  // The number indicates that we are waiting for the second Wake() call
+  // overall which is made by the thread requesting an unwind.
+  entry->Wait(2);
+
+  ThreadEntry::Remove(entry);
+}
+
+bool BacktraceCurrent::UnwindThread(size_t num_ignore_frames) {
+  // Prevent multiple threads trying to set the trigger action on different
+  // threads at the same time.
+  pthread_mutex_lock(&g_sigaction_mutex);
+
+  ThreadEntry* entry = ThreadEntry::Get(Pid(), Tid());
+  entry->Lock();
+
+  struct sigaction act, oldact;
+  memset(&act, 0, sizeof(act));
+  act.sa_sigaction = SignalHandler;
+  act.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK;
+  sigemptyset(&act.sa_mask);
+  if (sigaction(THREAD_SIGNAL, &act, &oldact) != 0) {
+    BACK_LOGW("sigaction failed %s", strerror(errno));
+    entry->Unlock();
+    ThreadEntry::Remove(entry);
+    pthread_mutex_unlock(&g_sigaction_mutex);
+    return false;
+  }
+
+  if (tgkill(Pid(), Tid(), THREAD_SIGNAL) != 0) {
+    BACK_LOGW("tgkill %d failed: %s", Tid(), strerror(errno));
+    sigaction(THREAD_SIGNAL, &oldact, nullptr);
+    entry->Unlock();
+    ThreadEntry::Remove(entry);
+    pthread_mutex_unlock(&g_sigaction_mutex);
+    return false;
+  }
+
+  // Wait for the thread to get the ucontext. The number indicates
+  // that we are waiting for the first Wake() call made by the thread.
+  entry->Wait(1);
+
+  // After the thread has received the signal, allow other unwinders to
+  // continue.
+  sigaction(THREAD_SIGNAL, &oldact, nullptr);
+  pthread_mutex_unlock(&g_sigaction_mutex);
+
+  bool unwind_done = UnwindFromContext(num_ignore_frames, entry->GetUcontext());
+
+  // Tell the signal handler to exit and release the entry.
+  entry->Wake();
+
+  return unwind_done;
+}
diff --git a/libbacktrace/BacktraceCurrent.h b/libbacktrace/BacktraceCurrent.h
new file mode 100644
index 0000000..8aad36d
--- /dev/null
+++ b/libbacktrace/BacktraceCurrent.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2013 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 _LIBBACKTRACE_BACKTRACE_CURRENT_H
+#define _LIBBACKTRACE_BACKTRACE_CURRENT_H
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <ucontext.h>
+
+#include <backtrace/Backtrace.h>
+
+// The signal used to cause a thread to dump the stack.
+#if defined(__GLIBC__)
+// In order to run the backtrace_tests on the host, we can't use
+// the internal real time signals used by GLIBC. To avoid this,
+// use SIGRTMIN for the signal to dump the stack.
+#define THREAD_SIGNAL SIGRTMIN
+#else
+#define THREAD_SIGNAL (__SIGRTMIN+1)
+#endif
+
+class BacktraceMap;
+
+class BacktraceCurrent : public Backtrace {
+public:
+  BacktraceCurrent(pid_t pid, pid_t tid, BacktraceMap* map) : Backtrace(pid, tid, map) {}
+  virtual ~BacktraceCurrent() {}
+
+  size_t Read(uintptr_t addr, uint8_t* buffer, size_t bytes) override;
+
+  bool ReadWord(uintptr_t ptr, word_t* out_value) override;
+
+  bool Unwind(size_t num_ignore_frames, ucontext_t* ucontext) override;
+
+protected:
+  bool DiscardFrame(const backtrace_frame_data_t& frame);
+
+private:
+  bool UnwindThread(size_t num_ignore_frames);
+
+  virtual bool UnwindFromContext(size_t num_ignore_frames, ucontext_t* ucontext) = 0;
+};
+
+#endif // _LIBBACKTRACE_BACKTRACE_CURRENT_H
diff --git a/libbacktrace/BacktraceImpl.cpp b/libbacktrace/BacktraceImpl.cpp
deleted file mode 100644
index 4650b6a..0000000
--- a/libbacktrace/BacktraceImpl.cpp
+++ /dev/null
@@ -1,283 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <errno.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/param.h>
-#include <sys/ptrace.h>
-#include <sys/types.h>
-#include <ucontext.h>
-#include <unistd.h>
-
-#include <string>
-
-#include <backtrace/Backtrace.h>
-#include <backtrace/BacktraceMap.h>
-
-#include "BacktraceImpl.h"
-#include "BacktraceLog.h"
-#include "thread_utils.h"
-
-//-------------------------------------------------------------------------
-// Backtrace functions.
-//-------------------------------------------------------------------------
-Backtrace::Backtrace(BacktraceImpl* impl, pid_t pid, BacktraceMap* map)
-    : pid_(pid), tid_(-1), map_(map), map_shared_(true), impl_(impl) {
-  impl_->SetParent(this);
-
-  if (map_ == NULL) {
-    map_ = BacktraceMap::Create(pid);
-    map_shared_ = false;
-  }
-}
-
-Backtrace::~Backtrace() {
-  if (impl_) {
-    delete impl_;
-    impl_ = NULL;
-  }
-
-  if (map_ && !map_shared_) {
-    delete map_;
-    map_ = NULL;
-  }
-}
-
-bool Backtrace::Unwind(size_t num_ignore_frames, ucontext_t* ucontext) {
-  return impl_->Unwind(num_ignore_frames, ucontext);
-}
-
-extern "C" char* __cxa_demangle(const char* mangled, char* buf, size_t* len,
-                                int* status);
-
-std::string Backtrace::GetFunctionName(uintptr_t pc, uintptr_t* offset) {
-  std::string func_name = impl_->GetFunctionNameRaw(pc, offset);
-  if (!func_name.empty()) {
-#if defined(__APPLE__)
-    // Mac OS' __cxa_demangle demangles "f" as "float"; last tested on 10.7.
-    if (func_name[0] != '_') {
-      return func_name;
-    }
-#endif
-    char* name = __cxa_demangle(func_name.c_str(), 0, 0, 0);
-    if (name) {
-      func_name = name;
-      free(name);
-    }
-  }
-  return func_name;
-}
-
-bool Backtrace::VerifyReadWordArgs(uintptr_t ptr, word_t* out_value) {
-  if (ptr & (sizeof(word_t)-1)) {
-    BACK_LOGW("invalid pointer %p", (void*)ptr);
-    *out_value = (word_t)-1;
-    return false;
-  }
-  return true;
-}
-
-std::string Backtrace::FormatFrameData(size_t frame_num) {
-  if (frame_num >= frames_.size()) {
-    return "";
-  }
-  return FormatFrameData(&frames_[frame_num]);
-}
-
-std::string Backtrace::FormatFrameData(const backtrace_frame_data_t* frame) {
-  const char* map_name;
-  if (BacktraceMap::IsValid(frame->map) && !frame->map.name.empty()) {
-    map_name = frame->map.name.c_str();
-  } else {
-    map_name = "<unknown>";
-  }
-
-  uintptr_t relative_pc;
-  if (BacktraceMap::IsValid(frame->map)) {
-    relative_pc = frame->pc - frame->map.start;
-  } else {
-    relative_pc = frame->pc;
-  }
-
-  char buf[512];
-  if (!frame->func_name.empty() && frame->func_offset) {
-    snprintf(buf, sizeof(buf), "#%02zu pc %0*" PRIxPTR "  %s (%s+%" PRIuPTR ")",
-             frame->num, (int)sizeof(uintptr_t)*2, relative_pc, map_name,
-             frame->func_name.c_str(), frame->func_offset);
-  } else if (!frame->func_name.empty()) {
-    snprintf(buf, sizeof(buf), "#%02zu pc %0*" PRIxPTR "  %s (%s)", frame->num,
-             (int)sizeof(uintptr_t)*2, relative_pc, map_name, frame->func_name.c_str());
-  } else {
-    snprintf(buf, sizeof(buf), "#%02zu pc %0*" PRIxPTR "  %s", frame->num,
-             (int)sizeof(uintptr_t)*2, relative_pc, map_name);
-  }
-
-  return buf;
-}
-
-void Backtrace::FillInMap(uintptr_t pc, backtrace_map_t* map) {
-  map_->FillIn(pc, map);
-}
-
-//-------------------------------------------------------------------------
-// BacktraceCurrent functions.
-//-------------------------------------------------------------------------
-BacktraceCurrent::BacktraceCurrent(
-    BacktraceImpl* impl, BacktraceMap* map) : Backtrace(impl, getpid(), map) {
-}
-
-BacktraceCurrent::~BacktraceCurrent() {
-}
-
-bool BacktraceCurrent::ReadWord(uintptr_t ptr, word_t* out_value) {
-  if (!VerifyReadWordArgs(ptr, out_value)) {
-    return false;
-  }
-
-  backtrace_map_t map;
-  FillInMap(ptr, &map);
-  if (BacktraceMap::IsValid(map) && map.flags & PROT_READ) {
-    *out_value = *reinterpret_cast<word_t*>(ptr);
-    return true;
-  } else {
-    BACK_LOGW("pointer %p not in a readable map", reinterpret_cast<void*>(ptr));
-    *out_value = static_cast<word_t>(-1);
-    return false;
-  }
-}
-
-size_t BacktraceCurrent::Read(uintptr_t addr, uint8_t* buffer, size_t bytes) {
-  backtrace_map_t map;
-  FillInMap(addr, &map);
-  if (!BacktraceMap::IsValid(map) || !(map.flags & PROT_READ)) {
-    return 0;
-  }
-  bytes = MIN(map.end - addr, bytes);
-  memcpy(buffer, reinterpret_cast<uint8_t*>(addr), bytes);
-  return bytes;
-}
-
-//-------------------------------------------------------------------------
-// BacktracePtrace functions.
-//-------------------------------------------------------------------------
-BacktracePtrace::BacktracePtrace(
-    BacktraceImpl* impl, pid_t pid, pid_t tid, BacktraceMap* map)
-    : Backtrace(impl, pid, map) {
-  tid_ = tid;
-}
-
-BacktracePtrace::~BacktracePtrace() {
-}
-
-#if !defined(__APPLE__)
-static bool PtraceRead(pid_t tid, uintptr_t addr, word_t* out_value) {
-  // ptrace() returns -1 and sets errno when the operation fails.
-  // To disambiguate -1 from a valid result, we clear errno beforehand.
-  errno = 0;
-  *out_value = ptrace(PTRACE_PEEKTEXT, tid, reinterpret_cast<void*>(addr), NULL);
-  if (*out_value == static_cast<word_t>(-1) && errno) {
-    BACK_LOGW("invalid pointer %p reading from tid %d, ptrace() strerror(errno)=%s",
-              reinterpret_cast<void*>(addr), tid, strerror(errno));
-    return false;
-  }
-  return true;
-}
-#endif
-
-bool BacktracePtrace::ReadWord(uintptr_t ptr, word_t* out_value) {
-#if defined(__APPLE__)
-  BACK_LOGW("MacOS does not support reading from another pid.");
-  return false;
-#else
-  if (!VerifyReadWordArgs(ptr, out_value)) {
-    return false;
-  }
-
-  backtrace_map_t map;
-  FillInMap(ptr, &map);
-  if (!BacktraceMap::IsValid(map) || !(map.flags & PROT_READ)) {
-    return false;
-  }
-
-  return PtraceRead(Tid(), ptr, out_value);
-#endif
-}
-
-size_t BacktracePtrace::Read(uintptr_t addr, uint8_t* buffer, size_t bytes) {
-#if defined(__APPLE__)
-  BACK_LOGW("MacOS does not support reading from another pid.");
-  return 0;
-#else
-  backtrace_map_t map;
-  FillInMap(addr, &map);
-  if (!BacktraceMap::IsValid(map) || !(map.flags & PROT_READ)) {
-    return 0;
-  }
-
-  bytes = MIN(map.end - addr, bytes);
-  size_t bytes_read = 0;
-  word_t data_word;
-  size_t align_bytes = addr & (sizeof(word_t) - 1);
-  if (align_bytes != 0) {
-    if (!PtraceRead(Tid(), addr & ~(sizeof(word_t) - 1), &data_word)) {
-      return 0;
-    }
-    align_bytes = sizeof(word_t) - align_bytes;
-    memcpy(buffer, reinterpret_cast<uint8_t*>(&data_word) + sizeof(word_t) - align_bytes,
-           align_bytes);
-    addr += align_bytes;
-    buffer += align_bytes;
-    bytes -= align_bytes;
-    bytes_read += align_bytes;
-  }
-
-  size_t num_words = bytes / sizeof(word_t);
-  for (size_t i = 0; i < num_words; i++) {
-    if (!PtraceRead(Tid(), addr, &data_word)) {
-      return bytes_read;
-    }
-    memcpy(buffer, &data_word, sizeof(word_t));
-    buffer += sizeof(word_t);
-    addr += sizeof(word_t);
-    bytes_read += sizeof(word_t);
-  }
-
-  size_t left_over = bytes & (sizeof(word_t) - 1);
-  if (left_over) {
-    if (!PtraceRead(Tid(), addr, &data_word)) {
-      return bytes_read;
-    }
-    memcpy(buffer, &data_word, left_over);
-    bytes_read += left_over;
-  }
-  return bytes_read;
-#endif
-}
-
-Backtrace* Backtrace::Create(pid_t pid, pid_t tid, BacktraceMap* map) {
-  if (pid == BACKTRACE_CURRENT_PROCESS || pid == getpid()) {
-    if (tid == BACKTRACE_CURRENT_THREAD || tid == gettid()) {
-      return CreateCurrentObj(map);
-    } else {
-      return CreateThreadObj(tid, map);
-    }
-  } else if (tid == BACKTRACE_CURRENT_THREAD) {
-    return CreatePtraceObj(pid, pid, map);
-  } else {
-    return CreatePtraceObj(pid, tid, map);
-  }
-}
diff --git a/libbacktrace/BacktraceImpl.h b/libbacktrace/BacktraceImpl.h
deleted file mode 100755
index 18c3cb5..0000000
--- a/libbacktrace/BacktraceImpl.h
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright (C) 2013 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 _LIBBACKTRACE_BACKTRACE_IMPL_H
-#define _LIBBACKTRACE_BACKTRACE_IMPL_H
-
-#include <backtrace/Backtrace.h>
-#include <backtrace/BacktraceMap.h>
-
-#include <sys/types.h>
-
-class BacktraceImpl {
-public:
-  virtual ~BacktraceImpl() { }
-
-  virtual bool Unwind(size_t num_ignore_frames, ucontext_t* ucontext) = 0;
-
-  // The name returned is not demangled, Backtrace::GetFunctionName()
-  // takes care of demangling the name.
-  virtual std::string GetFunctionNameRaw(uintptr_t pc, uintptr_t* offset) = 0;
-
-  void SetParent(Backtrace* backtrace) { backtrace_obj_ = backtrace; }
-
-  inline pid_t Pid() { return backtrace_obj_->Pid(); }
-  inline pid_t Tid() { return backtrace_obj_->Tid(); }
-
-  inline void FillInMap(uintptr_t addr, backtrace_map_t* map) {
-    backtrace_obj_->FillInMap(addr, map);
-  }
-  inline std::string GetFunctionName(uintptr_t pc, uintptr_t* offset) {
-    return backtrace_obj_->GetFunctionName(pc, offset);
-  }
-  inline BacktraceMap* GetMap() { return backtrace_obj_->GetMap(); }
-
-protected:
-  inline std::vector<backtrace_frame_data_t>* GetFrames() { return &backtrace_obj_->frames_; }
-
-  Backtrace* backtrace_obj_;
-};
-
-class BacktraceCurrent : public Backtrace {
-public:
-  BacktraceCurrent(BacktraceImpl* impl, BacktraceMap* map);
-  virtual ~BacktraceCurrent();
-
-  size_t Read(uintptr_t addr, uint8_t* buffer, size_t bytes);
-
-  bool ReadWord(uintptr_t ptr, word_t* out_value);
-};
-
-class BacktracePtrace : public Backtrace {
-public:
-  BacktracePtrace(BacktraceImpl* impl, pid_t pid, pid_t tid, BacktraceMap* map);
-  virtual ~BacktracePtrace();
-
-  size_t Read(uintptr_t addr, uint8_t* buffer, size_t bytes);
-
-  bool ReadWord(uintptr_t ptr, word_t* out_value);
-};
-
-Backtrace* CreateCurrentObj(BacktraceMap* map);
-Backtrace* CreatePtraceObj(pid_t pid, pid_t tid, BacktraceMap* map);
-Backtrace* CreateThreadObj(pid_t tid, BacktraceMap* map);
-
-#endif // _LIBBACKTRACE_BACKTRACE_IMPL_H
diff --git a/libbacktrace/BacktraceLog.h b/libbacktrace/BacktraceLog.h
old mode 100755
new mode 100644
diff --git a/libbacktrace/BacktraceMap.cpp b/libbacktrace/BacktraceMap.cpp
index 82a4085..b0ada46 100644
--- a/libbacktrace/BacktraceMap.cpp
+++ b/libbacktrace/BacktraceMap.cpp
@@ -15,18 +15,15 @@
  */
 
 #include <ctype.h>
+#include <stdint.h>
 #include <sys/types.h>
 #include <unistd.h>
 
-#include <string>
-#include <vector>
-
 #include <backtrace/backtrace_constants.h>
 #include <backtrace/BacktraceMap.h>
 #include <log/log.h>
 
 #include "thread_utils.h"
-#include "BacktraceImpl.h"
 
 BacktraceMap::BacktraceMap(pid_t pid) : pid_(pid) {
   if (pid_ < 0) {
@@ -116,7 +113,7 @@
   snprintf(path, sizeof(path), "/proc/%d/maps", pid_);
   FILE* fp = fopen(path, "r");
 #endif
-  if (fp == NULL) {
+  if (fp == nullptr) {
     return false;
   }
 
@@ -142,7 +139,7 @@
   BacktraceMap* map = new BacktraceMap(pid);
   if (!map->Build()) {
     delete map;
-    return NULL;
+    return nullptr;
   }
   return map;
 }
diff --git a/libbacktrace/BacktracePtrace.cpp b/libbacktrace/BacktracePtrace.cpp
new file mode 100644
index 0000000..6134438
--- /dev/null
+++ b/libbacktrace/BacktracePtrace.cpp
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <errno.h>
+#include <stdint.h>
+#include <string.h>
+#include <sys/param.h>
+#include <sys/ptrace.h>
+#include <sys/types.h>
+#include <ucontext.h>
+#include <unistd.h>
+
+#include <backtrace/Backtrace.h>
+#include <backtrace/BacktraceMap.h>
+
+#include "BacktraceLog.h"
+#include "BacktracePtrace.h"
+#include "thread_utils.h"
+
+#if !defined(__APPLE__)
+static bool PtraceRead(pid_t tid, uintptr_t addr, word_t* out_value) {
+  // ptrace() returns -1 and sets errno when the operation fails.
+  // To disambiguate -1 from a valid result, we clear errno beforehand.
+  errno = 0;
+  *out_value = ptrace(PTRACE_PEEKTEXT, tid, reinterpret_cast<void*>(addr), nullptr);
+  if (*out_value == static_cast<word_t>(-1) && errno) {
+    BACK_LOGW("invalid pointer %p reading from tid %d, ptrace() strerror(errno)=%s",
+              reinterpret_cast<void*>(addr), tid, strerror(errno));
+    return false;
+  }
+  return true;
+}
+#endif
+
+bool BacktracePtrace::ReadWord(uintptr_t ptr, word_t* out_value) {
+#if defined(__APPLE__)
+  BACK_LOGW("MacOS does not support reading from another pid.");
+  return false;
+#else
+  if (!VerifyReadWordArgs(ptr, out_value)) {
+    return false;
+  }
+
+  backtrace_map_t map;
+  FillInMap(ptr, &map);
+  if (!BacktraceMap::IsValid(map) || !(map.flags & PROT_READ)) {
+    return false;
+  }
+
+  return PtraceRead(Tid(), ptr, out_value);
+#endif
+}
+
+size_t BacktracePtrace::Read(uintptr_t addr, uint8_t* buffer, size_t bytes) {
+#if defined(__APPLE__)
+  BACK_LOGW("MacOS does not support reading from another pid.");
+  return 0;
+#else
+  backtrace_map_t map;
+  FillInMap(addr, &map);
+  if (!BacktraceMap::IsValid(map) || !(map.flags & PROT_READ)) {
+    return 0;
+  }
+
+  bytes = MIN(map.end - addr, bytes);
+  size_t bytes_read = 0;
+  word_t data_word;
+  size_t align_bytes = addr & (sizeof(word_t) - 1);
+  if (align_bytes != 0) {
+    if (!PtraceRead(Tid(), addr & ~(sizeof(word_t) - 1), &data_word)) {
+      return 0;
+    }
+    align_bytes = sizeof(word_t) - align_bytes;
+    memcpy(buffer, reinterpret_cast<uint8_t*>(&data_word) + sizeof(word_t) - align_bytes,
+           align_bytes);
+    addr += align_bytes;
+    buffer += align_bytes;
+    bytes -= align_bytes;
+    bytes_read += align_bytes;
+  }
+
+  size_t num_words = bytes / sizeof(word_t);
+  for (size_t i = 0; i < num_words; i++) {
+    if (!PtraceRead(Tid(), addr, &data_word)) {
+      return bytes_read;
+    }
+    memcpy(buffer, &data_word, sizeof(word_t));
+    buffer += sizeof(word_t);
+    addr += sizeof(word_t);
+    bytes_read += sizeof(word_t);
+  }
+
+  size_t left_over = bytes & (sizeof(word_t) - 1);
+  if (left_over) {
+    if (!PtraceRead(Tid(), addr, &data_word)) {
+      return bytes_read;
+    }
+    memcpy(buffer, &data_word, left_over);
+    bytes_read += left_over;
+  }
+  return bytes_read;
+#endif
+}
diff --git a/libbacktrace/BacktracePtrace.h b/libbacktrace/BacktracePtrace.h
new file mode 100644
index 0000000..1d49811
--- /dev/null
+++ b/libbacktrace/BacktracePtrace.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2013 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 _LIBBACKTRACE_BACKTRACE_PTRACE_H
+#define _LIBBACKTRACE_BACKTRACE_PTRACE_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <backtrace/Backtrace.h>
+
+class BacktraceMap;
+
+class BacktracePtrace : public Backtrace {
+public:
+  BacktracePtrace(pid_t pid, pid_t tid, BacktraceMap* map) : Backtrace(pid, tid, map) {}
+  virtual ~BacktracePtrace() {}
+
+  size_t Read(uintptr_t addr, uint8_t* buffer, size_t bytes);
+
+  bool ReadWord(uintptr_t ptr, word_t* out_value);
+};
+
+#endif // _LIBBACKTRACE_BACKTRACE_PTRACE_H
diff --git a/libbacktrace/BacktraceThread.cpp b/libbacktrace/BacktraceThread.cpp
deleted file mode 100644
index 439cc3b..0000000
--- a/libbacktrace/BacktraceThread.cpp
+++ /dev/null
@@ -1,227 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <errno.h>
-#include <inttypes.h>
-#include <limits.h>
-#include <pthread.h>
-#include <signal.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/syscall.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <ucontext.h>
-#include <unistd.h>
-
-#include <cutils/atomic.h>
-
-#include "BacktraceLog.h"
-#include "BacktraceThread.h"
-#include "thread_utils.h"
-
-//-------------------------------------------------------------------------
-// ThreadEntry implementation.
-//-------------------------------------------------------------------------
-ThreadEntry* ThreadEntry::list_ = NULL;
-pthread_mutex_t ThreadEntry::list_mutex_ = PTHREAD_MUTEX_INITIALIZER;
-
-// Assumes that ThreadEntry::list_mutex_ has already been locked before
-// creating a ThreadEntry object.
-ThreadEntry::ThreadEntry(pid_t pid, pid_t tid)
-    : pid_(pid), tid_(tid), ref_count_(1), mutex_(PTHREAD_MUTEX_INITIALIZER),
-      wait_mutex_(PTHREAD_MUTEX_INITIALIZER), wait_value_(0),
-      next_(ThreadEntry::list_), prev_(NULL) {
-  pthread_condattr_t attr;
-  pthread_condattr_init(&attr);
-  pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
-  pthread_cond_init(&wait_cond_, &attr);
-
-  // Add ourselves to the list.
-  if (ThreadEntry::list_) {
-    ThreadEntry::list_->prev_ = this;
-  }
-  ThreadEntry::list_ = this;
-}
-
-ThreadEntry* ThreadEntry::Get(pid_t pid, pid_t tid, bool create) {
-  pthread_mutex_lock(&ThreadEntry::list_mutex_);
-  ThreadEntry* entry = list_;
-  while (entry != NULL) {
-    if (entry->Match(pid, tid)) {
-      break;
-    }
-    entry = entry->next_;
-  }
-
-  if (!entry) {
-    if (create) {
-      entry = new ThreadEntry(pid, tid);
-    }
-  } else {
-    entry->ref_count_++;
-  }
-  pthread_mutex_unlock(&ThreadEntry::list_mutex_);
-
-  return entry;
-}
-
-void ThreadEntry::Remove(ThreadEntry* entry) {
-  pthread_mutex_unlock(&entry->mutex_);
-
-  pthread_mutex_lock(&ThreadEntry::list_mutex_);
-  if (--entry->ref_count_ == 0) {
-    delete entry;
-  }
-  pthread_mutex_unlock(&ThreadEntry::list_mutex_);
-}
-
-// Assumes that ThreadEntry::list_mutex_ has already been locked before
-// deleting a ThreadEntry object.
-ThreadEntry::~ThreadEntry() {
-  if (list_ == this) {
-    list_ = next_;
-  } else {
-    if (next_) {
-      next_->prev_ = prev_;
-    }
-    prev_->next_ = next_;
-  }
-
-  next_ = NULL;
-  prev_ = NULL;
-
-  pthread_cond_destroy(&wait_cond_);
-}
-
-void ThreadEntry::Wait(int value) {
-  timespec ts;
-  if (clock_gettime(CLOCK_MONOTONIC, &ts) == -1) {
-    BACK_LOGW("clock_gettime failed: %s", strerror(errno));
-    abort();
-  }
-  ts.tv_sec += 10;
-
-  pthread_mutex_lock(&wait_mutex_);
-  while (wait_value_ != value) {
-    int ret = pthread_cond_timedwait(&wait_cond_, &wait_mutex_, &ts);
-    if (ret != 0) {
-      BACK_LOGW("pthread_cond_timedwait failed: %s", strerror(ret));
-      break;
-    }
-  }
-  pthread_mutex_unlock(&wait_mutex_);
-}
-
-void ThreadEntry::Wake() {
-  pthread_mutex_lock(&wait_mutex_);
-  wait_value_++;
-  pthread_mutex_unlock(&wait_mutex_);
-
-  pthread_cond_signal(&wait_cond_);
-}
-
-void ThreadEntry::CopyUcontextFromSigcontext(void* sigcontext) {
-  ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(sigcontext);
-  // The only thing the unwinder cares about is the mcontext data.
-  memcpy(&ucontext_.uc_mcontext, &ucontext->uc_mcontext, sizeof(ucontext->uc_mcontext));
-}
-
-//-------------------------------------------------------------------------
-// BacktraceThread functions.
-//-------------------------------------------------------------------------
-static pthread_mutex_t g_sigaction_mutex = PTHREAD_MUTEX_INITIALIZER;
-
-static void SignalHandler(int, siginfo_t*, void* sigcontext) {
-  ThreadEntry* entry = ThreadEntry::Get(getpid(), gettid(), false);
-  if (!entry) {
-    BACK_LOGW("Unable to find pid %d tid %d information", getpid(), gettid());
-    return;
-  }
-
-  entry->CopyUcontextFromSigcontext(sigcontext);
-
-  // Indicate the ucontext is now valid.
-  entry->Wake();
-
-  // Pause the thread until the unwind is complete. This avoids having
-  // the thread run ahead causing problems.
-  entry->Wait(2);
-
-  ThreadEntry::Remove(entry);
-}
-
-BacktraceThread::BacktraceThread(BacktraceImpl* impl, pid_t tid, BacktraceMap* map)
-    : BacktraceCurrent(impl, map) {
-  tid_ = tid;
-}
-
-BacktraceThread::~BacktraceThread() {
-}
-
-bool BacktraceThread::Unwind(size_t num_ignore_frames, ucontext_t* ucontext) {
-  if (ucontext) {
-    // Unwind using an already existing ucontext.
-    return impl_->Unwind(num_ignore_frames, ucontext);
-  }
-
-  // Prevent multiple threads trying to set the trigger action on different
-  // threads at the same time.
-  if (pthread_mutex_lock(&g_sigaction_mutex) < 0) {
-    BACK_LOGW("sigaction failed: %s", strerror(errno));
-    return false;
-  }
-
-  ThreadEntry* entry = ThreadEntry::Get(Pid(), Tid());
-  entry->Lock();
-
-  struct sigaction act, oldact;
-  memset(&act, 0, sizeof(act));
-  act.sa_sigaction = SignalHandler;
-  act.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK;
-  sigemptyset(&act.sa_mask);
-  if (sigaction(THREAD_SIGNAL, &act, &oldact) != 0) {
-    BACK_LOGW("sigaction failed %s", strerror(errno));
-    entry->Unlock();
-    ThreadEntry::Remove(entry);
-    pthread_mutex_unlock(&g_sigaction_mutex);
-    return false;
-  }
-
-  if (tgkill(Pid(), Tid(), THREAD_SIGNAL) != 0) {
-    BACK_LOGW("tgkill %d failed: %s", Tid(), strerror(errno));
-    sigaction(THREAD_SIGNAL, &oldact, NULL);
-    entry->Unlock();
-    ThreadEntry::Remove(entry);
-    pthread_mutex_unlock(&g_sigaction_mutex);
-    return false;
-  }
-
-  // Wait for the thread to get the ucontext.
-  entry->Wait(1);
-
-  // After the thread has received the signal, allow other unwinders to
-  // continue.
-  sigaction(THREAD_SIGNAL, &oldact, NULL);
-  pthread_mutex_unlock(&g_sigaction_mutex);
-
-  bool unwind_done = impl_->Unwind(num_ignore_frames, entry->GetUcontext());
-
-  // Tell the signal handler to exit and release the entry.
-  entry->Wake();
-
-  return unwind_done;
-}
diff --git a/libbacktrace/GetPss.cpp b/libbacktrace/GetPss.cpp
index 442383b..09a721d 100644
--- a/libbacktrace/GetPss.cpp
+++ b/libbacktrace/GetPss.cpp
@@ -14,11 +14,10 @@
  * limitations under the License.
  */
 
-#include <assert.h>
 #include <inttypes.h>
+#include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
-#include <stdint.h>
 #include <sys/types.h>
 #include <unistd.h>
 #include <fcntl.h>
@@ -46,13 +45,22 @@
 
 size_t GetPssBytes() {
   FILE* maps = fopen("/proc/self/maps", "r");
-  assert(maps != NULL);
+  if (maps == nullptr) {
+    return 0;
+  }
 
   int pagecount_fd = open("/proc/kpagecount", O_RDONLY);
-  assert(pagecount_fd >= 0);
+  if (pagecount_fd == -1) {
+    fclose(maps);
+    return 0;
+  }
 
   int pagemap_fd = open("/proc/self/pagemap", O_RDONLY);
-  assert(pagemap_fd >= 0);
+  if (pagemap_fd == -1) {
+    fclose(maps);
+    close(pagecount_fd);
+    return 0;
+  }
 
   char line[4096];
   size_t total_pss = 0;
diff --git a/libbacktrace/ThreadEntry.cpp b/libbacktrace/ThreadEntry.cpp
new file mode 100644
index 0000000..e8b60c8
--- /dev/null
+++ b/libbacktrace/ThreadEntry.cpp
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <pthread.h>
+#include <stdint.h>
+#include <string.h>
+#include <sys/types.h>
+#include <time.h>
+#include <ucontext.h>
+
+#include "BacktraceLog.h"
+#include "ThreadEntry.h"
+
+// Initialize static member variables.
+ThreadEntry* ThreadEntry::list_ = nullptr;
+pthread_mutex_t ThreadEntry::list_mutex_ = PTHREAD_MUTEX_INITIALIZER;
+
+// Assumes that ThreadEntry::list_mutex_ has already been locked before
+// creating a ThreadEntry object.
+ThreadEntry::ThreadEntry(pid_t pid, pid_t tid)
+    : pid_(pid), tid_(tid), ref_count_(1), mutex_(PTHREAD_MUTEX_INITIALIZER),
+      wait_mutex_(PTHREAD_MUTEX_INITIALIZER), wait_value_(0),
+      next_(ThreadEntry::list_), prev_(nullptr) {
+  pthread_condattr_t attr;
+  pthread_condattr_init(&attr);
+  pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
+  pthread_cond_init(&wait_cond_, &attr);
+
+  // Add ourselves to the list.
+  if (ThreadEntry::list_) {
+    ThreadEntry::list_->prev_ = this;
+  }
+  ThreadEntry::list_ = this;
+}
+
+ThreadEntry* ThreadEntry::Get(pid_t pid, pid_t tid, bool create) {
+  pthread_mutex_lock(&ThreadEntry::list_mutex_);
+  ThreadEntry* entry = list_;
+  while (entry != nullptr) {
+    if (entry->Match(pid, tid)) {
+      break;
+    }
+    entry = entry->next_;
+  }
+
+  if (!entry) {
+    if (create) {
+      entry = new ThreadEntry(pid, tid);
+    }
+  } else {
+    entry->ref_count_++;
+  }
+  pthread_mutex_unlock(&ThreadEntry::list_mutex_);
+
+  return entry;
+}
+
+void ThreadEntry::Remove(ThreadEntry* entry) {
+  pthread_mutex_unlock(&entry->mutex_);
+
+  pthread_mutex_lock(&ThreadEntry::list_mutex_);
+  if (--entry->ref_count_ == 0) {
+    delete entry;
+  }
+  pthread_mutex_unlock(&ThreadEntry::list_mutex_);
+}
+
+// Assumes that ThreadEntry::list_mutex_ has already been locked before
+// deleting a ThreadEntry object.
+ThreadEntry::~ThreadEntry() {
+  if (list_ == this) {
+    list_ = next_;
+  } else {
+    if (next_) {
+      next_->prev_ = prev_;
+    }
+    prev_->next_ = next_;
+  }
+
+  next_ = nullptr;
+  prev_ = nullptr;
+
+  pthread_cond_destroy(&wait_cond_);
+}
+
+void ThreadEntry::Wait(int value) {
+  timespec ts;
+  clock_gettime(CLOCK_MONOTONIC, &ts);
+  ts.tv_sec += 10;
+
+  pthread_mutex_lock(&wait_mutex_);
+  while (wait_value_ != value) {
+    int ret = pthread_cond_timedwait(&wait_cond_, &wait_mutex_, &ts);
+    if (ret != 0) {
+      BACK_LOGW("pthread_cond_timedwait failed: %s", strerror(ret));
+      break;
+    }
+  }
+  pthread_mutex_unlock(&wait_mutex_);
+}
+
+void ThreadEntry::Wake() {
+  pthread_mutex_lock(&wait_mutex_);
+  wait_value_++;
+  pthread_mutex_unlock(&wait_mutex_);
+
+  pthread_cond_signal(&wait_cond_);
+}
+
+void ThreadEntry::CopyUcontextFromSigcontext(void* sigcontext) {
+  ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(sigcontext);
+  // The only thing the unwinder cares about is the mcontext data.
+  memcpy(&ucontext_.uc_mcontext, &ucontext->uc_mcontext, sizeof(ucontext->uc_mcontext));
+}
diff --git a/libbacktrace/BacktraceThread.h b/libbacktrace/ThreadEntry.h
similarity index 70%
rename from libbacktrace/BacktraceThread.h
rename to libbacktrace/ThreadEntry.h
index 99a8638..94becf2 100644
--- a/libbacktrace/BacktraceThread.h
+++ b/libbacktrace/ThreadEntry.h
@@ -14,26 +14,13 @@
  * limitations under the License.
  */
 
-#ifndef _LIBBACKTRACE_BACKTRACE_THREAD_H
-#define _LIBBACKTRACE_BACKTRACE_THREAD_H
+#ifndef _LIBBACKTRACE_THREAD_ENTRY_H
+#define _LIBBACKTRACE_THREAD_ENTRY_H
 
-#include <inttypes.h>
 #include <pthread.h>
-#include <signal.h>
-#include <string.h>
 #include <sys/types.h>
 #include <ucontext.h>
 
-#include "BacktraceImpl.h"
-
-// The signal used to cause a thread to dump the stack.
-#if defined(__GLIBC__)
-// GLIBC reserves __SIGRTMIN signals, so use SIGRTMIN to avoid errors.
-#define THREAD_SIGNAL SIGRTMIN
-#else
-#define THREAD_SIGNAL (__SIGRTMIN+1)
-#endif
-
 class ThreadEntry {
 public:
   static ThreadEntry* Get(pid_t pid, pid_t tid, bool create = true);
@@ -81,12 +68,4 @@
   static pthread_mutex_t list_mutex_;
 };
 
-class BacktraceThread : public BacktraceCurrent {
-public:
-  BacktraceThread(BacktraceImpl* impl, pid_t tid, BacktraceMap* map);
-  virtual ~BacktraceThread();
-
-  virtual bool Unwind(size_t num_ignore_frames, ucontext_t* ucontext);
-};
-
-#endif // _LIBBACKTRACE_BACKTRACE_THREAD_H
+#endif // _LIBBACKTRACE_THREAD_ENTRY_H
diff --git a/libbacktrace/UnwindCurrent.cpp b/libbacktrace/UnwindCurrent.cpp
old mode 100755
new mode 100644
index 372555b..67e583f
--- a/libbacktrace/UnwindCurrent.cpp
+++ b/libbacktrace/UnwindCurrent.cpp
@@ -14,41 +14,30 @@
  * limitations under the License.
  */
 
-#include <sys/types.h>
+#include <stdint.h>
 #include <ucontext.h>
 
-#include <backtrace/Backtrace.h>
-#include <backtrace/BacktraceMap.h>
+#include <memory>
+#include <string>
 
 #define UNW_LOCAL_ONLY
 #include <libunwind.h>
 
+#include <backtrace/Backtrace.h>
+
 #include "BacktraceLog.h"
-#include "BacktraceThread.h"
 #include "UnwindCurrent.h"
-#include "UnwindMap.h"
 
-//-------------------------------------------------------------------------
-// UnwindCurrent functions.
-//-------------------------------------------------------------------------
-UnwindCurrent::UnwindCurrent() {
-}
-
-UnwindCurrent::~UnwindCurrent() {
-}
-
-bool UnwindCurrent::Unwind(size_t num_ignore_frames, ucontext_t* ucontext) {
-  if (!ucontext) {
-    int ret = unw_getcontext(&context_);
-    if (ret < 0) {
-      BACK_LOGW("unw_getcontext failed %d", ret);
-      return false;
-    }
+std::string UnwindCurrent::GetFunctionNameRaw(uintptr_t pc, uintptr_t* offset) {
+  *offset = 0;
+  char buf[512];
+  unw_word_t value;
+  if (unw_get_proc_name_by_ip(unw_local_addr_space, pc, buf, sizeof(buf),
+                              &value, &context_) >= 0 && buf[0] != '\0') {
+    *offset = static_cast<uintptr_t>(value);
+    return buf;
   }
-  else {
-    GetUnwContextFromUcontext(ucontext);
-  }
-  return UnwindFromContext(num_ignore_frames, false);
+  return "";
 }
 
 void UnwindCurrent::GetUnwContextFromUcontext(const ucontext_t* ucontext) {
@@ -76,89 +65,67 @@
 #endif
 }
 
-std::string UnwindCurrent::GetFunctionNameRaw(uintptr_t pc, uintptr_t* offset) {
-  *offset = 0;
-  char buf[512];
-  unw_word_t value;
-  if (unw_get_proc_name_by_ip(unw_local_addr_space, pc, buf, sizeof(buf),
-                              &value, &context_) >= 0 && buf[0] != '\0') {
-    *offset = static_cast<uintptr_t>(value);
-    return buf;
-  }
-  return "";
-}
-
-bool UnwindCurrent::UnwindFromContext(size_t num_ignore_frames, bool within_handler) {
-  // The cursor structure is pretty large, do not put it on the stack.
-  unw_cursor_t* cursor = new unw_cursor_t;
-  int ret = unw_init_local(cursor, &context_);
-  if (ret < 0) {
-    if (!within_handler) {
-      BACK_LOGW("unw_init_local failed %d", ret);
+bool UnwindCurrent::UnwindFromContext(size_t num_ignore_frames, ucontext_t* ucontext) {
+  if (ucontext == nullptr) {
+    int ret = unw_getcontext(&context_);
+    if (ret < 0) {
+      BACK_LOGW("unw_getcontext failed %d", ret);
+      return false;
     }
-    delete cursor;
+  } else {
+    GetUnwContextFromUcontext(ucontext);
+  }
+
+  // The cursor structure is pretty large, do not put it on the stack.
+  std::unique_ptr<unw_cursor_t> cursor(new unw_cursor_t);
+  int ret = unw_init_local(cursor.get(), &context_);
+  if (ret < 0) {
+    BACK_LOGW("unw_init_local failed %d", ret);
     return false;
   }
 
-  std::vector<backtrace_frame_data_t>* frames = GetFrames();
-  frames->reserve(MAX_BACKTRACE_FRAMES);
   size_t num_frames = 0;
   do {
     unw_word_t pc;
-    ret = unw_get_reg(cursor, UNW_REG_IP, &pc);
+    ret = unw_get_reg(cursor.get(), UNW_REG_IP, &pc);
     if (ret < 0) {
-      if (!within_handler) {
-        BACK_LOGW("Failed to read IP %d", ret);
-      }
+      BACK_LOGW("Failed to read IP %d", ret);
       break;
     }
     unw_word_t sp;
-    ret = unw_get_reg(cursor, UNW_REG_SP, &sp);
+    ret = unw_get_reg(cursor.get(), UNW_REG_SP, &sp);
     if (ret < 0) {
-      if (!within_handler) {
-        BACK_LOGW("Failed to read SP %d", ret);
-      }
+      BACK_LOGW("Failed to read SP %d", ret);
       break;
     }
 
-    if (num_ignore_frames == 0) {
-      frames->resize(num_frames+1);
-      backtrace_frame_data_t* frame = &frames->at(num_frames);
-      frame->num = num_frames;
-      frame->pc = static_cast<uintptr_t>(pc);
-      frame->sp = static_cast<uintptr_t>(sp);
-      frame->stack_size = 0;
+    frames_.resize(num_frames+1);
+    backtrace_frame_data_t* frame = &frames_.at(num_frames);
+    frame->num = num_frames;
+    frame->pc = static_cast<uintptr_t>(pc);
+    frame->sp = static_cast<uintptr_t>(sp);
+    frame->stack_size = 0;
 
-      if (num_frames > 0) {
-        // Set the stack size for the previous frame.
-        backtrace_frame_data_t* prev = &frames->at(num_frames-1);
-        prev->stack_size = frame->sp - prev->sp;
-      }
-
-      if (!within_handler) {
+    FillInMap(frame->pc, &frame->map);
+    // Check to see if we should skip this frame because it's coming
+    // from within the library, and we are doing a local unwind.
+    if (ucontext != nullptr || num_frames != 0 || !DiscardFrame(*frame)) {
+      if (num_ignore_frames == 0) {
+        // GetFunctionName is an expensive call, only do it if we are
+        // keeping the frame.
         frame->func_name = GetFunctionName(frame->pc, &frame->func_offset);
-        FillInMap(frame->pc, &frame->map);
+        if (num_frames > 0) {
+          // Set the stack size for the previous frame.
+          backtrace_frame_data_t* prev = &frames_.at(num_frames-1);
+          prev->stack_size = frame->sp - prev->sp;
+        }
+        num_frames++;
       } else {
-        frame->func_offset = 0;
+        num_ignore_frames--;
       }
-      num_frames++;
-    } else {
-      num_ignore_frames--;
     }
-    ret = unw_step (cursor);
+    ret = unw_step (cursor.get());
   } while (ret > 0 && num_frames < MAX_BACKTRACE_FRAMES);
 
-  delete cursor;
   return true;
 }
-
-//-------------------------------------------------------------------------
-// C++ object creation function.
-//-------------------------------------------------------------------------
-Backtrace* CreateCurrentObj(BacktraceMap* map) {
-  return new BacktraceCurrent(new UnwindCurrent(), map);
-}
-
-Backtrace* CreateThreadObj(pid_t tid, BacktraceMap* map) {
-  return new BacktraceThread(new UnwindCurrent(), tid, map);
-}
diff --git a/libbacktrace/UnwindCurrent.h b/libbacktrace/UnwindCurrent.h
index 2375e6e..3023996 100644
--- a/libbacktrace/UnwindCurrent.h
+++ b/libbacktrace/UnwindCurrent.h
@@ -17,27 +17,32 @@
 #ifndef _LIBBACKTRACE_UNWIND_CURRENT_H
 #define _LIBBACKTRACE_UNWIND_CURRENT_H
 
+#include <stdint.h>
+#include <sys/types.h>
+#include <ucontext.h>
+
 #include <string>
 
-#include "BacktraceImpl.h"
+#include <backtrace/Backtrace.h>
+#include <backtrace/BacktraceMap.h>
+
+#include "BacktraceCurrent.h"
 
 #define UNW_LOCAL_ONLY
 #include <libunwind.h>
 
-class UnwindCurrent : public BacktraceImpl {
+class UnwindCurrent : public BacktraceCurrent {
 public:
-  UnwindCurrent();
-  virtual ~UnwindCurrent();
+  UnwindCurrent(pid_t pid, pid_t tid, BacktraceMap* map) : BacktraceCurrent(pid, tid, map) {}
+  virtual ~UnwindCurrent() {}
 
-  virtual bool Unwind(size_t num_ignore_frames, ucontext_t* ucontext);
+  std::string GetFunctionNameRaw(uintptr_t pc, uintptr_t* offset) override;
 
-  virtual std::string GetFunctionNameRaw(uintptr_t pc, uintptr_t* offset);
+private:
+  void GetUnwContextFromUcontext(const ucontext_t* ucontext);
 
-  bool UnwindFromContext(size_t num_ignore_frames, bool within_handler);
+  bool UnwindFromContext(size_t num_ignore_frames, ucontext_t* ucontext) override;
 
-  void GetUnwContextFromUcontext(const ucontext_t* context);
-
-protected:
   unw_context_t context_;
 };
 
diff --git a/libbacktrace/UnwindMap.cpp b/libbacktrace/UnwindMap.cpp
index 284a561..fa59d07 100644
--- a/libbacktrace/UnwindMap.cpp
+++ b/libbacktrace/UnwindMap.cpp
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#include <pthread.h>
+#include <stdint.h>
 #include <stdlib.h>
 #include <sys/types.h>
 #include <unistd.h>
@@ -142,7 +142,7 @@
   }
   if (!map->Build()) {
     delete map;
-    return NULL;
+    return nullptr;
   }
   return map;
 }
diff --git a/libbacktrace/UnwindMap.h b/libbacktrace/UnwindMap.h
index be8855e..e292016 100644
--- a/libbacktrace/UnwindMap.h
+++ b/libbacktrace/UnwindMap.h
@@ -17,6 +17,9 @@
 #ifndef _LIBBACKTRACE_UNWIND_MAP_H
 #define _LIBBACKTRACE_UNWIND_MAP_H
 
+#include <stdint.h>
+#include <sys/types.h>
+
 #include <backtrace/BacktraceMap.h>
 
 // The unw_map_cursor_t structure is different depending on whether it is
diff --git a/libbacktrace/UnwindPtrace.cpp b/libbacktrace/UnwindPtrace.cpp
index efe758b..a7c3de5 100644
--- a/libbacktrace/UnwindPtrace.cpp
+++ b/libbacktrace/UnwindPtrace.cpp
@@ -14,35 +14,36 @@
  * limitations under the License.
  */
 
-#include <backtrace/Backtrace.h>
-#include <backtrace/BacktraceMap.h>
-
+#include <stdint.h>
 #include <sys/types.h>
-#include <string.h>
 #include <ucontext.h>
 
 #include <libunwind.h>
 #include <libunwind-ptrace.h>
 
+#include <backtrace/Backtrace.h>
+#include <backtrace/BacktraceMap.h>
+
 #include "BacktraceLog.h"
 #include "UnwindMap.h"
 #include "UnwindPtrace.h"
 
-UnwindPtrace::UnwindPtrace() : addr_space_(NULL), upt_info_(NULL) {
+UnwindPtrace::UnwindPtrace(pid_t pid, pid_t tid, BacktraceMap* map)
+    : BacktracePtrace(pid, tid, map), addr_space_(nullptr), upt_info_(nullptr) {
 }
 
 UnwindPtrace::~UnwindPtrace() {
   if (upt_info_) {
     _UPT_destroy(upt_info_);
-    upt_info_ = NULL;
+    upt_info_ = nullptr;
   }
   if (addr_space_) {
     // Remove the map from the address space before destroying it.
     // It will be freed in the UnwindMap destructor.
-    unw_map_set(addr_space_, NULL);
+    unw_map_set(addr_space_, nullptr);
 
     unw_destroy_addr_space(addr_space_);
-    addr_space_ = NULL;
+    addr_space_ = nullptr;
   }
 }
 
@@ -74,8 +75,6 @@
     return false;
   }
 
-  std::vector<backtrace_frame_data_t>* frames = GetFrames();
-  frames->reserve(MAX_BACKTRACE_FRAMES);
   size_t num_frames = 0;
   do {
     unw_word_t pc;
@@ -92,15 +91,15 @@
     }
 
     if (num_ignore_frames == 0) {
-      frames->resize(num_frames+1);
-      backtrace_frame_data_t* frame = &frames->at(num_frames);
+      frames_.resize(num_frames+1);
+      backtrace_frame_data_t* frame = &frames_.at(num_frames);
       frame->num = num_frames;
       frame->pc = static_cast<uintptr_t>(pc);
       frame->sp = static_cast<uintptr_t>(sp);
       frame->stack_size = 0;
 
       if (num_frames > 0) {
-        backtrace_frame_data_t* prev = &frames->at(num_frames-1);
+        backtrace_frame_data_t* prev = &frames_.at(num_frames-1);
         prev->stack_size = frame->sp - prev->sp;
       }
 
@@ -129,10 +128,3 @@
   }
   return "";
 }
-
-//-------------------------------------------------------------------------
-// C++ object creation function.
-//-------------------------------------------------------------------------
-Backtrace* CreatePtraceObj(pid_t pid, pid_t tid, BacktraceMap* map) {
-  return new BacktracePtrace(new UnwindPtrace(), pid, tid, map);
-}
diff --git a/libbacktrace/UnwindPtrace.h b/libbacktrace/UnwindPtrace.h
index 2fb7967..ab04abf 100644
--- a/libbacktrace/UnwindPtrace.h
+++ b/libbacktrace/UnwindPtrace.h
@@ -17,20 +17,26 @@
 #ifndef _LIBBACKTRACE_UNWIND_PTRACE_H
 #define _LIBBACKTRACE_UNWIND_PTRACE_H
 
+#include <stdint.h>
+#include <sys/types.h>
+
 #include <string>
 
-#include "BacktraceImpl.h"
-
+#ifdef UNW_LOCAL_ONLY
+#undef UNW_LOCAL_ONLY
+#endif
 #include <libunwind.h>
 
-class UnwindPtrace : public BacktraceImpl {
+#include "BacktracePtrace.h"
+
+class UnwindPtrace : public BacktracePtrace {
 public:
-  UnwindPtrace();
+  UnwindPtrace(pid_t pid, pid_t tid, BacktraceMap* map);
   virtual ~UnwindPtrace();
 
-  virtual bool Unwind(size_t num_ignore_frames, ucontext_t* ucontext);
+  bool Unwind(size_t num_ignore_frames, ucontext_t* ucontext) override;
 
-  virtual std::string GetFunctionNameRaw(uintptr_t pc, uintptr_t* offset);
+  std::string GetFunctionNameRaw(uintptr_t pc, uintptr_t* offset) override;
 
 private:
   unw_addr_space_t addr_space_;
diff --git a/libbacktrace/backtrace_test.cpp b/libbacktrace/backtrace_test.cpp
index b1e34bd..5de80b1 100644
--- a/libbacktrace/backtrace_test.cpp
+++ b/libbacktrace/backtrace_test.cpp
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#define _GNU_SOURCE 1
 #include <dirent.h>
 #include <errno.h>
 #include <inttypes.h>
@@ -33,13 +34,14 @@
 #include <backtrace/BacktraceMap.h>
 
 // For the THREAD_SIGNAL definition.
-#include "BacktraceThread.h"
+#include "BacktraceCurrent.h"
 
 #include <cutils/atomic.h>
 #include <gtest/gtest.h>
 
 #include <algorithm>
 #include <memory>
+#include <string>
 #include <vector>
 
 #include "thread_utils.h"
@@ -83,15 +85,16 @@
   return static_cast<uint64_t>(t.tv_sec * NS_PER_SEC + t.tv_nsec);
 }
 
-void DumpFrames(Backtrace* backtrace) {
+std::string DumpFrames(Backtrace* backtrace) {
   if (backtrace->NumFrames() == 0) {
-    printf("    No frames to dump\n");
-    return;
+    return "   No frames to dump\n";
   }
 
+  std::string frame;
   for (size_t i = 0; i < backtrace->NumFrames(); i++) {
-    printf("    %s\n", backtrace->FormatFrameData(i).c_str());
+    frame += "   " + backtrace->FormatFrameData(i) + '\n';
   }
+  return frame;
 }
 
 void WaitForStop(pid_t pid) {
@@ -133,8 +136,8 @@
       break;
     }
   }
-  ASSERT_LT(static_cast<size_t>(0), frame_num);
-  ASSERT_LE(static_cast<size_t>(3), frame_num);
+  ASSERT_LT(static_cast<size_t>(0), frame_num) << DumpFrames(backtrace);
+  ASSERT_LE(static_cast<size_t>(3), frame_num) << DumpFrames(backtrace);
 
   ASSERT_EQ(backtrace->GetFrame(frame_num)->func_name, "test_level_one");
   ASSERT_EQ(backtrace->GetFrame(frame_num-1)->func_name, "test_level_two");
@@ -198,6 +201,23 @@
   return false;
 }
 
+TEST(libbacktrace, local_no_unwind_frames) {
+  // Verify that a local unwind does not include any frames within
+  // libunwind or libbacktrace.
+  std::unique_ptr<Backtrace> backtrace(Backtrace::Create(getpid(), getpid()));
+  ASSERT_TRUE(backtrace->Unwind(0));
+
+  ASSERT_TRUE(backtrace->NumFrames() != 0);
+  for (const auto& frame : *backtrace ) {
+    if (BacktraceMap::IsValid(frame.map)) {
+      const std::string name = basename(frame.map.name.c_str());
+      ASSERT_TRUE(name != "libunwind.so" && name != "libbacktrace.so")
+        << DumpFrames(backtrace.get());
+    }
+    break;
+  }
+}
+
 TEST(libbacktrace, local_trace) {
   ASSERT_NE(test_level_one(1, 2, 3, 4, VerifyLevelBacktrace, nullptr), 0);
 }
@@ -490,9 +510,13 @@
   // The SA_RESTORER flag gets set behind our back, so a direct comparison
   // doesn't work unless we mask the value off. Mips doesn't have this
   // flag, so skip this on that platform.
-#ifdef SA_RESTORER
+#if defined(SA_RESTORER)
   cur_action.sa_flags &= ~SA_RESTORER;
   new_action.sa_flags &= ~SA_RESTORER;
+#elif defined(__GLIBC__)
+  // Our host compiler doesn't appear to define this flag for some reason.
+  cur_action.sa_flags &= ~0x04000000;
+  new_action.sa_flags &= ~0x04000000;
 #endif
   EXPECT_EQ(cur_action.sa_flags, new_action.sa_flags);
 }
@@ -858,10 +882,15 @@
   // Tell the caller it's okay to start reading memory.
   android_atomic_acquire_store(1, &thread_data->state);
 
-  // Loop waiting for everything
+  // Loop waiting for the caller to finish reading the memory.
   while (thread_data->state) {
   }
 
+  // Re-enable read-write on the page so that we don't crash if we try
+  // and access data on this page when freeing the memory.
+  if (mprotect(&memory[pagesize], pagesize, PROT_READ | PROT_WRITE) != 0) {
+    return reinterpret_cast<void*>(-1);
+  }
   free(memory);
 
   android_atomic_acquire_store(1, &thread_data->state);
@@ -1005,6 +1034,7 @@
     delete backtrace;
   }
   size_t stable_pss = GetPssBytes();
+  ASSERT_TRUE(stable_pss != 0);
 
   // Loop enough that even a small leak should be detectable.
   for (size_t i = 0; i < 4096; i++) {
@@ -1014,6 +1044,7 @@
     delete backtrace;
   }
   size_t new_pss = GetPssBytes();
+  ASSERT_TRUE(new_pss != 0);
   size_t abs_diff = (new_pss > stable_pss) ? new_pss - stable_pss : stable_pss - new_pss;
   // As long as the new pss is within a certain amount, consider everything okay.
   ASSERT_LE(abs_diff, MAX_LEAK_BYTES);
diff --git a/libcutils/Android.mk b/libcutils/Android.mk
index d890319..0cd560d 100644
--- a/libcutils/Android.mk
+++ b/libcutils/Android.mk
@@ -22,6 +22,7 @@
 	native_handle.c \
 	config_utils.c \
 	load_file.c \
+	memory.c \
 	open_memstream.c \
 	strdup16to8.c \
 	strdup8to16.c \
@@ -59,7 +60,8 @@
         sockets.c \
 
     commonHostSources += \
-        ashmem-host.c
+        ashmem-host.c \
+        trace-host.c
 
 endif
 
@@ -112,11 +114,10 @@
         ashmem-dev.c \
         debugger.c \
         klog.c \
-        memory.c \
         partition_utils.c \
         properties.c \
         qtaguid.c \
-        trace.c \
+        trace-dev.c \
         uevent.c \
 
 LOCAL_SRC_FILES_arm += \
diff --git a/libcutils/tests/Android.mk b/libcutils/tests/Android.mk
index 5a54698..d532dfb 100644
--- a/libcutils/tests/Android.mk
+++ b/libcutils/tests/Android.mk
@@ -32,21 +32,19 @@
 LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
 include $(BUILD_NATIVE_TEST)
 
-# The static libcutils tests cannot be built when using libc++ because there are
-# multiple symbol definition errors between libc++ and libgcc. b/18389856
-#include $(CLEAR_VARS)
-#LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
-#LOCAL_MODULE := libcutils_test_static
-#LOCAL_FORCE_STATIC_EXECUTABLE := true
-#LOCAL_SRC_FILES := $(test_src_files)
-#LOCAL_STATIC_LIBRARIES := \
-#    libc \
-#    libcutils \
-#    liblog \
-#    libutils \
+include $(CLEAR_VARS)
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
+LOCAL_MODULE := libcutils_test_static
+LOCAL_FORCE_STATIC_EXECUTABLE := true
+LOCAL_SRC_FILES := $(test_src_files)
+LOCAL_STATIC_LIBRARIES := \
+    libc \
+    libcutils \
+    liblog \
+    libutils \
 
-#LOCAL_CXX_STL := stlport_static
-#LOCAL_MULTILIB := both
-#LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
-#LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
-#include $(BUILD_NATIVE_TEST)
+LOCAL_CXX_STL := libc++_static
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
+include $(BUILD_NATIVE_TEST)
diff --git a/libcutils/trace.c b/libcutils/trace-dev.c
similarity index 100%
rename from libcutils/trace.c
rename to libcutils/trace-dev.c
diff --git a/libcutils/trace-host.c b/libcutils/trace-host.c
new file mode 100644
index 0000000..b87e543
--- /dev/null
+++ b/libcutils/trace-host.c
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2012 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 <cutils/trace.h>
+
+#ifndef __unused
+#define __unused __attribute__((__unused__))
+#endif
+
+volatile int32_t        atrace_is_ready      = 1;
+int                     atrace_marker_fd     = -1;
+uint64_t                atrace_enabled_tags  = 0;
+
+void atrace_set_debuggable(bool debuggable __unused) { }
+void atrace_set_tracing_enabled(bool enabled __unused) { }
+void atrace_update_tags() { }
+void atrace_setup() { }
+void atrace_begin_body(const char* name __unused) { }
+void atrace_async_begin_body(const char* name __unused, int32_t cookie __unused) { }
+void atrace_async_end_body(const char* name __unused, int32_t cookie __unused) { }
+void atrace_int_body(const char* name __unused, int32_t value __unused) { }
+void atrace_int64_body(const char* name __unused, int64_t value __unused) { }
diff --git a/libsparse/append2simg.c b/libsparse/append2simg.c
index 65e6cc2..1cf827c 100644
--- a/libsparse/append2simg.c
+++ b/libsparse/append2simg.c
@@ -82,7 +82,7 @@
         exit(-1);
     }
 
-    sparse_output = sparse_file_import_auto(output, true);
+    sparse_output = sparse_file_import_auto(output, true, true);
     if (!sparse_output) {
         fprintf(stderr, "Couldn't import output file\n");
         exit(-1);
diff --git a/libsparse/include/sparse/sparse.h b/libsparse/include/sparse/sparse.h
index 8b757d2..42d4adb 100644
--- a/libsparse/include/sparse/sparse.h
+++ b/libsparse/include/sparse/sparse.h
@@ -234,6 +234,7 @@
  *
  * @fd - file descriptor to read from
  * @crc - verify the crc of a file in the Android sparse file format
+ * @verbose - whether to use verbose logging
  *
  * Reads an existing sparse or normal file into a sparse file cookie.
  * Attempts to determine if the file is sparse or not by looking for the sparse
@@ -243,7 +244,7 @@
  *
  * Returns a new sparse file cookie on success, NULL on error.
  */
-struct sparse_file *sparse_file_import_auto(int fd, bool crc);
+struct sparse_file *sparse_file_import_auto(int fd, bool crc, bool verbose);
 
 /** sparse_file_resparse - rechunk an existing sparse file into smaller files
  *
diff --git a/libsparse/sparse_read.c b/libsparse/sparse_read.c
index 8e188e9..9b10293 100644
--- a/libsparse/sparse_read.c
+++ b/libsparse/sparse_read.c
@@ -472,13 +472,13 @@
 	return s;
 }
 
-struct sparse_file *sparse_file_import_auto(int fd, bool crc)
+struct sparse_file *sparse_file_import_auto(int fd, bool crc, bool verbose)
 {
 	struct sparse_file *s;
 	int64_t len;
 	int ret;
 
-	s = sparse_file_import(fd, true, crc);
+	s = sparse_file_import(fd, verbose, crc);
 	if (s) {
 		return s;
 	}
diff --git a/logd/LogCommand.cpp b/logd/LogCommand.cpp
index e4c138e..b78c0e0 100644
--- a/logd/LogCommand.cpp
+++ b/logd/LogCommand.cpp
@@ -17,6 +17,7 @@
 #include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
 
 #include <private/android_filesystem_config.h>
 
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 452758c..3da6cc7 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -270,6 +270,7 @@
     chmod 0660 /data/misc/wifi/wpa_supplicant.conf
     mkdir /data/local 0751 root root
     mkdir /data/misc/media 0700 media media
+    mkdir /data/misc/vold 0700 root root
 
     # For security reasons, /data/local/tmp should always be empty.
     # Do not place files or directories in /data/local/tmp
@@ -535,7 +536,9 @@
     onrestart restart surfaceflinger
     onrestart restart drm
 
-service vold /system/bin/vold
+service vold /system/bin/vold \
+        --blkid_context=u:r:blkid:s0 --blkid_untrusted_context=u:r:blkid_untrusted:s0 \
+        --fsck_context=u:r:fsck:s0 --fsck_untrusted_context=u:r:fsck_untrusted:s0
     class core
     socket vold stream 0660 root mount
     ioprio be 2
diff --git a/run-as/package.c b/run-as/package.c
index 4f8f3a7..9e1f5bb 100644
--- a/run-as/package.c
+++ b/run-as/package.c
@@ -16,9 +16,11 @@
 */
 #include <errno.h>
 #include <fcntl.h>
-#include <unistd.h>
-#include <sys/stat.h>
+#include <string.h>
 #include <sys/mman.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
 #include <private/android_filesystem_config.h>
 #include "package.h"
 
diff --git a/run-as/run-as.c b/run-as/run-as.c
index cc05e63..368b8f1 100644
--- a/run-as/run-as.c
+++ b/run-as/run-as.c
@@ -15,22 +15,25 @@
 ** limitations under the License.
 */
 
-#define PROGNAME  "run-as"
-#define LOG_TAG   PROGNAME
+#define PROGNAME "run-as"
+#define LOG_TAG  PROGNAME
 
+#include <dirent.h>
+#include <errno.h>
+#include <stdarg.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <sys/types.h>
+#include <sys/capability.h>
+#include <sys/cdefs.h>
 #include <sys/stat.h>
-#include <dirent.h>
-#include <errno.h>
-#include <unistd.h>
+#include <sys/types.h>
 #include <time.h>
-#include <stdarg.h>
+#include <unistd.h>
 
-#include <selinux/android.h>
 #include <private/android_filesystem_config.h>
+#include <selinux/android.h>
+
 #include "package.h"
 
 /*
@@ -83,37 +86,37 @@
  *  - Run the 'gdbserver' binary executable to allow native debugging
  */
 
-static void
-usage(void)
-{
-    const char*  str = "Usage: " PROGNAME " <package-name> <command> [<args>]\n\n";
-    write(1, str, strlen(str));
-    exit(1);
-}
-
-
-static void
+__noreturn static void
 panic(const char* format, ...)
 {
     va_list args;
+    int e = errno;
 
     fprintf(stderr, "%s: ", PROGNAME);
     va_start(args, format);
     vfprintf(stderr, format, args);
     va_end(args);
-    exit(1);
+    exit(e ? -e : 1);
 }
 
+static void
+usage(void)
+{
+    panic("Usage:\n    " PROGNAME " <package-name> <command> [<args>]\n");
+}
 
 int main(int argc, char **argv)
 {
     const char* pkgname;
     int myuid, uid, gid;
     PackageInfo info;
+    struct __user_cap_header_struct capheader;
+    struct __user_cap_data_struct capdata[2];
 
     /* check arguments */
-    if (argc < 2)
+    if (argc < 2) {
         usage();
+    }
 
     /* check userid of caller - must be 'shell' or 'root' */
     myuid = getuid();
@@ -121,29 +124,37 @@
         panic("only 'shell' or 'root' users can run this program\n");
     }
 
-    /* retrieve package information from system */
+    memset(&capheader, 0, sizeof(capheader));
+    memset(&capdata, 0, sizeof(capdata));
+    capheader.version = _LINUX_CAPABILITY_VERSION_3;
+    capdata[CAP_TO_INDEX(CAP_SETUID)].effective |= CAP_TO_MASK(CAP_SETUID);
+    capdata[CAP_TO_INDEX(CAP_SETGID)].effective |= CAP_TO_MASK(CAP_SETGID);
+    capdata[CAP_TO_INDEX(CAP_SETUID)].permitted |= CAP_TO_MASK(CAP_SETUID);
+    capdata[CAP_TO_INDEX(CAP_SETGID)].permitted |= CAP_TO_MASK(CAP_SETGID);
+
+    if (capset(&capheader, &capdata[0]) < 0) {
+        panic("Could not set capabilities: %s\n", strerror(errno));
+    }
+
+    /* retrieve package information from system (does setegid) */
     pkgname = argv[1];
     if (get_package_info(pkgname, &info) < 0) {
         panic("Package '%s' is unknown\n", pkgname);
-        return 1;
     }
 
     /* reject system packages */
     if (info.uid < AID_APP) {
         panic("Package '%s' is not an application\n", pkgname);
-        return 1;
     }
 
     /* reject any non-debuggable package */
     if (!info.isDebuggable) {
         panic("Package '%s' is not debuggable\n", pkgname);
-        return 1;
     }
 
     /* check that the data directory path is valid */
     if (check_data_path(info.dataDir, info.uid) < 0) {
         panic("Package '%s' has corrupt installation\n", pkgname);
-        return 1;
     }
 
     /* Ensure that we change all real/effective/saved IDs at the
@@ -152,38 +163,30 @@
     uid = gid = info.uid;
     if(setresgid(gid,gid,gid) || setresuid(uid,uid,uid)) {
         panic("Permission denied\n");
-        return 1;
+    }
+
+    /* Required if caller has uid and gid all non-zero */
+    memset(&capdata, 0, sizeof(capdata));
+    if (capset(&capheader, &capdata[0]) < 0) {
+        panic("Could not clear all capabilities: %s\n", strerror(errno));
     }
 
     if (selinux_android_setcontext(uid, 0, info.seinfo, pkgname) < 0) {
-        panic("Could not set SELinux security context:  %s\n", strerror(errno));
-        return 1;
+        panic("Could not set SELinux security context: %s\n", strerror(errno));
     }
 
     /* cd into the data directory */
-    {
-        int ret;
-        do {
-            ret = chdir(info.dataDir);
-        } while (ret < 0 && errno == EINTR);
-
-        if (ret < 0) {
-            panic("Could not cd to package's data directory: %s\n", strerror(errno));
-            return 1;
-        }
+    if (TEMP_FAILURE_RETRY(chdir(info.dataDir)) < 0) {
+        panic("Could not cd to package's data directory: %s\n", strerror(errno));
     }
 
     /* User specified command for exec. */
-    if (argc >= 3 ) {
-        if (execvp(argv[2], argv+2) < 0) {
-            panic("exec failed for %s Error:%s\n", argv[2], strerror(errno));
-            return -errno;
-        }
+    if ((argc >= 3) && (execvp(argv[2], argv+2) < 0)) {
+        panic("exec failed for %s: %s\n", argv[2], strerror(errno));
     }
 
     /* Default exec shell. */
     execlp("/system/bin/sh", "sh", NULL);
 
-    panic("exec failed\n");
-    return 1;
+    panic("exec failed: %s\n", strerror(errno));
 }
diff --git a/sdcard/sdcard.c b/sdcard/sdcard.c
index 2cb41e5..942c181 100644
--- a/sdcard/sdcard.c
+++ b/sdcard/sdcard.c
@@ -1860,7 +1860,8 @@
             "fd=%i,rootmode=40000,default_permissions,allow_other,user_id=%d,group_id=%d",
             fd, uid, gid);
 
-    res = mount("/dev/fuse", dest_path, "fuse", MS_NOSUID | MS_NODEV | MS_NOEXEC, opts);
+    res = mount("/dev/fuse", dest_path, "fuse", MS_NOSUID | MS_NODEV | MS_NOEXEC |
+            MS_NOATIME, opts);
     if (res < 0) {
         ERROR("cannot mount fuse filesystem: %s\n", strerror(errno));
         goto error;