Merge "Set verity mode as the verified property value"
diff --git a/adb/Android.mk b/adb/Android.mk
index 4f19d47..3733ae3 100644
--- a/adb/Android.mk
+++ b/adb/Android.mk
@@ -161,7 +161,6 @@
     LOCAL_STATIC_LIBRARIES += libcutils
 endif
 
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
 include $(BUILD_HOST_EXECUTABLE)
 
 $(call dist-for-goals,dist_files sdk,$(LOCAL_BUILT_MODULE))
@@ -221,6 +220,4 @@
     libselinux \
     libext4_utils_static \
 
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
-
 include $(BUILD_EXECUTABLE)
diff --git a/adb/commandline.cpp b/adb/commandline.cpp
index f9ca5ed..34efefe 100644
--- a/adb/commandline.cpp
+++ b/adb/commandline.cpp
@@ -256,29 +256,25 @@
 }
 
 #else
-static struct termios tio_save;
+static termios g_saved_terminal_state;
 
-static void stdin_raw_init(int fd)
-{
-    struct termios tio;
+static void stdin_raw_init(int fd) {
+    if (tcgetattr(fd, &g_saved_terminal_state)) return;
 
-    if(tcgetattr(fd, &tio)) return;
-    if(tcgetattr(fd, &tio_save)) return;
+    termios tio;
+    if (tcgetattr(fd, &tio)) return;
 
-    tio.c_lflag = 0; /* disable CANON, ECHO*, etc */
+    cfmakeraw(&tio);
 
-        /* no timeout but request at least one character per read */
+    // No timeout but request at least one character per read.
     tio.c_cc[VTIME] = 0;
     tio.c_cc[VMIN] = 1;
 
-    tcsetattr(fd, TCSANOW, &tio);
-    tcflush(fd, TCIFLUSH);
+    tcsetattr(fd, TCSAFLUSH, &tio);
 }
 
-static void stdin_raw_restore(int fd)
-{
-    tcsetattr(fd, TCSANOW, &tio_save);
-    tcflush(fd, TCIFLUSH);
+static void stdin_raw_restore(int fd) {
+    tcsetattr(fd, TCSAFLUSH, &g_saved_terminal_state);
 }
 #endif
 
diff --git a/adb/transport.cpp b/adb/transport.cpp
index 0a960ff..4b9eeeb 100644
--- a/adb/transport.cpp
+++ b/adb/transport.cpp
@@ -772,7 +772,7 @@
 }
 
 static int qual_match(const char *to_test,
-                      const char *prefix, const char *qual, int sanitize_qual)
+                      const char *prefix, const char *qual, bool sanitize_qual)
 {
     if (!to_test || !*to_test)
         /* Return true if both the qual and to_test are null strings. */
@@ -790,7 +790,7 @@
 
     while (*qual) {
         char ch = *qual++;
-        if (sanitize_qual && isalnum(ch))
+        if (sanitize_qual && !isalnum(ch))
             ch = '_';
         if (ch != *to_test++)
             return 0;
@@ -823,9 +823,9 @@
         if (serial) {
             if ((t->serial && !strcmp(serial, t->serial)) ||
                 (t->devpath && !strcmp(serial, t->devpath)) ||
-                qual_match(serial, "product:", t->product, 0) ||
-                qual_match(serial, "model:", t->model, 1) ||
-                qual_match(serial, "device:", t->device, 0)) {
+                qual_match(serial, "product:", t->product, false) ||
+                qual_match(serial, "model:", t->model, true) ||
+                qual_match(serial, "device:", t->device, false)) {
                 if (result) {
                     if (error_out)
                         *error_out = "more than one device";
@@ -918,20 +918,17 @@
 }
 
 static void add_qual(char **buf, size_t *buf_size,
-                     const char *prefix, const char *qual, int sanitize_qual)
+                     const char *prefix, const char *qual, bool sanitize_qual)
 {
-    size_t len;
-    int prefix_len;
-
     if (!buf || !*buf || !buf_size || !*buf_size || !qual || !*qual)
         return;
 
-    len = snprintf(*buf, *buf_size, "%s%n%s", prefix, &prefix_len, qual);
+    int prefix_len;
+    size_t len = snprintf(*buf, *buf_size, "%s%n%s", prefix, &prefix_len, qual);
 
     if (sanitize_qual) {
-        char *cp;
-        for (cp = *buf + prefix_len; cp < *buf + len; cp++) {
-            if (isalnum(*cp))
+        for (char* cp = *buf + prefix_len; cp < *buf + len; cp++) {
+            if (!isalnum(*cp))
                 *cp = '_';
         }
     }
@@ -956,10 +953,10 @@
         remaining -= len;
         buf += len;
 
-        add_qual(&buf, &remaining, " ", t->devpath, 0);
-        add_qual(&buf, &remaining, " product:", t->product, 0);
-        add_qual(&buf, &remaining, " model:", t->model, 1);
-        add_qual(&buf, &remaining, " device:", t->device, 0);
+        add_qual(&buf, &remaining, " ", t->devpath, false);
+        add_qual(&buf, &remaining, " product:", t->product, false);
+        add_qual(&buf, &remaining, " model:", t->model, true);
+        add_qual(&buf, &remaining, " device:", t->device, false);
 
         len = snprintf(buf, remaining, "\n");
         remaining -= len;
diff --git a/base/CPPLINT.cfg b/base/CPPLINT.cfg
index a61c08d..d94a89c 100644
--- a/base/CPPLINT.cfg
+++ b/base/CPPLINT.cfg
@@ -1,2 +1,2 @@
 set noparent
-filter=-build/header_guard,-build/include,-build/c++11
+filter=-build/header_guard,-build/include,-build/c++11,-whitespace/operators
diff --git a/base/include/base/logging.h b/base/include/base/logging.h
index 5e115fe..230adb8 100644
--- a/base/include/base/logging.h
+++ b/base/include/base/logging.h
@@ -17,6 +17,7 @@
 #ifndef BASE_LOGGING_H
 #define BASE_LOGGING_H
 
+#include <functional>
 #include <memory>
 #include <ostream>
 
@@ -34,6 +35,33 @@
   FATAL,
 };
 
+enum LogId {
+  DEFAULT,
+  MAIN,
+  SYSTEM,
+};
+
+typedef std::function<void(LogId, LogSeverity, const char*, const char*,
+                           unsigned int, const char*)> LogFunction;
+
+extern void StderrLogger(LogId, LogSeverity, const char*, const char*,
+                         unsigned int, const char*);
+
+#ifdef __ANDROID__
+// We expose this even though it is the default because a user that wants to
+// override the default log buffer will have to construct this themselves.
+class LogdLogger {
+ public:
+  explicit LogdLogger(LogId default_log_id = android::base::MAIN);
+
+  void operator()(LogId, LogSeverity, const char* tag, const char* file,
+                  unsigned int line, const char* message);
+
+ private:
+  LogId default_log_id_;
+};
+#endif
+
 // Configure logging based on ANDROID_LOG_TAGS environment variable.
 // We need to parse a string that looks like
 //
@@ -42,33 +70,39 @@
 // The tag (or '*' for the global level) comes first, followed by a colon and a
 // letter indicating the minimum priority level we're expected to log.  This can
 // be used to reveal or conceal logs with specific tags.
+extern void InitLogging(char* argv[], LogFunction&& logger);
+
+// Configures logging using the default logger (logd for the device, stderr for
+// the host).
 extern void InitLogging(char* argv[]);
 
-// Returns the command line used to invoke the current tool or nullptr if
-// InitLogging hasn't been performed.
-extern const char* GetCmdLine();
-
-// The command used to start the program, such as "/system/bin/dalvikvm". If
-// InitLogging hasn't been performed then just returns "unknown"
-extern const char* ProgramInvocationName();
-
-// A short version of the command used to start the program, such as "dalvikvm".
-// If InitLogging hasn't been performed then just returns "unknown"
-extern const char* ProgramInvocationShortName();
+// Replace the current logger.
+extern void SetLogger(LogFunction&& logger);
 
 // Logs a message to logcat on Android otherwise to stderr. If the severity is
 // FATAL it also causes an abort. For example:
 //
 //     LOG(FATAL) << "We didn't expect to reach here";
-#define LOG(severity)                                                        \
-  ::android::base::LogMessage(__FILE__, __LINE__, ::android::base::severity, \
-                              -1).stream()
+#define LOG(severity)                                                       \
+  ::android::base::LogMessage(__FILE__, __LINE__, ::android::base::DEFAULT, \
+                              ::android::base::severity, -1).stream()
+
+// Logs a message to logcat with the specified log ID on Android otherwise to
+// stderr. If the severity is FATAL it also causes an abort.
+#define LOG_TO(dest, severity)                                           \
+  ::android::base::LogMessage(__FILE__, __LINE__, ::android::base::dest, \
+                              ::android::base::severity, -1).stream()
 
 // A variant of LOG that also logs the current errno value. To be used when
 // library calls fail.
-#define PLOG(severity)                                                       \
-  ::android::base::LogMessage(__FILE__, __LINE__, ::android::base::severity, \
-                              errno).stream()
+#define PLOG(severity)                                                      \
+  ::android::base::LogMessage(__FILE__, __LINE__, ::android::base::DEFAULT, \
+                              ::android::base::severity, errno).stream()
+
+// Behaves like PLOG, but logs to the specified log ID.
+#define PLOG_TO(dest, severity)                                          \
+  ::android::base::LogMessage(__FILE__, __LINE__, ::android::base::dest, \
+                              ::android::base::severity, errno).stream()
 
 // Marker that code is yet to be implemented.
 #define UNIMPLEMENTED(level) \
@@ -82,18 +116,18 @@
 //       "Check failed: false == true".
 #define CHECK(x)                                                            \
   if (UNLIKELY(!(x)))                                                       \
-    ::android::base::LogMessage(__FILE__, __LINE__, ::android::base::FATAL, \
-                                -1).stream()                                \
-        << "Check failed: " #x << " "
+  ::android::base::LogMessage(__FILE__, __LINE__, ::android::base::DEFAULT, \
+                              ::android::base::FATAL, -1).stream()          \
+      << "Check failed: " #x << " "
 
 // Helper for CHECK_xx(x,y) macros.
-#define CHECK_OP(LHS, RHS, OP)                                                \
-  for (auto _values = ::android::base::MakeEagerEvaluator(LHS, RHS);          \
-       UNLIKELY(!(_values.lhs OP _values.rhs));                               \
-       /* empty */)                                                           \
-  ::android::base::LogMessage(__FILE__, __LINE__, ::android::base::FATAL, -1) \
-          .stream()                                                           \
-      << "Check failed: " << #LHS << " " << #OP << " " << #RHS                \
+#define CHECK_OP(LHS, RHS, OP)                                              \
+  for (auto _values = ::android::base::MakeEagerEvaluator(LHS, RHS);        \
+       UNLIKELY(!(_values.lhs OP _values.rhs));                             \
+       /* empty */)                                                         \
+  ::android::base::LogMessage(__FILE__, __LINE__, ::android::base::DEFAULT, \
+                              ::android::base::FATAL, -1).stream()          \
+      << "Check failed: " << #LHS << " " << #OP << " " << #RHS              \
       << " (" #LHS "=" << _values.lhs << ", " #RHS "=" << _values.rhs << ") "
 
 // Check whether a condition holds between x and y, LOG(FATAL) if not. The value
@@ -228,8 +262,8 @@
 // of a CHECK. The destructor will abort if the severity is FATAL.
 class LogMessage {
  public:
-  LogMessage(const char* file, unsigned int line, LogSeverity severity,
-             int error);
+  LogMessage(const char* file, unsigned int line, LogId id,
+             LogSeverity severity, int error);
 
   ~LogMessage();
 
@@ -238,12 +272,8 @@
   std::ostream& stream();
 
   // The routine that performs the actual logging.
-  static void LogLine(const char* file, unsigned int line, LogSeverity severity,
-                      const char* msg);
-
-  // A variant of the above for use with little stack.
-  static void LogLineLowStack(const char* file, unsigned int line,
-                              LogSeverity severity, const char* msg);
+  static void LogLine(const char* file, unsigned int line, LogId id,
+                      LogSeverity severity, const char* msg);
 
  private:
   const std::unique_ptr<LogMessageData> data_;
diff --git a/base/logging.cpp b/base/logging.cpp
index 38ee2af..0142b70 100644
--- a/base/logging.cpp
+++ b/base/logging.cpp
@@ -16,11 +16,21 @@
 
 #include "base/logging.h"
 
+#include <libgen.h>
+
+// For getprogname(3) or program_invocation_short_name.
+#if defined(__ANDROID__) || defined(__APPLE__)
+#include <stdlib.h>
+#elif defined(__GLIBC__)
+#include <errno.h>
+#endif
+
 #include <iostream>
 #include <limits>
 #include <mutex>
 #include <sstream>
 #include <string>
+#include <utility>
 #include <vector>
 
 #include "base/strings.h"
@@ -40,49 +50,96 @@
 
 static std::mutex logging_lock;
 
+#ifdef __ANDROID__
+static LogFunction gLogger = LogdLogger();
+#else
+static LogFunction gLogger = StderrLogger;
+#endif
+
+static bool gInitialized = false;
 static LogSeverity gMinimumLogSeverity = INFO;
-static std::unique_ptr<std::string> gCmdLine;
 static std::unique_ptr<std::string> gProgramInvocationName;
-static std::unique_ptr<std::string> gProgramInvocationShortName;
 
-const char* GetCmdLine() {
-  return (gCmdLine.get() != nullptr) ? gCmdLine->c_str() : nullptr;
+#if defined(__GLIBC__)
+static const char* getprogname() {
+  return program_invocation_short_name;
+}
+#endif
+
+static const char* ProgramInvocationName() {
+  if (gProgramInvocationName == nullptr) {
+    gProgramInvocationName.reset(new std::string(getprogname()));
+  }
+
+  return gProgramInvocationName->c_str();
 }
 
-const char* ProgramInvocationName() {
-  return (gProgramInvocationName.get() != nullptr)
-             ? gProgramInvocationName->c_str()
-             : "unknown";
+void StderrLogger(LogId, LogSeverity severity, const char*, const char* file,
+                  unsigned int line, const char* message) {
+  static const char* log_characters = "VDIWEF";
+  CHECK_EQ(strlen(log_characters), FATAL + 1U);
+  char severity_char = log_characters[severity];
+  fprintf(stderr, "%s %c %5d %5d %s:%u] %s\n", ProgramInvocationName(),
+          severity_char, getpid(), gettid(), file, line, message);
 }
 
-const char* ProgramInvocationShortName() {
-  return (gProgramInvocationShortName.get() != nullptr)
-             ? gProgramInvocationShortName->c_str()
-             : "unknown";
+
+#ifdef __ANDROID__
+LogdLogger::LogdLogger(LogId default_log_id) : default_log_id_(default_log_id) {
+}
+
+static const android_LogPriority kLogSeverityToAndroidLogPriority[] = {
+    ANDROID_LOG_VERBOSE, ANDROID_LOG_DEBUG, ANDROID_LOG_INFO,
+    ANDROID_LOG_WARN,    ANDROID_LOG_ERROR, ANDROID_LOG_FATAL,
+};
+static_assert(arraysize(kLogSeverityToAndroidLogPriority) == FATAL + 1,
+              "Mismatch in size of kLogSeverityToAndroidLogPriority and values "
+              "in LogSeverity");
+
+static const log_id kLogIdToAndroidLogId[] = {
+    LOG_ID_MAX, LOG_ID_MAIN, LOG_ID_SYSTEM,
+};
+static_assert(arraysize(kLogIdToAndroidLogId) == SYSTEM + 1,
+              "Mismatch in size of kLogIdToAndroidLogId and values in LogId");
+
+void LogdLogger::operator()(LogId id, LogSeverity severity, const char* tag,
+                            const char* file, unsigned int line,
+                            const char* message) {
+  int priority = kLogSeverityToAndroidLogPriority[severity];
+  if (id == DEFAULT) {
+    id = default_log_id_;
+  }
+
+  log_id lg_id = kLogIdToAndroidLogId[id];
+
+  if (priority == ANDROID_LOG_FATAL) {
+    __android_log_buf_print(lg_id, priority, tag, "%s:%u] %s", file, line,
+                            message);
+  } else {
+    __android_log_buf_print(lg_id, priority, tag, "%s", message);
+  }
+}
+#endif
+
+void InitLogging(char* argv[], LogFunction&& logger) {
+  SetLogger(std::forward<LogFunction>(logger));
+  InitLogging(argv);
 }
 
 void InitLogging(char* argv[]) {
-  if (gCmdLine.get() != nullptr) {
+  if (gInitialized) {
     return;
   }
 
+  gInitialized = true;
+
   // Stash the command line for later use. We can use /proc/self/cmdline on
   // Linux to recover this, but we don't have that luxury on the Mac, and there
   // are a couple of argv[0] variants that are commonly used.
   if (argv != nullptr) {
-    gCmdLine.reset(new std::string(argv[0]));
-    for (size_t i = 1; argv[i] != nullptr; ++i) {
-      gCmdLine->append(" ");
-      gCmdLine->append(argv[i]);
-    }
-    gProgramInvocationName.reset(new std::string(argv[0]));
-    const char* last_slash = strrchr(argv[0], '/');
-    gProgramInvocationShortName.reset(
-        new std::string((last_slash != nullptr) ? last_slash + 1 : argv[0]));
-  } else {
-    // TODO: fall back to /proc/self/cmdline when argv is NULL on Linux.
-    gCmdLine.reset(new std::string("<unset>"));
+    gProgramInvocationName.reset(new std::string(basename(argv[0])));
   }
+
   const char* tags = getenv("ANDROID_LOG_TAGS");
   if (tags == nullptr) {
     return;
@@ -124,13 +181,22 @@
   }
 }
 
+void SetLogger(LogFunction&& logger) {
+  std::lock_guard<std::mutex> lock(logging_lock);
+  gLogger = std::move(logger);
+}
+
 // This indirection greatly reduces the stack impact of having lots of
 // checks/logging in a function.
 class LogMessageData {
  public:
-  LogMessageData(const char* file, unsigned int line, LogSeverity severity,
-                 int error)
-      : file_(file), line_number_(line), severity_(severity), error_(error) {
+  LogMessageData(const char* file, unsigned int line, LogId id,
+                 LogSeverity severity, int error)
+      : file_(file),
+        line_number_(line),
+        id_(id),
+        severity_(severity),
+        error_(error) {
     const char* last_slash = strrchr(file, '/');
     file = (last_slash == nullptr) ? file : last_slash + 1;
   }
@@ -147,6 +213,10 @@
     return severity_;
   }
 
+  LogId GetId() const {
+    return id_;
+  }
+
   int GetError() const {
     return error_;
   }
@@ -163,15 +233,16 @@
   std::ostringstream buffer_;
   const char* const file_;
   const unsigned int line_number_;
+  const LogId id_;
   const LogSeverity severity_;
   const int error_;
 
   DISALLOW_COPY_AND_ASSIGN(LogMessageData);
 };
 
-LogMessage::LogMessage(const char* file, unsigned int line,
+LogMessage::LogMessage(const char* file, unsigned int line, LogId id,
                        LogSeverity severity, int error)
-    : data_(new LogMessageData(file, line, severity, error)) {
+    : data_(new LogMessageData(file, line, id, severity, error)) {
 }
 
 LogMessage::~LogMessage() {
@@ -185,22 +256,18 @@
   }
   std::string msg(data_->ToString());
 
-  // Do the actual logging with the lock held.
-  {
-    std::lock_guard<std::mutex> lock(logging_lock);
-    if (msg.find('\n') == std::string::npos) {
-      LogLine(data_->GetFile(), data_->GetLineNumber(), data_->GetSeverity(),
-              msg.c_str());
-    } else {
-      msg += '\n';
-      size_t i = 0;
-      while (i < msg.size()) {
-        size_t nl = msg.find('\n', i);
-        msg[nl] = '\0';
-        LogLine(data_->GetFile(), data_->GetLineNumber(), data_->GetSeverity(),
-                &msg[i]);
-        i = nl + 1;
-      }
+  if (msg.find('\n') == std::string::npos) {
+    LogLine(data_->GetFile(), data_->GetLineNumber(), data_->GetId(),
+            data_->GetSeverity(), msg.c_str());
+  } else {
+    msg += '\n';
+    size_t i = 0;
+    while (i < msg.size()) {
+      size_t nl = msg.find('\n', i);
+      msg[nl] = '\0';
+      LogLine(data_->GetFile(), data_->GetLineNumber(), data_->GetId(),
+              data_->GetSeverity(), &msg[i]);
+      i = nl + 1;
     }
   }
 
@@ -217,76 +284,11 @@
   return data_->GetBuffer();
 }
 
-#ifdef __ANDROID__
-static const android_LogPriority kLogSeverityToAndroidLogPriority[] = {
-    ANDROID_LOG_VERBOSE, ANDROID_LOG_DEBUG, ANDROID_LOG_INFO,
-    ANDROID_LOG_WARN,    ANDROID_LOG_ERROR, ANDROID_LOG_FATAL};
-static_assert(arraysize(kLogSeverityToAndroidLogPriority) == FATAL + 1,
-              "Mismatch in size of kLogSeverityToAndroidLogPriority and values "
-              "in LogSeverity");
-#endif
-
-void LogMessage::LogLine(const char* file, unsigned int line,
-                         LogSeverity log_severity, const char* message) {
-#ifdef __ANDROID__
-  const char* tag = ProgramInvocationShortName();
-  int priority = kLogSeverityToAndroidLogPriority[log_severity];
-  if (priority == ANDROID_LOG_FATAL) {
-    LOG_PRI(priority, tag, "%s:%u] %s", file, line, message);
-  } else {
-    LOG_PRI(priority, tag, "%s", message);
-  }
-#else
-  static const char* log_characters = "VDIWEF";
-  CHECK_EQ(strlen(log_characters), FATAL + 1U);
-  char severity = log_characters[log_severity];
-  fprintf(stderr, "%s %c %5d %5d %s:%u] %s\n", ProgramInvocationShortName(),
-          severity, getpid(), gettid(), file, line, message);
-#endif
-}
-
-void LogMessage::LogLineLowStack(const char* file, unsigned int line,
-                                 LogSeverity log_severity, const char* message) {
-#ifdef __ANDROID__
-  // Use android_writeLog() to avoid stack-based buffers used by
-  // android_printLog().
-  const char* tag = ProgramInvocationShortName();
-  int priority = kLogSeverityToAndroidLogPriority[log_severity];
-  char* buf = nullptr;
-  size_t buf_size = 0u;
-  if (priority == ANDROID_LOG_FATAL) {
-    // Allocate buffer for snprintf(buf, buf_size, "%s:%u] %s", file, line,
-    // message) below.  If allocation fails, fall back to printing only the
-    // message.
-    buf_size = strlen(file) + 1 /* ':' */ +
-               std::numeric_limits<typeof(line)>::max_digits10 + 2 /* "] " */ +
-               strlen(message) + 1 /* terminating 0 */;
-    buf = reinterpret_cast<char*>(malloc(buf_size));
-  }
-  if (buf != nullptr) {
-    snprintf(buf, buf_size, "%s:%u] %s", file, line, message);
-    android_writeLog(priority, tag, buf);
-    free(buf);
-  } else {
-    android_writeLog(priority, tag, message);
-  }
-#else
-  static const char* log_characters = "VDIWEF";
-  CHECK_EQ(strlen(log_characters), FATAL + 1U);
-
-  const char* program_name = ProgramInvocationShortName();
-  write(STDERR_FILENO, program_name, strlen(program_name));
-  write(STDERR_FILENO, " ", 1);
-  write(STDERR_FILENO, &log_characters[log_severity], 1);
-  write(STDERR_FILENO, " ", 1);
-  // TODO: pid and tid.
-  write(STDERR_FILENO, file, strlen(file));
-  // TODO: line.
-  UNUSED(line);
-  write(STDERR_FILENO, "] ", 2);
-  write(STDERR_FILENO, message, strlen(message));
-  write(STDERR_FILENO, "\n", 1);
-#endif
+void LogMessage::LogLine(const char* file, unsigned int line, LogId id,
+                         LogSeverity severity, const char* message) {
+  const char* tag = ProgramInvocationName();
+  std::lock_guard<std::mutex> lock(logging_lock);
+  gLogger(id, severity, tag, file, line, message);
 }
 
 ScopedLogSeverity::ScopedLogSeverity(LogSeverity level) {
diff --git a/base/logging_test.cpp b/base/logging_test.cpp
index 0a03e38..d947c1d 100644
--- a/base/logging_test.cpp
+++ b/base/logging_test.cpp
@@ -61,7 +61,7 @@
   int old_stderr_;
 };
 
-HOST_TEST(logging, CHECK) {
+TEST(logging, CHECK) {
   ASSERT_DEATH(CHECK(false), "Check failed: false ");
   CHECK(true);
 
@@ -82,7 +82,7 @@
       log_char, message);
 }
 
-HOST_TEST(logging, LOG) {
+TEST(logging, LOG) {
   ASSERT_DEATH(LOG(FATAL) << "foobar", "foobar");
 
   {
@@ -136,7 +136,7 @@
   }
 }
 
-HOST_TEST(logging, PLOG) {
+TEST(logging, PLOG) {
   {
     CapturedStderr cap;
     errno = ENOENT;
@@ -152,7 +152,7 @@
   }
 }
 
-HOST_TEST(logging, UNIMPLEMENTED) {
+TEST(logging, UNIMPLEMENTED) {
   {
     CapturedStderr cap;
     errno = ENOENT;
diff --git a/base/test_main.cpp b/base/test_main.cpp
index c49ca4b..546923d 100644
--- a/base/test_main.cpp
+++ b/base/test_main.cpp
@@ -20,6 +20,6 @@
 
 int main(int argc, char** argv) {
   ::testing::InitGoogleTest(&argc, argv);
-  android::base::InitLogging(argv);
+  android::base::InitLogging(argv, android::base::StderrLogger);
   return RUN_ALL_TESTS();
 }
diff --git a/cpio/Android.mk b/cpio/Android.mk
index 575beb2..b9d18ba 100644
--- a/cpio/Android.mk
+++ b/cpio/Android.mk
@@ -10,6 +10,8 @@
 
 LOCAL_CFLAGS := -Werror
 
+LOCAL_STATIC_LIBRARIES := libcutils
+
 include $(BUILD_HOST_EXECUTABLE)
 
 $(call dist-for-goals,dist_files,$(LOCAL_BUILT_MODULE))
diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp
index 6dc7d34..e139bcd 100644
--- a/fastboot/fastboot.cpp
+++ b/fastboot/fastboot.cpp
@@ -538,7 +538,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/fs_mgr/fs_mgr.c b/fs_mgr/fs_mgr.c
index d4daed6..273a2ec 100644
--- a/fs_mgr/fs_mgr.c
+++ b/fs_mgr/fs_mgr.c
@@ -31,6 +31,7 @@
 #include <dirent.h>
 #include <ext4.h>
 #include <ext4_sb.h>
+#include <ext4_crypt.h>
 
 #include <linux/loop.h>
 #include <private/android_filesystem_config.h>
@@ -428,6 +429,73 @@
     return ret;
 }
 
+// Check to see if a mountable volume has encryption requirements
+static int handle_encryptable(struct fstab *fstab, const struct fstab_rec* rec)
+{
+    /* If this is block encryptable, need to trigger encryption */
+    if (   (rec->fs_mgr_flags & MF_FORCECRYPT)
+        || (device_is_force_encrypted() && fs_mgr_is_encryptable(rec))) {
+        if (umount(rec->mount_point) == 0) {
+            return FS_MGR_MNTALL_DEV_NEEDS_ENCRYPTION;
+        } else {
+            WARNING("Could not umount %s (%s) - allow continue unencrypted\n",
+                    rec->mount_point, strerror(errno));
+            return FS_MGR_MNTALL_DEV_NOT_ENCRYPTED;
+        }
+    }
+
+    // Deal with file level encryption
+    if (rec->fs_mgr_flags & MF_FILEENCRYPTION) {
+        // Default or not yet initialized encryption requires no more work here
+        if (!e4crypt_non_default_key(rec->mount_point)) {
+            INFO("%s is default file encrypted\n", rec->mount_point);
+            return FS_MGR_MNTALL_DEV_DEFAULT_FILE_ENCRYPTED;
+        }
+
+        INFO("%s is non-default file encrypted\n", rec->mount_point);
+
+        // Uses non-default key, so must unmount and set up temp file system
+        if (umount(rec->mount_point)) {
+            ERROR("Failed to umount %s - rebooting\n", rec->mount_point);
+            return FS_MGR_MNTALL_FAIL;
+        }
+
+        if (fs_mgr_do_tmpfs_mount(rec->mount_point) != 0) {
+            ERROR("Failed to mount a tmpfs at %s\n", rec->mount_point);
+            return FS_MGR_MNTALL_FAIL;
+        }
+
+        // Mount data temporarily so we can access unencrypted dir
+        char tmp_mnt[PATH_MAX];
+        strlcpy(tmp_mnt, rec->mount_point, sizeof(tmp_mnt));
+        strlcat(tmp_mnt, "/tmp_mnt", sizeof(tmp_mnt));
+        if (mkdir(tmp_mnt, 0700)) {
+            ERROR("Failed to create temp mount point\n");
+            return FS_MGR_MNTALL_FAIL;
+        }
+
+        if (fs_mgr_do_mount(fstab, rec->mount_point,
+                            rec->blk_device, tmp_mnt)) {
+            ERROR("Error temp mounting encrypted file system\n");
+            return FS_MGR_MNTALL_FAIL;
+        }
+
+        // Link it to the normal place so ext4_crypt functions work normally
+        strlcat(tmp_mnt, "/unencrypted", sizeof(tmp_mnt));
+        char link_path[PATH_MAX];
+        strlcpy(link_path, rec->mount_point, sizeof(link_path));
+        strlcat(link_path, "/unencrypted", sizeof(link_path));
+        if (symlink(tmp_mnt, link_path)) {
+            ERROR("Error creating symlink to unencrypted directory\n");
+            return FS_MGR_MNTALL_FAIL;
+        }
+
+        return FS_MGR_MNTALL_DEV_NON_DEFAULT_FILE_ENCRYPTED;
+    }
+
+    return FS_MGR_MNTALL_DEV_NOT_ENCRYPTED;
+}
+
 /* When multiple fstab records share the same mount_point, it will
  * try to mount each one in turn, and ignore any duplicates after a
  * first successful mount.
@@ -490,25 +558,21 @@
 
         /* Deal with encryptability. */
         if (!mret) {
-            /* If this is encryptable, need to trigger encryption */
-            if (   (fstab->recs[attempted_idx].fs_mgr_flags & MF_FORCECRYPT)
-                || (device_is_force_encrypted()
-                    && fs_mgr_is_encryptable(&fstab->recs[attempted_idx]))) {
-                if (umount(fstab->recs[attempted_idx].mount_point) == 0) {
-                    if (encryptable == FS_MGR_MNTALL_DEV_NOT_ENCRYPTED) {
-                        ERROR("Will try to encrypt %s %s\n", fstab->recs[attempted_idx].mount_point,
-                              fstab->recs[attempted_idx].fs_type);
-                        encryptable = FS_MGR_MNTALL_DEV_NEEDS_ENCRYPTION;
-                    } else {
-                        ERROR("Only one encryptable/encrypted partition supported\n");
-                        encryptable = FS_MGR_MNTALL_DEV_MIGHT_BE_ENCRYPTED;
-                    }
-                } else {
-                    WARNING("Could not umount %s (%s) - allow continue unencrypted\n",
-                            fstab->recs[attempted_idx].mount_point, strerror(errno));
-                    continue;
-                }
+            int status = handle_encryptable(fstab, &fstab->recs[attempted_idx]);
+
+            if (status == FS_MGR_MNTALL_FAIL) {
+                /* Fatal error - no point continuing */
+                return status;
             }
+
+            if (status != FS_MGR_MNTALL_DEV_NOT_ENCRYPTED) {
+                if (encryptable != FS_MGR_MNTALL_DEV_NOT_ENCRYPTED) {
+                    // Log and continue
+                    ERROR("Only one encryptable/encrypted partition supported\n");
+                }
+                encryptable = status;
+            }
+
             /* Success!  Go get the next one */
             continue;
         }
diff --git a/fs_mgr/fs_mgr_fstab.c b/fs_mgr/fs_mgr_fstab.c
index 2c3c90d..8b0f714 100644
--- a/fs_mgr/fs_mgr_fstab.c
+++ b/fs_mgr/fs_mgr_fstab.c
@@ -61,6 +61,7 @@
     { "check",       MF_CHECK },
     { "encryptable=",MF_CRYPT },
     { "forceencrypt=",MF_FORCECRYPT },
+    { "fileencryption",MF_FILEENCRYPTION },
     { "nonremovable",MF_NONREMOVABLE },
     { "voldmanaged=",MF_VOLDMANAGED},
     { "length=",     MF_LENGTH },
@@ -418,27 +419,32 @@
     return fs_mgr_get_entry_for_mount_point_after(NULL, fstab, path);
 }
 
-int fs_mgr_is_voldmanaged(struct fstab_rec *fstab)
+int fs_mgr_is_voldmanaged(const struct fstab_rec *fstab)
 {
     return fstab->fs_mgr_flags & MF_VOLDMANAGED;
 }
 
-int fs_mgr_is_nonremovable(struct fstab_rec *fstab)
+int fs_mgr_is_nonremovable(const struct fstab_rec *fstab)
 {
     return fstab->fs_mgr_flags & MF_NONREMOVABLE;
 }
 
-int fs_mgr_is_verified(struct fstab_rec *fstab)
+int fs_mgr_is_verified(const struct fstab_rec *fstab)
 {
     return fstab->fs_mgr_flags & MF_VERIFY;
 }
 
-int fs_mgr_is_encryptable(struct fstab_rec *fstab)
+int fs_mgr_is_encryptable(const struct fstab_rec *fstab)
 {
     return fstab->fs_mgr_flags & (MF_CRYPT | MF_FORCECRYPT);
 }
 
-int fs_mgr_is_noemulatedsd(struct fstab_rec *fstab)
+int fs_mgr_is_file_encrypted(const struct fstab_rec *fstab)
+{
+    return fstab->fs_mgr_flags & MF_FILEENCRYPTION;
+}
+
+int fs_mgr_is_noemulatedsd(const struct fstab_rec *fstab)
 {
     return fstab->fs_mgr_flags & MF_NOEMULATEDSD;
 }
diff --git a/fs_mgr/fs_mgr_priv.h b/fs_mgr/fs_mgr_priv.h
index 88a1040..d56111a 100644
--- a/fs_mgr/fs_mgr_priv.h
+++ b/fs_mgr/fs_mgr_priv.h
@@ -76,6 +76,7 @@
 #define MF_FORCECRYPT   0x400
 #define MF_NOEMULATEDSD 0x800 /* no emulated sdcard daemon, sd card is the only
                                  external storage */
+#define MF_FILEENCRYPTION 0x2000
 
 #define DM_BUF_SIZE 4096
 
diff --git a/fs_mgr/include/fs_mgr.h b/fs_mgr/include/fs_mgr.h
index 3286948..c58a888 100644
--- a/fs_mgr/include/fs_mgr.h
+++ b/fs_mgr/include/fs_mgr.h
@@ -74,10 +74,13 @@
 struct fstab *fs_mgr_read_fstab(const char *fstab_path);
 void fs_mgr_free_fstab(struct fstab *fstab);
 
+#define FS_MGR_MNTALL_DEV_NON_DEFAULT_FILE_ENCRYPTED 5
+#define FS_MGR_MNTALL_DEV_DEFAULT_FILE_ENCRYPTED 4
 #define FS_MGR_MNTALL_DEV_NEEDS_RECOVERY 3
 #define FS_MGR_MNTALL_DEV_NEEDS_ENCRYPTION 2
 #define FS_MGR_MNTALL_DEV_MIGHT_BE_ENCRYPTED 1
 #define FS_MGR_MNTALL_DEV_NOT_ENCRYPTED 0
+#define FS_MGR_MNTALL_FAIL -1
 int fs_mgr_mount_all(struct fstab *fstab);
 
 #define FS_MGR_DOMNT_FAILED -1
@@ -94,11 +97,12 @@
                      const char *mount_point, const char *fs_type,
                      const char *blk_device);
 struct fstab_rec *fs_mgr_get_entry_for_mount_point(struct fstab *fstab, const char *path);
-int fs_mgr_is_voldmanaged(struct fstab_rec *fstab);
-int fs_mgr_is_nonremovable(struct fstab_rec *fstab);
-int fs_mgr_is_verified(struct fstab_rec *fstab);
-int fs_mgr_is_encryptable(struct fstab_rec *fstab);
-int fs_mgr_is_noemulatedsd(struct fstab_rec *fstab);
+int fs_mgr_is_voldmanaged(const struct fstab_rec *fstab);
+int fs_mgr_is_nonremovable(const struct fstab_rec *fstab);
+int fs_mgr_is_verified(const struct fstab_rec *fstab);
+int fs_mgr_is_encryptable(const struct fstab_rec *fstab);
+int fs_mgr_is_file_encrypted(const struct fstab_rec *fstab);
+int fs_mgr_is_noemulatedsd(const struct fstab_rec *fstab);
 int fs_mgr_swapon_all(struct fstab *fstab);
 #ifdef __cplusplus
 }
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/memory.h b/include/cutils/memory.h
index e725cdd..4d26882 100644
--- a/include/cutils/memory.h
+++ b/include/cutils/memory.h
@@ -30,7 +30,7 @@
 /* size is given in bytes and must be multiple of 4 */
 void android_memset32(uint32_t* dst, uint32_t value, size_t size);
 
-#if !HAVE_STRLCPY
+#if defined(__GLIBC__) || defined(_WIN32)
 /* Declaration of strlcpy() for platforms that don't already have it. */
 size_t strlcpy(char *dst, const char *src, size_t size);
 #endif
diff --git a/include/cutils/sockets.h b/include/cutils/sockets.h
index c47588c..f8076ca 100644
--- a/include/cutils/sockets.h
+++ b/include/cutils/sockets.h
@@ -18,6 +18,7 @@
 #define __CUTILS_SOCKETS_H
 
 #include <errno.h>
+#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <stdbool.h>
@@ -46,30 +47,19 @@
  */
 static inline int android_get_control_socket(const char *name)
 {
-	char key[64] = ANDROID_SOCKET_ENV_PREFIX;
-	const char *val;
-	int fd;
+	char key[64];
+	snprintf(key, sizeof(key), ANDROID_SOCKET_ENV_PREFIX "%s", name);
 
-	/* build our environment variable, counting cycles like a wolf ... */
-#if HAVE_STRLCPY
-	strlcpy(key + sizeof(ANDROID_SOCKET_ENV_PREFIX) - 1,
-		name,
-		sizeof(key) - sizeof(ANDROID_SOCKET_ENV_PREFIX));
-#else	/* for the host, which may lack the almightly strncpy ... */
-	strncpy(key + sizeof(ANDROID_SOCKET_ENV_PREFIX) - 1,
-		name,
-		sizeof(key) - sizeof(ANDROID_SOCKET_ENV_PREFIX));
-	key[sizeof(key)-1] = '\0';
-#endif
-
-	val = getenv(key);
-	if (!val)
+	const char* val = getenv(key);
+	if (!val) {
 		return -1;
+	}
 
 	errno = 0;
-	fd = strtol(val, NULL, 10);
-	if (errno)
+	int fd = strtol(val, NULL, 10);
+	if (errno) {
 		return -1;
+	}
 
 	return fd;
 }
diff --git a/include/cutils/str_parms.h b/include/cutils/str_parms.h
index 66f3637..aa1435a 100644
--- a/include/cutils/str_parms.h
+++ b/include/cutils/str_parms.h
@@ -18,6 +18,9 @@
 #define __CUTILS_STR_PARMS_H
 
 #include <stdint.h>
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
 
 struct str_parms;
 
@@ -52,4 +55,6 @@
 /* debug */
 void str_parms_dump(struct str_parms *str_parms);
 
+__END_DECLS
+
 #endif /* __CUTILS_STR_PARMS_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..fed81f8 100644
--- a/include/private/android_filesystem_config.h
+++ b/include/private/android_filesystem_config.h
@@ -22,8 +22,7 @@
 #ifndef _ANDROID_FILESYSTEM_CONFIG_H_
 #define _ANDROID_FILESYSTEM_CONFIG_H_
 
-#include <string.h>
-#include <sys/stat.h>
+#include <sys/cdefs.h>
 #include <sys/types.h>
 #include <stdint.h>
 
@@ -114,6 +113,14 @@
 #define AID_SHARED_GID_END   59999 /* start of gids for apps in each user to share */
 
 #if !defined(EXCLUDE_FS_CONFIG_STRUCTURES)
+/*
+ * Used in:
+ *  bionic/libc/bionic/stubs.cpp
+ *  external/libselinux/src/android.c
+ *  system/core/logd/LogStatistics.cpp
+ *  system/core/init/ueventd.cpp
+ *  system/core/init/util.cpp
+ */
 struct android_id_info {
     const char *name;
     unsigned aid;
@@ -191,116 +198,24 @@
     const char *prefix;
 };
 
-/* Rules for directories.
-** These rules are applied based on "first match", so they
-** should start with the most specific path and work their
-** way up to the root.
-*/
+/* Rules for directories and files has moved to system/code/libcutils/fs_config.c */
 
-static const struct fs_path_config android_dirs[] = {
-    { 00770, AID_SYSTEM, AID_CACHE,  0, "cache" },
-    { 00771, AID_SYSTEM, AID_SYSTEM, 0, "data/app" },
-    { 00771, AID_SYSTEM, AID_SYSTEM, 0, "data/app-private" },
-    { 00771, AID_ROOT,   AID_ROOT,   0, "data/dalvik-cache" },
-    { 00771, AID_SYSTEM, AID_SYSTEM, 0, "data/data" },
-    { 00771, AID_SHELL,  AID_SHELL,  0, "data/local/tmp" },
-    { 00771, AID_SHELL,  AID_SHELL,  0, "data/local" },
-    { 01771, AID_SYSTEM, AID_MISC,   0, "data/misc" },
-    { 00770, AID_DHCP,   AID_DHCP,   0, "data/misc/dhcp" },
-    { 00771, AID_SHARED_RELRO, AID_SHARED_RELRO, 0, "data/misc/shared_relro" },
-    { 00775, AID_MEDIA_RW, AID_MEDIA_RW, 0, "data/media" },
-    { 00775, AID_MEDIA_RW, AID_MEDIA_RW, 0, "data/media/Music" },
-    { 00771, AID_SYSTEM, AID_SYSTEM, 0, "data" },
-    { 00750, AID_ROOT,   AID_SHELL,  0, "sbin" },
-    { 00755, AID_ROOT,   AID_SHELL,  0, "system/bin" },
-    { 00755, AID_ROOT,   AID_SHELL,  0, "system/vendor" },
-    { 00755, AID_ROOT,   AID_SHELL,  0, "system/xbin" },
-    { 00755, AID_ROOT,   AID_ROOT,   0, "system/etc/ppp" },
-    { 00755, AID_ROOT,   AID_SHELL,  0, "vendor" },
-    { 00777, AID_ROOT,   AID_ROOT,   0, "sdcard" },
-    { 00755, AID_ROOT,   AID_ROOT,   0, 0 },
-};
+__BEGIN_DECLS
 
-/* Rules for files.
-** These rules are applied based on "first match", so they
-** should start with the most specific path and work their
-** way up to the root. Prefixes ending in * denotes wildcard
-** and will allow partial matches.
-*/
-static const struct fs_path_config android_files[] = {
-    { 00440, AID_ROOT,      AID_SHELL,     0, "system/etc/init.goldfish.rc" },
-    { 00550, AID_ROOT,      AID_SHELL,     0, "system/etc/init.goldfish.sh" },
-    { 00550, AID_ROOT,      AID_SHELL,     0, "system/etc/init.ril" },
-    { 00550, AID_DHCP,      AID_SHELL,     0, "system/etc/dhcpcd/dhcpcd-run-hooks" },
-    { 00555, AID_ROOT,      AID_ROOT,      0, "system/etc/ppp/*" },
-    { 00555, AID_ROOT,      AID_ROOT,      0, "system/etc/rc.*" },
-    { 00644, AID_SYSTEM,    AID_SYSTEM,    0, "data/app/*" },
-    { 00644, AID_MEDIA_RW,  AID_MEDIA_RW,  0, "data/media/*" },
-    { 00644, AID_SYSTEM,    AID_SYSTEM,    0, "data/app-private/*" },
-    { 00644, AID_APP,       AID_APP,       0, "data/data/*" },
+/*
+ * Used in:
+ *  build/tools/fs_config/fs_config.c
+ *  build/tools/fs_get_stats/fs_get_stats.c
+ *  external/genext2fs/genext2fs.c
+ *  external/squashfs-tools/squashfs-tools/android.c
+ *  system/core/cpio/mkbootfs.c
+ *  system/core/adb/file_sync_service.cpp
+ *  system/extras/ext4_utils/canned_fs_config.c
+ */
+void fs_config(const char *path, int dir,
+               unsigned *uid, unsigned *gid, unsigned *mode, uint64_t *capabilities);
 
-    /* the following five files are INTENTIONALLY set-uid, but they
-     * are NOT included on user builds. */
-    { 04750, AID_ROOT,      AID_SHELL,     0, "system/xbin/su" },
-    { 06755, AID_ROOT,      AID_ROOT,      0, "system/xbin/librank" },
-    { 06755, AID_ROOT,      AID_ROOT,      0, "system/xbin/procrank" },
-    { 06755, AID_ROOT,      AID_ROOT,      0, "system/xbin/procmem" },
-    { 04770, AID_ROOT,      AID_RADIO,     0, "system/bin/pppd-ril" },
+__END_DECLS
 
-    /* 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" },
-
-    { 00750, AID_ROOT,      AID_ROOT,      0, "system/bin/uncrypt" },
-    { 00750, AID_ROOT,      AID_ROOT,      0, "system/bin/install-recovery.sh" },
-    { 00755, AID_ROOT,      AID_SHELL,     0, "system/bin/*" },
-    { 00755, AID_ROOT,      AID_ROOT,      0, "system/lib/valgrind/*" },
-    { 00755, AID_ROOT,      AID_ROOT,      0, "system/lib64/valgrind/*" },
-    { 00755, AID_ROOT,      AID_SHELL,     0, "system/xbin/*" },
-    { 00755, AID_ROOT,      AID_SHELL,     0, "system/vendor/bin/*" },
-    { 00755, AID_ROOT,      AID_SHELL,     0, "vendor/bin/*" },
-    { 00750, AID_ROOT,      AID_SHELL,     0, "sbin/*" },
-    { 00755, AID_ROOT,      AID_ROOT,      0, "bin/*" },
-    { 00750, AID_ROOT,      AID_SHELL,     0, "init*" },
-    { 00750, AID_ROOT,      AID_SHELL,     0, "sbin/fs_mgr" },
-    { 00640, AID_ROOT,      AID_SHELL,     0, "fstab.*" },
-    { 00644, AID_ROOT,      AID_ROOT,      0, 0 },
-};
-
-static inline void fs_config(const char *path, int dir,
-                             unsigned *uid, unsigned *gid, unsigned *mode, uint64_t *capabilities)
-{
-    const struct fs_path_config *pc;
-    int plen;
-
-    if (path[0] == '/') {
-        path++;
-    }
-
-    pc = dir ? android_dirs : android_files;
-    plen = strlen(path);
-    for(; pc->prefix; pc++){
-        int len = strlen(pc->prefix);
-        if (dir) {
-            if(plen < len) continue;
-            if(!strncmp(pc->prefix, path, len)) break;
-            continue;
-        }
-        /* If name ends in * then allow partial matches. */
-        if (pc->prefix[len -1] == '*') {
-            if(!strncmp(pc->prefix, path, len - 1)) break;
-        } else if (plen == len){
-            if(!strncmp(pc->prefix, path, len)) break;
-        }
-    }
-    *uid = pc->uid;
-    *gid = pc->gid;
-    *mode = (*mode & (~07777)) | pc->mode;
-    *capabilities = pc->capabilities;
-
-#if 0
-    fprintf(stderr,"< '%s' '%s' %d %d %o >\n",
-            path, pc->prefix ? pc->prefix : "", *uid, *gid, *mode);
-#endif
-}
 #endif
 #endif
diff --git a/include/utils/Compat.h b/include/utils/Compat.h
index ca4a8e0..7d96310 100644
--- a/include/utils/Compat.h
+++ b/include/utils/Compat.h
@@ -41,12 +41,12 @@
 #define DEFFILEMODE 0666
 #endif /* _WIN32 */
 
-#if HAVE_PRINTF_ZD
-#  define ZD "%zd"
-#  define ZD_TYPE ssize_t
+#if defined(_WIN32)
+#define ZD "%ld"
+#define ZD_TYPE long
 #else
-#  define ZD "%ld"
-#  define ZD_TYPE long
+#define ZD "%zd"
+#define ZD_TYPE ssize_t
 #endif
 
 /*
diff --git a/init/Android.mk b/init/Android.mk
index 94d3dad..9d91a3f 100644
--- a/init/Android.mk
+++ b/init/Android.mk
@@ -50,7 +50,7 @@
     watchdogd.cpp \
 
 LOCAL_MODULE:= init
-
+LOCAL_C_INCLUDES += system/extras/ext4_utils
 LOCAL_FORCE_STATIC_EXECUTABLE := true
 LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT)
 LOCAL_UNSTRIPPED_PATH := $(TARGET_ROOT_OUT_UNSTRIPPED)
@@ -61,11 +61,14 @@
     liblogwrap \
     libcutils \
     libbase \
+    libext4_utils_static \
+    libutils \
     liblog \
     libc \
     libselinux \
     libmincrypt \
-    libext4_utils_static
+    libc++_static \
+    libdl
 
 # Create symlinks
 LOCAL_POST_INSTALL_CMD := $(hide) mkdir -p $(TARGET_ROOT_OUT)/sbin; \
diff --git a/init/builtins.cpp b/init/builtins.cpp
index aa5c649..3bbaf83 100644
--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -29,6 +29,7 @@
 #include <sys/wait.h>
 #include <unistd.h>
 #include <linux/loop.h>
+#include <ext4_crypt.h>
 
 #include <selinux/selinux.h>
 #include <selinux/label.h>
@@ -153,68 +154,6 @@
     return 0;
 }
 
-// TODO: remove execonce when exec is available.
-int do_execonce(int nargs, char **args)
-{
-    pid_t child;
-    int child_status = 0;
-    static int already_done;
-
-    if (already_done) {
-      return -1;
-    }
-    already_done = 1;
-    if (!(child = fork())) {
-        /*
-         * Child process.
-         */
-        zap_stdio();
-        char *exec_args[100];
-        size_t num_process_args = nargs;
-
-        memset(exec_args, 0, sizeof(exec_args));
-        if (num_process_args > ARRAY_SIZE(exec_args) - 1) {
-            ERROR("exec called with %zu args, limit is %zu", num_process_args,
-                  ARRAY_SIZE(exec_args) - 1);
-            _exit(1);
-        }
-        for (size_t i = 1; i < num_process_args; i++)
-            exec_args[i - 1] = args[i];
-
-        if (execv(exec_args[0], exec_args) == -1) {
-            ERROR("Failed to execv '%s' (%s)", exec_args[0], strerror(errno));
-            _exit(1);
-        }
-        ERROR("Returned from execv()!");
-        _exit(1);
-    }
-
-    /*
-     * Parent process.
-     */
-    if (child == -1) {
-        ERROR("Fork failed\n");
-        return -1;
-    }
-
-    if (TEMP_FAILURE_RETRY(waitpid(child, &child_status, 0)) == -1) {
-        ERROR("waitpid(): failed (%s)\n", strerror(errno));
-        return -1;
-    }
-
-    if (WIFSIGNALED(child_status)) {
-        INFO("Child exited due to signal %d\n", WTERMSIG(child_status));
-        return -1;
-    } else if (WIFEXITED(child_status)) {
-        INFO("Child exited normally (exit code %d)\n", WEXITSTATUS(child_status));
-        return WEXITSTATUS(child_status);
-    }
-
-    ERROR("Abnormal child process exit\n");
-
-    return -1;
-}
-
 int do_export(int nargs, char **args)
 {
     return add_environment(args[1], args[2]);
@@ -302,7 +241,7 @@
         }
     }
 
-    return 0;
+    return e4crypt_set_directory_policy(args[1]);
 }
 
 static struct {
@@ -446,6 +385,17 @@
     while (1) { pause(); }  // never reached
 }
 
+/*
+ * Callback to make a directory from the ext4 code
+ */
+static int do_mount_alls_make_dir(const char* dir)
+{
+    if (make_dir(dir, 0700) && errno != EEXIST) {
+        return -1;
+    }
+
+    return 0;
+}
 
 /*
  * This function might request a reboot, in which case it will
@@ -514,6 +464,37 @@
         ERROR("fs_mgr_mount_all suggested recovery, so wiping data via recovery.\n");
         ret = wipe_data_via_recovery();
         /* If reboot worked, there is no return. */
+    } else if (ret == FS_MGR_MNTALL_DEV_DEFAULT_FILE_ENCRYPTED) {
+        // We have to create the key files here. Only init can call make_dir,
+        // and we can't do it from fs_mgr as then fs_mgr would depend on
+        // make_dir creating a circular dependency.
+        fstab = fs_mgr_read_fstab(args[1]);
+        for (int i = 0; i < fstab->num_entries; ++i) {
+            if (fs_mgr_is_file_encrypted(&fstab->recs[i])) {
+              if (e4crypt_create_device_key(fstab->recs[i].mount_point,
+                                            do_mount_alls_make_dir)) {
+                    ERROR("Could not create device key on %s"
+                          " - continue unencrypted\n",
+                          fstab->recs[i].mount_point);
+                }
+            }
+        }
+        fs_mgr_free_fstab(fstab);
+
+        if (e4crypt_install_keyring()) {
+            return -1;
+        }
+        property_set("ro.crypto.state", "encrypted");
+
+        // Although encrypted, we have device key, so we do not need to
+        // do anything different from the nonencrypted case.
+        action_for_each_trigger("nonencrypted", action_add_queue_tail);
+    } else if (ret == FS_MGR_MNTALL_DEV_NON_DEFAULT_FILE_ENCRYPTED) {
+        if (e4crypt_install_keyring()) {
+            return -1;
+        }
+        property_set("ro.crypto.state", "encrypted");
+        property_set("vold.decrypt", "trigger_restart_min_framework");
     } else if (ret > 0) {
         ERROR("fs_mgr_mount_all returned unexpected error %d\n", ret);
     }
@@ -867,3 +848,12 @@
     } else
         return -1;
 }
+
+int do_installkey(int nargs, char **args)
+{
+    if (nargs == 2) {
+        return e4crypt_install_key(args[1]);
+    }
+
+    return -1;
+}
diff --git a/init/init_parser.cpp b/init/init_parser.cpp
index 294dc19..af935d7 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;
@@ -139,7 +138,6 @@
     case 'e':
         if (!strcmp(s, "nable")) return K_enable;
         if (!strcmp(s, "xec")) return K_exec;
-        if (!strcmp(s, "xeconce")) return K_execonce;
         if (!strcmp(s, "xport")) return K_export;
         break;
     case 'g':
@@ -153,6 +151,7 @@
         if (!strcmp(s, "fup")) return K_ifup;
         if (!strcmp(s, "nsmod")) return K_insmod;
         if (!strcmp(s, "mport")) return K_import;
+        if (!strcmp(s, "nstallkey")) return K_installkey;
         break;
     case 'k':
         if (!strcmp(s, "eycodes")) return K_keycodes;
@@ -775,8 +774,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 09f645b..059dde1 100644
--- a/init/keywords.h
+++ b/init/keywords.h
@@ -6,11 +6,11 @@
 int do_domainname(int nargs, char **args);
 int do_enable(int nargs, char **args);
 int do_exec(int nargs, char **args);
-int do_execonce(int nargs, char **args);
 int do_export(int nargs, char **args);
 int do_hostname(int nargs, char **args);
 int do_ifup(int nargs, char **args);
 int do_insmod(int nargs, char **args);
+int do_installkey(int nargs, char **args);
 int do_mkdir(int nargs, char **args);
 int do_mount_all(int nargs, char **args);
 int do_mount(int nargs, char **args);
@@ -44,7 +44,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)
@@ -55,12 +54,12 @@
     KEYWORD(domainname,  COMMAND, 1, do_domainname)
     KEYWORD(enable,      COMMAND, 1, do_enable)
     KEYWORD(exec,        COMMAND, 1, do_exec)
-    KEYWORD(execonce,    COMMAND, 1, do_execonce)
     KEYWORD(export,      COMMAND, 2, do_export)
     KEYWORD(group,       OPTION,  0, 0)
     KEYWORD(hostname,    COMMAND, 1, do_hostname)
     KEYWORD(ifup,        COMMAND, 1, do_ifup)
     KEYWORD(insmod,      COMMAND, 1, do_insmod)
+    KEYWORD(installkey,  COMMAND, 1, do_installkey)
     KEYWORD(import,      SECTION, 1, 0)
     KEYWORD(keycodes,    OPTION,  0, 0)
     KEYWORD(mkdir,       COMMAND, 1, do_mkdir)
diff --git a/init/readme.txt b/init/readme.txt
index 630dd03..84afd11 100644
--- a/init/readme.txt
+++ b/init/readme.txt
@@ -182,10 +182,6 @@
    groups can be provided. No other commands will be run until this one
    finishes.
 
-execonce <path> [ <argument> ]*
-   Use exec instead. This command will be removed after existing callers have
-   moved to exec.
-
 export <name> <value>
    Set the environment variable <name> equal to <value> in the
    global environment (which will be inherited by all processes
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..4af6592 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) {
@@ -121,8 +124,10 @@
 }
 
 void VerifyLevelDump(Backtrace* backtrace) {
-  ASSERT_GT(backtrace->NumFrames(), static_cast<size_t>(0));
-  ASSERT_LT(backtrace->NumFrames(), static_cast<size_t>(MAX_BACKTRACE_FRAMES));
+  ASSERT_GT(backtrace->NumFrames(), static_cast<size_t>(0))
+    << DumpFrames(backtrace);
+  ASSERT_LT(backtrace->NumFrames(), static_cast<size_t>(MAX_BACKTRACE_FRAMES))
+    << DumpFrames(backtrace);
 
   // Look through the frames starting at the highest to find the
   // frame we want.
@@ -133,13 +138,17 @@
       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");
-  ASSERT_EQ(backtrace->GetFrame(frame_num-2)->func_name, "test_level_three");
-  ASSERT_EQ(backtrace->GetFrame(frame_num-3)->func_name, "test_level_four");
+  ASSERT_EQ(backtrace->GetFrame(frame_num)->func_name, "test_level_one")
+    << DumpFrames(backtrace);
+  ASSERT_EQ(backtrace->GetFrame(frame_num-1)->func_name, "test_level_two")
+    << DumpFrames(backtrace);
+  ASSERT_EQ(backtrace->GetFrame(frame_num-2)->func_name, "test_level_three")
+    << DumpFrames(backtrace);
+  ASSERT_EQ(backtrace->GetFrame(frame_num-3)->func_name, "test_level_four")
+    << DumpFrames(backtrace);
 }
 
 void VerifyLevelBacktrace(void*) {
@@ -156,10 +165,11 @@
 }
 
 void VerifyMaxDump(Backtrace* backtrace) {
-  ASSERT_EQ(backtrace->NumFrames(), static_cast<size_t>(MAX_BACKTRACE_FRAMES));
+  ASSERT_EQ(backtrace->NumFrames(), static_cast<size_t>(MAX_BACKTRACE_FRAMES))
+    << DumpFrames(backtrace);
   // Verify that the last frame is our recursive call.
-  ASSERT_EQ(backtrace->GetFrame(MAX_BACKTRACE_FRAMES-1)->func_name,
-            "test_recursive_call");
+  ASSERT_EQ(backtrace->GetFrame(MAX_BACKTRACE_FRAMES-1)->func_name, "test_recursive_call")
+    << DumpFrames(backtrace);
 }
 
 void VerifyMaxBacktrace(void*) {
@@ -198,6 +208,24 @@
   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.get() != nullptr);
+  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);
 }
@@ -205,8 +233,10 @@
 void VerifyIgnoreFrames(
     Backtrace* bt_all, Backtrace* bt_ign1,
     Backtrace* bt_ign2, const char* cur_proc) {
-  EXPECT_EQ(bt_all->NumFrames(), bt_ign1->NumFrames() + 1);
-  EXPECT_EQ(bt_all->NumFrames(), bt_ign2->NumFrames() + 2);
+  EXPECT_EQ(bt_all->NumFrames(), bt_ign1->NumFrames() + 1)
+    << "All backtrace:\n" << DumpFrames(bt_all) << "Ignore 1 backtrace:\n" << DumpFrames(bt_ign1);
+  EXPECT_EQ(bt_all->NumFrames(), bt_ign2->NumFrames() + 2)
+    << "All backtrace:\n" << DumpFrames(bt_all) << "Ignore 2 backtrace:\n" << DumpFrames(bt_ign2);
 
   // Check all of the frames are the same > the current frame.
   bool check = (cur_proc == nullptr);
@@ -264,6 +294,7 @@
   }
   uint64_t start = NanoTime();
   bool verified = false;
+  std::string last_dump;
   do {
     usleep(US_PER_MSEC);
     if (ptrace(PTRACE_ATTACH, ptrace_tid, 0, 0) == 0) {
@@ -275,18 +306,20 @@
         map.reset(BacktraceMap::Create(pid));
       }
       std::unique_ptr<Backtrace> backtrace(Backtrace::Create(pid, tid, map.get()));
-      ASSERT_TRUE(backtrace->Unwind(0));
       ASSERT_TRUE(backtrace.get() != nullptr);
+      ASSERT_TRUE(backtrace->Unwind(0));
       if (ReadyFunc(backtrace.get())) {
         VerifyFunc(backtrace.get());
         verified = true;
+      } else {
+        last_dump = DumpFrames(backtrace.get());
       }
 
       ASSERT_TRUE(ptrace(PTRACE_DETACH, ptrace_tid, 0, 0) == 0);
     }
     // If 5 seconds have passed, then we are done.
   } while (!verified && (NanoTime() - start) <= 5 * NS_PER_SEC);
-  ASSERT_TRUE(verified);
+  ASSERT_TRUE(verified) << "Last backtrace:\n" << last_dump;
 }
 
 TEST(libbacktrace, ptrace_trace) {
@@ -490,9 +523,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);
 }
@@ -674,16 +711,19 @@
   BacktraceMap* map3 = BacktraceMap::Create(getpid());
 
   Backtrace* back1 = Backtrace::Create(getpid(), BACKTRACE_CURRENT_THREAD, map1);
+  ASSERT_TRUE(back1 != nullptr);
   EXPECT_TRUE(back1->Unwind(0));
   delete back1;
   delete map1;
 
   Backtrace* back2 = Backtrace::Create(getpid(), BACKTRACE_CURRENT_THREAD, map2);
+  ASSERT_TRUE(back2 != nullptr);
   EXPECT_TRUE(back2->Unwind(0));
   delete back2;
   delete map2;
 
   Backtrace* back3 = Backtrace::Create(getpid(), BACKTRACE_CURRENT_THREAD, map3);
+  ASSERT_TRUE(back3 != nullptr);
   EXPECT_TRUE(back3->Unwind(0));
   delete back3;
   delete map3;
@@ -858,10 +898,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);
@@ -960,6 +1005,7 @@
       WaitForStop(pid);
 
       std::unique_ptr<Backtrace> backtrace(Backtrace::Create(pid, pid));
+      ASSERT_TRUE(backtrace.get() != nullptr);
 
       uintptr_t read_addr;
       size_t bytes_read = backtrace->Read(reinterpret_cast<uintptr_t>(&g_ready),
@@ -1005,6 +1051,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 +1061,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..c636196 100644
--- a/libcutils/Android.mk
+++ b/libcutils/Android.mk
@@ -22,6 +22,7 @@
 	native_handle.c \
 	config_utils.c \
 	load_file.c \
+	strlcpy.c \
 	open_memstream.c \
 	strdup16to8.c \
 	strdup8to16.c \
@@ -31,6 +32,7 @@
 	sched_policy.c \
 	iosched_policy.c \
 	str_parms.c \
+	fs_config.c
 
 # some files must not be compiled when building against Mingw
 # they correspond to features not used by our host development tools
@@ -59,7 +61,8 @@
         sockets.c \
 
     commonHostSources += \
-        ashmem-host.c
+        ashmem-host.c \
+        trace-host.c
 
 endif
 
@@ -73,7 +76,6 @@
 LOCAL_CFLAGS += -Werror
 endif
 LOCAL_MULTILIB := both
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
 include $(BUILD_HOST_STATIC_LIBRARY)
 
 include $(CLEAR_VARS)
@@ -84,22 +86,8 @@
 LOCAL_CFLAGS += -Werror
 endif
 LOCAL_MULTILIB := both
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
 include $(BUILD_HOST_SHARED_LIBRARY)
 
-# Tests for host
-# ========================================================
-include $(CLEAR_VARS)
-LOCAL_MODULE := tst_str_parms
-LOCAL_CFLAGS += -DTEST_STR_PARMS
-ifneq ($(HOST_OS),windows)
-LOCAL_CFLAGS += -Werror
-endif
-LOCAL_SRC_FILES := str_parms.c hashmap.c memory.c
-LOCAL_STATIC_LIBRARIES := liblog
-LOCAL_MODULE_TAGS := optional
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
-include $(BUILD_HOST_EXECUTABLE)
 
 
 # Shared and static library for target
@@ -112,32 +100,19 @@
         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 += \
-        arch-arm/memset32.S \
-
 # arch-arm/memset32.S does not compile with Clang.
 LOCAL_CLANG_ASFLAGS_arm += -no-integrated-as
 
-LOCAL_SRC_FILES_arm64 += \
-        arch-arm64/android_memset.S \
-
-ifndef ARCH_MIPS_REV6
-LOCAL_SRC_FILES_mips += \
-        arch-mips/android_memset.c \
-
-LOCAL_CFLAGS_mips += -DHAVE_MEMSET16 -DHAVE_MEMSET32
-endif
-
-# TODO: switch mips64 back to using arch-mips/android_memset.c
-LOCAL_SRC_FILES_mips64 += \
-#       arch-mips/android_memset.c \
+LOCAL_SRC_FILES_arm += arch-arm/memset32.S
+LOCAL_SRC_FILES_arm64 += arch-arm64/android_memset.S
+LOCAL_SRC_FILES_mips += arch-mips/android_memset.S
+LOCAL_SRC_FILES_mips64 += arch-mips/android_memset.S
 
 LOCAL_SRC_FILES_x86 += \
         arch-x86/android_memset16.S \
@@ -147,16 +122,9 @@
         arch-x86_64/android_memset16.S \
         arch-x86_64/android_memset32.S \
 
-LOCAL_CFLAGS_arm += -DHAVE_MEMSET16 -DHAVE_MEMSET32
-LOCAL_CFLAGS_arm64 += -DHAVE_MEMSET16 -DHAVE_MEMSET32
-#LOCAL_CFLAGS_mips64 += -DHAVE_MEMSET16 -DHAVE_MEMSET32
-LOCAL_CFLAGS_x86 += -DHAVE_MEMSET16 -DHAVE_MEMSET32
-LOCAL_CFLAGS_x86_64 += -DHAVE_MEMSET16 -DHAVE_MEMSET32
-
 LOCAL_C_INCLUDES := $(libcutils_c_includes)
 LOCAL_STATIC_LIBRARIES := liblog
 LOCAL_CFLAGS += -Werror -std=gnu90
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
 include $(BUILD_STATIC_LIBRARY)
 
 include $(CLEAR_VARS)
@@ -167,16 +135,6 @@
 LOCAL_SHARED_LIBRARIES := liblog
 LOCAL_CFLAGS += -Werror
 LOCAL_C_INCLUDES := $(libcutils_c_includes)
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
 include $(BUILD_SHARED_LIBRARY)
 
-include $(CLEAR_VARS)
-LOCAL_MODULE := tst_str_parms
-LOCAL_CFLAGS += -DTEST_STR_PARMS -Werror
-LOCAL_SRC_FILES := str_parms.c hashmap.c memory.c
-LOCAL_SHARED_LIBRARIES := liblog
-LOCAL_MODULE_TAGS := optional
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
-include $(BUILD_EXECUTABLE)
-
 include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/libcutils/arch-mips/android_memset.S b/libcutils/arch-mips/android_memset.S
new file mode 100644
index 0000000..6811de0
--- /dev/null
+++ b/libcutils/arch-mips/android_memset.S
@@ -0,0 +1,323 @@
+/*
+ * Copyright (c) 2009
+ *      MIPS Technologies, Inc., California.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the MIPS Technologies, Inc., nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE MIPS TECHNOLOGIES, INC. ``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 MIPS TECHNOLOGIES, INC. 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.
+ */
+
+/************************************************************************
+ *
+ *  memset.S, version "64h" with 1 cache line horizon for "pref 30" and 14 nops
+ *  Version: "043009"
+ *
+ ************************************************************************/
+
+
+/************************************************************************
+ *  Include files
+ ************************************************************************/
+
+#include <machine/asm.h>
+#define END(f) .cfi_endproc; .size f, .-f; .end f
+
+/*
+ * This routine could be optimized for MIPS64. The current code only
+ * uses MIPS32 instructions.
+ */
+
+#if defined(__MIPSEB__)
+#  define SWHI	swl		/* high part is left in big-endian	*/
+#  define SWLO	swr		/* low part is right in big-endian	*/
+#endif
+
+#if defined(__MIPSEL__)
+#  define SWHI	swr		/* high part is right in little-endian	*/
+#  define SWLO	swl		/* low part is left in little-endian	*/
+#endif
+
+#if !(defined(XGPROF) || defined(XPROF))
+#undef SETUP_GP
+#define SETUP_GP
+#endif
+
+#ifdef NDEBUG
+#define DBG #
+#else
+#define DBG
+#endif
+
+/*
+ * void android_memset16(uint16_t* dst, uint16_t value, size_t size);
+ */
+
+LEAF(android_memset16,0)
+	.set noreorder
+DBG	/* Check parameters */
+DBG	andi	t0,a0,1			# a0 must be halfword aligned
+DBG	tne	t0,zero
+DBG	andi	t2,a2,1			# a2 must be even
+DBG	tne	t2,zero
+
+#ifdef FIXARGS
+	# ensure count is even
+#if (__mips==32) && (__mips_isa_rev>=2)
+	ins	a2,zero,0,1
+#else
+	ori	a2,1
+	xori	a2,1
+#endif
+#endif
+
+#if (__mips==32) && (__mips_isa_rev>=2)
+	ins	a1,a1,16,16
+#else
+	andi	a1,0xffff
+	sll	t3,a1,16
+	or	a1,t3
+#endif
+
+	beqz	a2,.Ldone
+	 andi	t1,a0,2
+	beqz	t1,.Lalignok
+	 addu	t0,a0,a2		# t0 is the "past the end" address
+	sh	a1,0(a0)		# store one halfword to get aligned
+	addu	a0,2
+	subu	a2,2
+.Lalignok:
+	slti	t1,a2,4			# .Laligned for 4 or more bytes
+	beqz	t1,.Laligned
+	 sne	t1,a2,2			# one more halfword?
+	bnez	t1,.Ldone
+	 nop
+	sh	a1,0(a0)
+.Ldone:
+	j	ra
+	 nop
+	.set reorder
+END(android_memset16)
+
+/*
+ * void android_memset32(uint32_t* dst, uint32_t value, size_t size);
+ */
+
+LEAF(android_memset32,0)
+	.set noreorder
+DBG	/* Check parameters */
+DBG	andi	t0,a0,3			# a0 must be word aligned
+DBG	tne	t0,zero
+DBG	andi	t2,a2,3			# a2 must be a multiple of 4 bytes
+DBG	tne	t2,zero
+
+#ifdef FIXARGS
+	# ensure count is a multiple of 4
+#if (__mips==32) && (__mips_isa_rev>=2)
+	ins	$a2,$0,0,2
+#else
+	ori	a2,3
+	xori	a2,3
+#endif
+#endif
+
+	bnez	a2,.Laligned		# any work to do?
+	 addu	t0,a0,a2		# t0 is the "past the end" address
+
+	j	ra
+	 nop
+	.set reorder
+END(android_memset32)
+
+LEAF(memset,0)
+
+	.set	noreorder
+	.set	noat
+
+	addu	t0,a0,a2		# t0 is the "past the end" address
+	slti	AT,a2,4			# is a2 less than 4?
+	bne	AT,zero,.Llast4		# if yes, go to last4
+	 move	v0,a0			# memset returns the dst pointer
+
+	beq	a1,zero,.Lset0
+	 subu	v1,zero,a0
+
+	# smear byte into 32 bit word
+#if (__mips==32) && (__mips_isa_rev>=2)
+	ins     a1, a1, 8, 8        # Replicate fill byte into half-word.
+	ins     a1, a1, 16, 16      # Replicate fill byte into word.
+#else
+	and	a1,0xff
+	sll	AT,a1,8
+	or	a1,AT
+	sll	AT,a1,16
+	or	a1,AT
+#endif
+
+.Lset0:
+	andi	v1,v1,0x3		# word-unaligned address?
+	beq	v1,zero,.Laligned	# v1 is the unalignment count
+	 subu	a2,a2,v1
+	SWHI	a1,0(a0)
+	addu	a0,a0,v1
+
+# Here we have the "word-aligned" a0 (until the "last4")
+.Laligned:
+	andi	t8,a2,0x3f	# any 64-byte chunks?
+				# t8 is the byte count past 64-byte chunks
+	beq	a2,t8,.Lchk8w	# when a2==t8, no 64-byte chunks
+				# There will be at most 1 32-byte chunk then
+	 subu	a3,a2,t8	# subtract from a2 the reminder
+				# Here a3 counts bytes in 16w chunks
+	addu	a3,a0,a3	# Now a3 is the final dst after 64-byte chunks
+
+# Find out, if there are any 64-byte chunks after which will be still at least
+# 96 bytes left. The value "96" is calculated as needed buffer for
+# "pref 30,64(a0)" prefetch, which can be used as "pref 30,0(a0)" after
+# incrementing "a0" by 64.
+# For "a2" below 160 there will be no such "pref 30 safe" 64-byte chunk.
+#
+	sltiu	v1,a2,160
+	bgtz	v1,.Lloop16w_nopref30	# skip "pref 30,0(a0)"
+	 subu	t7,a2,96	# subtract "pref 30 unsafe" region
+		# below we have at least 1 64-byte chunk which is "pref 30 safe"
+	andi	t6,t7,0x3f	# t6 is past "64-byte safe chunks" reminder
+	subu	t5,t7,t6	# subtract from t7 the reminder
+				# Here t5 counts bytes in 16w "safe" chunks
+	addu	t4,a0,t5	# Now t4 is the dst after 64-byte "safe" chunks
+
+# Don't use "pref 30,0(a0)" for a0 in a "middle" of a cache line
+#	pref	30,0(a0)
+# Here we are in the region, where it is safe to use "pref 30,64(a0)"
+.Lloop16w:
+	addiu	a0,a0,64
+	pref	30,-32(a0)	# continue setting up the dest, addr 64-32
+	sw	a1,-64(a0)
+	sw	a1,-60(a0)
+	sw	a1,-56(a0)
+	sw	a1,-52(a0)
+	sw	a1,-48(a0)
+	sw	a1,-44(a0)
+	sw	a1,-40(a0)
+	sw	a1,-36(a0)
+	nop
+	nop			# the extra nop instructions help to balance
+	nop			# cycles needed for "store" + "fill" + "evict"
+	nop			# For 64byte store there are needed 8 fill
+	nop			# and 8 evict cycles, i.e. at least 32 instr.
+	nop
+	nop
+	pref	30,0(a0)	# continue setting up the dest, addr 64-0
+	sw	a1,-32(a0)
+	sw	a1,-28(a0)
+	sw	a1,-24(a0)
+	sw	a1,-20(a0)
+	sw	a1,-16(a0)
+	sw	a1,-12(a0)
+	sw	a1,-8(a0)
+	sw	a1,-4(a0)
+	nop
+	nop
+	nop
+	nop			# NOTE: adding 14 nop-s instead of 12 nop-s
+	nop			# gives better results for "fast" memory
+	nop
+	bne	a0,t4,.Lloop16w
+	 nop
+
+	beq	a0,a3,.Lchk8w	# maybe no more 64-byte chunks?
+	 nop			# this "delayed slot" is useless ...
+
+.Lloop16w_nopref30:	# there could be up to 3 "64-byte nopref30" chunks
+	addiu	a0,a0,64
+	sw	a1,-64(a0)
+	sw	a1,-60(a0)
+	sw	a1,-56(a0)
+	sw	a1,-52(a0)
+	sw	a1,-48(a0)
+	sw	a1,-44(a0)
+	sw	a1,-40(a0)
+	sw	a1,-36(a0)
+	sw	a1,-32(a0)
+	sw	a1,-28(a0)
+	sw	a1,-24(a0)
+	sw	a1,-20(a0)
+	sw	a1,-16(a0)
+	sw	a1,-12(a0)
+	sw	a1,-8(a0)
+	bne	a0,a3,.Lloop16w_nopref30
+	 sw	a1,-4(a0)
+
+.Lchk8w:		# t8 here is the byte count past 64-byte chunks
+
+	andi	t7,t8,0x1f	# is there a 32-byte chunk?
+				# the t7 is the reminder count past 32-bytes
+	beq	t8,t7,.Lchk1w	# when t8==t7, no 32-byte chunk
+	 move	a2,t7
+
+	sw	a1,0(a0)
+	sw	a1,4(a0)
+	sw	a1,8(a0)
+	sw	a1,12(a0)
+	sw	a1,16(a0)
+	sw	a1,20(a0)
+	sw	a1,24(a0)
+	sw	a1,28(a0)
+	addiu	a0,a0,32
+
+.Lchk1w:
+	andi	t8,a2,0x3	# now t8 is the reminder past 1w chunks
+	beq	a2,t8,.Llast4aligned
+	 subu	a3,a2,t8	# a3 is the count of bytes in 1w chunks
+	addu	a3,a0,a3	# now a3 is the dst address past the 1w chunks
+
+# copying in words (4-byte chunks)
+.LwordCopy_loop:
+	addiu	a0,a0,4
+	bne	a0,a3,.LwordCopy_loop
+	 sw	a1,-4(a0)
+
+# store last 0-3 bytes
+# this will repeat the last store if the memset finishes on a word boundary
+.Llast4aligned:
+	j	ra
+	 SWLO	a1,-1(t0)
+
+.Llast4:
+	beq	a0,t0,.Llast4e
+.Llast4l:
+	 addiu	a0,a0,1
+	bne	a0,t0,.Llast4l
+	 sb	a1,-1(a0)
+.Llast4e:
+	j	ra
+	 nop
+
+	.set	at
+	.set	reorder
+
+END(memset)
+
+
+/************************************************************************
+ *  Implementation : Static functions
+ ************************************************************************/
diff --git a/libcutils/arch-mips/android_memset.c b/libcutils/arch-mips/android_memset.c
deleted file mode 100644
index bbc99fe..0000000
--- a/libcutils/arch-mips/android_memset.c
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * 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/memory.h>
-
-/* Use mips-assembler versions supplied by bionic/libc/arch-mips/string/memset.S: */
-void _memset16(uint16_t* dst, uint16_t value, size_t size);
-void _memset32(uint32_t* dst, uint32_t value, size_t size);
-
-void android_memset16(uint16_t* dst, uint16_t value, size_t size)
-{
-    _memset16(dst, value, size);
-}
-
-void android_memset32(uint32_t* dst, uint32_t value, size_t size)
-{
-    _memset32(dst, value, size);
-}
diff --git a/libcutils/fs_config.c b/libcutils/fs_config.c
new file mode 100644
index 0000000..659f614
--- /dev/null
+++ b/libcutils/fs_config.c
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2007 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.
+ */
+
+/* This file is used to define the properties of the filesystem
+** images generated by build tools (mkbootfs and mkyaffs2image) and
+** by the device side of adb.
+*/
+
+#include <stdint.h>
+#include <string.h>
+#include <sys/stat.h>
+
+#include <private/android_filesystem_config.h>
+
+/* Rules for directories.
+** These rules are applied based on "first match", so they
+** should start with the most specific path and work their
+** way up to the root.
+*/
+
+static const struct fs_path_config android_dirs[] = {
+    { 00770, AID_SYSTEM, AID_CACHE,  0, "cache" },
+    { 00771, AID_SYSTEM, AID_SYSTEM, 0, "data/app" },
+    { 00771, AID_SYSTEM, AID_SYSTEM, 0, "data/app-private" },
+    { 00771, AID_ROOT,   AID_ROOT,   0, "data/dalvik-cache" },
+    { 00771, AID_SYSTEM, AID_SYSTEM, 0, "data/data" },
+    { 00771, AID_SHELL,  AID_SHELL,  0, "data/local/tmp" },
+    { 00771, AID_SHELL,  AID_SHELL,  0, "data/local" },
+    { 01771, AID_SYSTEM, AID_MISC,   0, "data/misc" },
+    { 00770, AID_DHCP,   AID_DHCP,   0, "data/misc/dhcp" },
+    { 00771, AID_SHARED_RELRO, AID_SHARED_RELRO, 0, "data/misc/shared_relro" },
+    { 00775, AID_MEDIA_RW, AID_MEDIA_RW, 0, "data/media" },
+    { 00775, AID_MEDIA_RW, AID_MEDIA_RW, 0, "data/media/Music" },
+    { 00771, AID_SYSTEM, AID_SYSTEM, 0, "data" },
+    { 00750, AID_ROOT,   AID_SHELL,  0, "sbin" },
+    { 00755, AID_ROOT,   AID_SHELL,  0, "system/bin" },
+    { 00755, AID_ROOT,   AID_SHELL,  0, "system/vendor" },
+    { 00755, AID_ROOT,   AID_SHELL,  0, "system/xbin" },
+    { 00755, AID_ROOT,   AID_ROOT,   0, "system/etc/ppp" },
+    { 00755, AID_ROOT,   AID_SHELL,  0, "vendor" },
+    { 00777, AID_ROOT,   AID_ROOT,   0, "sdcard" },
+    { 00755, AID_ROOT,   AID_ROOT,   0, 0 },
+};
+
+/* Rules for files.
+** These rules are applied based on "first match", so they
+** should start with the most specific path and work their
+** way up to the root. Prefixes ending in * denotes wildcard
+** and will allow partial matches.
+*/
+static const struct fs_path_config android_files[] = {
+    { 00440, AID_ROOT,      AID_SHELL,     0, "system/etc/init.goldfish.rc" },
+    { 00550, AID_ROOT,      AID_SHELL,     0, "system/etc/init.goldfish.sh" },
+    { 00550, AID_ROOT,      AID_SHELL,     0, "system/etc/init.ril" },
+    { 00550, AID_DHCP,      AID_SHELL,     0, "system/etc/dhcpcd/dhcpcd-run-hooks" },
+    { 00555, AID_ROOT,      AID_ROOT,      0, "system/etc/ppp/*" },
+    { 00555, AID_ROOT,      AID_ROOT,      0, "system/etc/rc.*" },
+    { 00644, AID_SYSTEM,    AID_SYSTEM,    0, "data/app/*" },
+    { 00644, AID_MEDIA_RW,  AID_MEDIA_RW,  0, "data/media/*" },
+    { 00644, AID_SYSTEM,    AID_SYSTEM,    0, "data/app-private/*" },
+    { 00644, AID_APP,       AID_APP,       0, "data/data/*" },
+
+    /* the following five files are INTENTIONALLY set-uid, but they
+     * are NOT included on user builds. */
+    { 04750, AID_ROOT,      AID_SHELL,     0, "system/xbin/su" },
+    { 06755, AID_ROOT,      AID_ROOT,      0, "system/xbin/librank" },
+    { 06755, AID_ROOT,      AID_ROOT,      0, "system/xbin/procrank" },
+    { 06755, AID_ROOT,      AID_ROOT,      0, "system/xbin/procmem" },
+    { 04770, AID_ROOT,      AID_RADIO,     0, "system/bin/pppd-ril" },
+
+    /* the following files have enhanced capabilities and ARE included in user builds. */
+    { 00750, AID_ROOT,      AID_SHELL,     (1ULL << CAP_SETUID) | (1ULL << CAP_SETGID), "system/bin/run-as" },
+    { 00700, AID_SYSTEM,    AID_SHELL,     (1ULL << 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" },
+    { 00755, AID_ROOT,      AID_SHELL,     0, "system/bin/*" },
+    { 00755, AID_ROOT,      AID_ROOT,      0, "system/lib/valgrind/*" },
+    { 00755, AID_ROOT,      AID_ROOT,      0, "system/lib64/valgrind/*" },
+    { 00755, AID_ROOT,      AID_SHELL,     0, "system/xbin/*" },
+    { 00755, AID_ROOT,      AID_SHELL,     0, "system/vendor/bin/*" },
+    { 00755, AID_ROOT,      AID_SHELL,     0, "vendor/bin/*" },
+    { 00750, AID_ROOT,      AID_SHELL,     0, "sbin/*" },
+    { 00755, AID_ROOT,      AID_ROOT,      0, "bin/*" },
+    { 00750, AID_ROOT,      AID_SHELL,     0, "init*" },
+    { 00750, AID_ROOT,      AID_SHELL,     0, "sbin/fs_mgr" },
+    { 00640, AID_ROOT,      AID_SHELL,     0, "fstab.*" },
+    { 00644, AID_ROOT,      AID_ROOT,      0, 0 },
+};
+
+void fs_config(const char *path, int dir,
+               unsigned *uid, unsigned *gid, unsigned *mode, uint64_t *capabilities)
+{
+    const struct fs_path_config *pc;
+    int plen;
+
+    if (path[0] == '/') {
+        path++;
+    }
+
+    pc = dir ? android_dirs : android_files;
+    plen = strlen(path);
+    for(; pc->prefix; pc++){
+        int len = strlen(pc->prefix);
+        if (dir) {
+            if(plen < len) continue;
+            if(!strncmp(pc->prefix, path, len)) break;
+            continue;
+        }
+        /* If name ends in * then allow partial matches. */
+        if (pc->prefix[len -1] == '*') {
+            if(!strncmp(pc->prefix, path, len - 1)) break;
+        } else if (plen == len){
+            if(!strncmp(pc->prefix, path, len)) break;
+        }
+    }
+    *uid = pc->uid;
+    *gid = pc->gid;
+    *mode = (*mode & (~07777)) | pc->mode;
+    *capabilities = pc->capabilities;
+}
diff --git a/libcutils/iosched_policy.c b/libcutils/iosched_policy.c
index a6da9ca..8946d3c 100644
--- a/libcutils/iosched_policy.c
+++ b/libcutils/iosched_policy.c
@@ -1,5 +1,5 @@
 /*
-** Copyright 2007-2014, The Android Open Source Project
+** Copyright 2007, 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. 
diff --git a/libcutils/str_parms.c b/libcutils/str_parms.c
index dfe8c4b..924289a 100644
--- a/libcutils/str_parms.c
+++ b/libcutils/str_parms.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011-2013 The Android Open Source Project
+ * 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.
@@ -357,51 +357,3 @@
 {
     hashmapForEach(str_parms->map, dump_entry, str_parms);
 }
-
-#ifdef TEST_STR_PARMS
-static void test_str_parms_str(const char *str)
-{
-    struct str_parms *str_parms;
-    char *out_str;
-
-    str_parms = str_parms_create_str(str);
-    str_parms_add_str(str_parms, "dude", "woah");
-    str_parms_add_str(str_parms, "dude", "woah");
-    str_parms_del(str_parms, "dude");
-    str_parms_dump(str_parms);
-    out_str = str_parms_to_str(str_parms);
-    str_parms_destroy(str_parms);
-    ALOGI("%s: '%s' stringified is '%s'", __func__, str, out_str);
-    free(out_str);
-}
-
-int main(void)
-{
-    test_str_parms_str("");
-    test_str_parms_str(";");
-    test_str_parms_str("=");
-    test_str_parms_str("=;");
-    test_str_parms_str("=bar");
-    test_str_parms_str("=bar;");
-    test_str_parms_str("foo=");
-    test_str_parms_str("foo=;");
-    test_str_parms_str("foo=bar");
-    test_str_parms_str("foo=bar;");
-    test_str_parms_str("foo=bar;baz");
-    test_str_parms_str("foo=bar;baz=");
-    test_str_parms_str("foo=bar;baz=bat");
-    test_str_parms_str("foo=bar;baz=bat;");
-    test_str_parms_str("foo=bar;baz=bat;foo=bar");
-
-    // hashmapPut reports errors by setting errno to ENOMEM.
-    // Test that we're not confused by running in an environment where this is already true.
-    errno = ENOMEM;
-    test_str_parms_str("foo=bar;baz=");
-    if (errno != ENOMEM) {
-        abort();
-    }
-    test_str_parms_str("foo=bar;baz=");
-
-    return 0;
-}
-#endif
diff --git a/libcutils/memory.c b/libcutils/strlcpy.c
similarity index 62%
rename from libcutils/memory.c
rename to libcutils/strlcpy.c
index 6486b45..c66246c 100644
--- a/libcutils/memory.c
+++ b/libcutils/strlcpy.c
@@ -1,43 +1,4 @@
 /*
- * Copyright (C) 2007 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/memory.h>
-
-#if !HAVE_MEMSET16
-void android_memset16(uint16_t* dst, uint16_t value, size_t size)
-{
-    size >>= 1;
-    while (size--) {
-        *dst++ = value;
-    }
-}
-#endif
-
-#if !HAVE_MEMSET32
-void android_memset32(uint32_t* dst, uint32_t value, size_t size)
-{
-    size >>= 2;
-    while (size--) {
-        *dst++ = value;
-    }
-}
-#endif
-
-#if !HAVE_STRLCPY
-/*
  * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -54,8 +15,13 @@
  */
 
 #include <sys/types.h>
+
+#if defined(__GLIBC__) || defined(_WIN32)
+
 #include <string.h>
 
+#include <cutils/memory.h>
+
 /* Implementation of strlcpy() for platforms that don't already have it. */
 
 /*
@@ -88,4 +54,5 @@
 
 	return(s - src - 1);	/* count does not include NUL */
 }
+
 #endif
diff --git a/libcutils/tests/Android.mk b/libcutils/tests/Android.mk
index 5a54698..cf70345 100644
--- a/libcutils/tests/Android.mk
+++ b/libcutils/tests/Android.mk
@@ -15,38 +15,59 @@
 LOCAL_PATH := $(call my-dir)
 
 test_src_files := \
+    test_str_parms.cpp \
+
+test_target_only_src_files := \
     MemsetTest.cpp \
     PropertiesTest.cpp \
 
-include $(CLEAR_VARS)
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
-LOCAL_MODULE := libcutils_test
-LOCAL_SRC_FILES := $(test_src_files)
-LOCAL_SHARED_LIBRARIES := \
-    libcutils \
-    liblog \
-    libutils \
+test_libraries := libcutils liblog
 
+
+#
+# Target.
+#
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := libcutils_test
+LOCAL_SRC_FILES := $(test_src_files) $(test_target_only_src_files)
+LOCAL_SHARED_LIBRARIES := $(test_libraries)
 LOCAL_MULTILIB := both
 LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
 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_MODULE := libcutils_test_static
+LOCAL_FORCE_STATIC_EXECUTABLE := true
+LOCAL_SRC_FILES := $(test_src_files) $(test_target_only_src_files)
+LOCAL_STATIC_LIBRARIES := libc $(test_libraries)
+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)
 
-#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)
+
+#
+# Host.
+#
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := libcutils_test
+LOCAL_SRC_FILES := $(test_src_files)
+LOCAL_SHARED_LIBRARIES := $(test_libraries)
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
+include $(BUILD_HOST_NATIVE_TEST)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := libcutils_test_static
+LOCAL_SRC_FILES := $(test_src_files)
+LOCAL_STATIC_LIBRARIES := $(test_libraries)
+LOCAL_CXX_STL := libc++_static
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
+include $(BUILD_HOST_NATIVE_TEST)
diff --git a/libcutils/tests/test_str_parms.cpp b/libcutils/tests/test_str_parms.cpp
new file mode 100644
index 0000000..d8f639b
--- /dev/null
+++ b/libcutils/tests/test_str_parms.cpp
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <cutils/str_parms.h>
+#include <gtest/gtest.h>
+
+static void test_str_parms_str(const char* str, const char* expected) {
+    str_parms* str_parms = str_parms_create_str(str);
+    str_parms_add_str(str_parms, "dude", "woah");
+    str_parms_add_str(str_parms, "dude", "woah");
+    str_parms_del(str_parms, "dude");
+    str_parms_dump(str_parms);
+    char* out_str = str_parms_to_str(str_parms);
+    str_parms_destroy(str_parms);
+    ASSERT_STREQ(expected, out_str) << str;
+    free(out_str);
+}
+
+TEST(str_parms, smoke) {
+    test_str_parms_str("", "");
+    test_str_parms_str(";", "");
+    test_str_parms_str("=", "");
+    test_str_parms_str("=;", "");
+    test_str_parms_str("=bar", "");
+    test_str_parms_str("=bar;", "");
+    test_str_parms_str("foo=", "foo=");
+    test_str_parms_str("foo=;", "foo=");
+    test_str_parms_str("foo=bar", "foo=bar");
+    test_str_parms_str("foo=bar;", "foo=bar");
+    test_str_parms_str("foo=bar;baz", "foo=bar;baz=");
+    test_str_parms_str("foo=bar;baz=", "foo=bar;baz=");
+    test_str_parms_str("foo=bar;baz=bat", "foo=bar;baz=bat");
+    test_str_parms_str("foo=bar;baz=bat;", "foo=bar;baz=bat");
+    test_str_parms_str("foo=bar1;baz=bat;foo=bar2", "foo=bar2;baz=bat");
+}
+
+TEST(str_parms, put_ENOMEM) {
+    // hashmapPut reports errors by setting errno to ENOMEM.
+    // Test that we're not confused by running in an environment where this is already true.
+    errno = ENOMEM;
+    test_str_parms_str("foo=bar;baz=", "foo=bar;baz=");
+    ASSERT_EQ(ENOMEM, errno);
+    test_str_parms_str("foo=bar;baz=", "foo=bar;baz=");
+}
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/libion/tests/Android.mk b/libion/tests/Android.mk
index abf527a..894f90e 100644
--- a/libion/tests/Android.mk
+++ b/libion/tests/Android.mk
@@ -18,7 +18,6 @@
 
 include $(CLEAR_VARS)
 LOCAL_MODULE := ion-unit-tests
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
 LOCAL_CFLAGS += -g -Wall -Werror -std=gnu++11 -Wno-missing-field-initializers
 LOCAL_SHARED_LIBRARIES += libion
 LOCAL_C_INCLUDES := $(LOCAL_PATH)/../kernel-headers
diff --git a/liblog/logd_write.c b/liblog/logd_write.c
index dfe34d1..c62a246 100644
--- a/liblog/logd_write.c
+++ b/liblog/logd_write.c
@@ -356,43 +356,7 @@
 
 int __android_log_write(int prio, const char *tag, const char *msg)
 {
-    struct iovec vec[3];
-    log_id_t log_id = LOG_ID_MAIN;
-    char tmp_tag[32];
-
-    if (!tag)
-        tag = "";
-
-    /* XXX: This needs to go! */
-    if (!strcmp(tag, "HTC_RIL") ||
-        !strncmp(tag, "RIL", 3) || /* Any log tag with "RIL" as the prefix */
-        !strncmp(tag, "IMS", 3) || /* Any log tag with "IMS" as the prefix */
-        !strcmp(tag, "AT") ||
-        !strcmp(tag, "GSM") ||
-        !strcmp(tag, "STK") ||
-        !strcmp(tag, "CDMA") ||
-        !strcmp(tag, "PHONE") ||
-        !strcmp(tag, "SMS")) {
-            log_id = LOG_ID_RADIO;
-            /* Inform third party apps/ril/radio.. to use Rlog or RLOG */
-            snprintf(tmp_tag, sizeof(tmp_tag), "use-Rlog/RLOG-%s", tag);
-            tag = tmp_tag;
-    }
-
-#if __BIONIC__
-    if (prio == ANDROID_LOG_FATAL) {
-        android_set_abort_message(msg);
-    }
-#endif
-
-    vec[0].iov_base   = (unsigned char *) &prio;
-    vec[0].iov_len    = 1;
-    vec[1].iov_base   = (void *) tag;
-    vec[1].iov_len    = strlen(tag) + 1;
-    vec[2].iov_base   = (void *) msg;
-    vec[2].iov_len    = strlen(msg) + 1;
-
-    return write_to_log(log_id, vec, 3);
+    return __android_log_buf_write(LOG_ID_MAIN, prio, tag, msg);
 }
 
 int __android_log_buf_write(int bufID, int prio, const char *tag, const char *msg)
@@ -420,6 +384,12 @@
             tag = tmp_tag;
     }
 
+#if __BIONIC__
+    if (prio == ANDROID_LOG_FATAL) {
+        android_set_abort_message(msg);
+    }
+#endif
+
     vec[0].iov_base   = (unsigned char *) &prio;
     vec[0].iov_len    = 1;
     vec[1].iov_base   = (void *) tag;
diff --git a/liblog/logd_write_kern.c b/liblog/logd_write_kern.c
index ca63067..8742b34 100644
--- a/liblog/logd_write_kern.c
+++ b/liblog/logd_write_kern.c
@@ -139,41 +139,7 @@
 
 int __android_log_write(int prio, const char *tag, const char *msg)
 {
-    struct iovec vec[3];
-    log_id_t log_id = LOG_ID_MAIN;
-    char tmp_tag[32];
-
-    if (!tag)
-        tag = "";
-
-    /* XXX: This needs to go! */
-    if (!strcmp(tag, "HTC_RIL") ||
-        !strncmp(tag, "RIL", 3) || /* Any log tag with "RIL" as the prefix */
-        !strncmp(tag, "IMS", 3) || /* Any log tag with "IMS" as the prefix */
-        !strcmp(tag, "AT") ||
-        !strcmp(tag, "GSM") ||
-        !strcmp(tag, "STK") ||
-        !strcmp(tag, "CDMA") ||
-        !strcmp(tag, "PHONE") ||
-        !strcmp(tag, "SMS")) {
-            log_id = LOG_ID_RADIO;
-            /* Inform third party apps/ril/radio.. to use Rlog or RLOG */
-            snprintf(tmp_tag, sizeof(tmp_tag), "use-Rlog/RLOG-%s", tag);
-            tag = tmp_tag;
-    }
-
-    if (prio == ANDROID_LOG_FATAL) {
-        android_set_abort_message(msg);
-    }
-
-    vec[0].iov_base   = (unsigned char *) &prio;
-    vec[0].iov_len    = 1;
-    vec[1].iov_base   = (void *) tag;
-    vec[1].iov_len    = strlen(tag) + 1;
-    vec[2].iov_base   = (void *) msg;
-    vec[2].iov_len    = strlen(msg) + 1;
-
-    return write_to_log(log_id, vec, 3);
+    return __android_log_buf_write(LOG_ID_MAIN, prio, tag, msg);
 }
 
 int __android_log_buf_write(int bufID, int prio, const char *tag, const char *msg)
@@ -201,6 +167,10 @@
             tag = tmp_tag;
     }
 
+    if (prio == ANDROID_LOG_FATAL) {
+        android_set_abort_message(msg);
+    }
+
     vec[0].iov_base   = (unsigned char *) &prio;
     vec[0].iov_len    = 1;
     vec[1].iov_base   = (void *) tag;
diff --git a/liblog/tests/Android.mk b/liblog/tests/Android.mk
index 8137a75..d75bbc9 100644
--- a/liblog/tests/Android.mk
+++ b/liblog/tests/Android.mk
@@ -39,7 +39,6 @@
 include $(CLEAR_VARS)
 LOCAL_MODULE := $(test_module_prefix)benchmarks
 LOCAL_MODULE_TAGS := $(test_tags)
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
 LOCAL_CFLAGS += $(benchmark_c_flags)
 LOCAL_SHARED_LIBRARIES += liblog libm
 LOCAL_SRC_FILES := $(benchmark_src_files)
@@ -77,7 +76,6 @@
 include $(CLEAR_VARS)
 LOCAL_MODULE := $(test_module_prefix)unit-tests
 LOCAL_MODULE_TAGS := $(test_tags)
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
 LOCAL_CFLAGS += $(test_c_flags)
 LOCAL_SHARED_LIBRARIES := liblog
 LOCAL_SRC_FILES := $(test_src_files)
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/libsync/tests/Android.mk b/libsync/tests/Android.mk
index 9c9562a..8137c7a 100644
--- a/libsync/tests/Android.mk
+++ b/libsync/tests/Android.mk
@@ -19,7 +19,6 @@
 include $(CLEAR_VARS)
 LOCAL_CLANG := true
 LOCAL_MODULE := sync-unit-tests
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
 LOCAL_CFLAGS += -g -Wall -Werror -std=gnu++11 -Wno-missing-field-initializers -Wno-sign-compare
 LOCAL_SHARED_LIBRARIES += libsync
 LOCAL_STATIC_LIBRARIES += libgtest_main
diff --git a/libutils/tests/Android.mk b/libutils/tests/Android.mk
index 634f44f..7cfad89 100644
--- a/libutils/tests/Android.mk
+++ b/libutils/tests/Android.mk
@@ -18,7 +18,6 @@
 LOCAL_PATH := $(call my-dir)
 
 include $(CLEAR_VARS)
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
 
 LOCAL_MODULE := libutils_tests
 
diff --git a/libziparchive/Android.mk b/libziparchive/Android.mk
index 3937449..0d31001 100644
--- a/libziparchive/Android.mk
+++ b/libziparchive/Android.mk
@@ -18,7 +18,6 @@
 source_files := zip_archive.cc
 
 include $(CLEAR_VARS)
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
 LOCAL_CPP_EXTENSION := .cc
 LOCAL_SRC_FILES := ${source_files}
 LOCAL_STATIC_LIBRARIES := libz
@@ -29,7 +28,6 @@
 include $(BUILD_STATIC_LIBRARY)
 
 include $(CLEAR_VARS)
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
 LOCAL_CPP_EXTENSION := .cc
 LOCAL_SRC_FILES := ${source_files}
 LOCAL_STATIC_LIBRARIES := libz libutils
@@ -42,7 +40,6 @@
 include $(BUILD_HOST_STATIC_LIBRARY)
 
 include $(CLEAR_VARS)
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
 LOCAL_CPP_EXTENSION := .cc
 LOCAL_SRC_FILES := ${source_files}
 LOCAL_STATIC_LIBRARIES := libz libutils
@@ -54,7 +51,6 @@
 
 # Tests.
 include $(CLEAR_VARS)
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
 LOCAL_MODULE := ziparchive-tests
 LOCAL_CPP_EXTENSION := .cc
 LOCAL_CFLAGS := -Werror
@@ -64,7 +60,6 @@
 include $(BUILD_NATIVE_TEST)
 
 include $(CLEAR_VARS)
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
 LOCAL_MODULE := ziparchive-tests-host
 LOCAL_CPP_EXTENSION := .cc
 LOCAL_CFLAGS += \
diff --git a/logcat/tests/Android.mk b/logcat/tests/Android.mk
index 015a23d..a28664e 100644
--- a/logcat/tests/Android.mk
+++ b/logcat/tests/Android.mk
@@ -39,7 +39,6 @@
 include $(CLEAR_VARS)
 LOCAL_MODULE := $(test_module_prefix)benchmarks
 LOCAL_MODULE_TAGS := $(test_tags)
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
 LOCAL_CFLAGS += $(test_c_flags)
 LOCAL_SRC_FILES := $(benchmark_src_files)
 include $(BUILD_NATIVE_TEST)
@@ -56,7 +55,6 @@
 include $(CLEAR_VARS)
 LOCAL_MODULE := $(test_module_prefix)unit-tests
 LOCAL_MODULE_TAGS := $(test_tags)
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
 LOCAL_CFLAGS += $(test_c_flags)
 LOCAL_SHARED_LIBRARIES := liblog
 LOCAL_SRC_FILES := $(test_src_files)
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/logd/tests/Android.mk b/logd/tests/Android.mk
index f851288..85ca4ac 100644
--- a/logd/tests/Android.mk
+++ b/logd/tests/Android.mk
@@ -46,7 +46,6 @@
 include $(CLEAR_VARS)
 LOCAL_MODULE := $(test_module_prefix)unit-tests
 LOCAL_MODULE_TAGS := $(test_tags)
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
 LOCAL_CFLAGS += $(test_c_flags)
 LOCAL_SHARED_LIBRARIES := libcutils
 LOCAL_SRC_FILES := $(test_src_files)
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 3ae0954..cda79ce 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -225,6 +225,8 @@
     mkdir /cache/lost+found 0770 root root
 
 on post-fs-data
+    installkey /data
+
     # We chown/chmod /data again so because mount is run as root + defaults
     chown system system /data
     chmod 0771 /data
@@ -303,6 +305,14 @@
     # Separate location for storing security policy files on data
     mkdir /data/security 0711 system system
 
+    # Create all remaining /data root dirs so that they are made through init
+    # and get proper encryption policy installed
+    mkdir /data/backup 0700 system system
+    mkdir /data/media 0770 media_rw media_rw
+    mkdir /data/ss 0700 system system
+    mkdir /data/system 0775 system system
+    mkdir /data/user 0711 system system
+
     # Reload policy from /data/security if present.
     setprop selinux.reload_policy 1
 
@@ -438,6 +448,7 @@
     class_start main
 
 on property:vold.decrypt=trigger_restart_framework
+    installkey /data
     class_start main
     class_start late_start
 
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 4d50bf0..041c37a 100644
--- a/sdcard/sdcard.c
+++ b/sdcard/sdcard.c
@@ -199,6 +199,8 @@
      * position. Used to support things like OBB. */
     char* graft_path;
     size_t graft_pathlen;
+
+    bool deleted;
 };
 
 static int str_hash(void *key) {
@@ -631,6 +633,8 @@
     node->ino = fuse->inode_ctr++;
     node->gen = fuse->next_generation++;
 
+    node->deleted = false;
+
     derive_permissions_locked(fuse, parent, node);
     acquire_node_locked(node);
     add_node_to_parent_locked(node, parent);
@@ -704,7 +708,7 @@
          * must be considered distinct even if they refer to the same
          * underlying file as otherwise operations such as "mv x x"
          * will not work because the source and target nodes are the same. */
-        if (!strcmp(name, node->name)) {
+        if (!strcmp(name, node->name) && !node->deleted) {
             return node;
         }
     }
@@ -1070,6 +1074,7 @@
 {
     bool has_rw;
     struct node* parent_node;
+    struct node* child_node;
     char parent_path[PATH_MAX];
     char child_path[PATH_MAX];
 
@@ -1091,6 +1096,12 @@
     if (unlink(child_path) < 0) {
         return -errno;
     }
+    pthread_mutex_lock(&fuse->lock);
+    child_node = lookup_child_by_name_locked(parent_node, name);
+    if (child_node) {
+        child_node->deleted = true;
+    }
+    pthread_mutex_unlock(&fuse->lock);
     return 0;
 }
 
@@ -1098,6 +1109,7 @@
         const struct fuse_in_header* hdr, const char* name)
 {
     bool has_rw;
+    struct node* child_node;
     struct node* parent_node;
     char parent_path[PATH_MAX];
     char child_path[PATH_MAX];
@@ -1120,6 +1132,12 @@
     if (rmdir(child_path) < 0) {
         return -errno;
     }
+    pthread_mutex_lock(&fuse->lock);
+    child_node = lookup_child_by_name_locked(parent_node, name);
+    if (child_node) {
+        child_node->deleted = true;
+    }
+    pthread_mutex_unlock(&fuse->lock);
     return 0;
 }
 
@@ -1869,7 +1887,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;
diff --git a/toolbox/Android.mk b/toolbox/Android.mk
index 4e54eb8..186a89f 100644
--- a/toolbox/Android.mk
+++ b/toolbox/Android.mk
@@ -23,14 +23,12 @@
     upstream-netbsd/lib/libutil/raise_default_signal.c
 LOCAL_CFLAGS += $(common_cflags) -Dmain=dd_main -DNO_CONV
 LOCAL_MODULE := libtoolbox_dd
-LOCAL_ADDITIONAL_DEPENDENCIES += $(LOCAL_PATH)/Android.mk
 include $(BUILD_STATIC_LIBRARY)
 
 include $(CLEAR_VARS)
 LOCAL_SRC_FILES := upstream-netbsd/usr.bin/du/du.c
 LOCAL_CFLAGS += $(common_cflags) -Dmain=du_main
 LOCAL_MODULE := libtoolbox_du
-LOCAL_ADDITIONAL_DEPENDENCIES += $(LOCAL_PATH)/Android.mk
 include $(BUILD_STATIC_LIBRARY)
 
 
@@ -62,7 +60,6 @@
     start \
     stop \
     top \
-    umount \
     uptime \
     watchprops \
 
@@ -82,7 +79,6 @@
 LOCAL_WHOLE_STATIC_LIBRARIES := $(patsubst %,libtoolbox_%,$(BSD_TOOLS))
 
 LOCAL_MODULE := toolbox
-LOCAL_ADDITIONAL_DEPENDENCIES += $(LOCAL_PATH)/Android.mk
 
 # Install the symlinks.
 LOCAL_POST_INSTALL_CMD := $(hide) $(foreach t,$(ALL_TOOLS),ln -sf toolbox $(TARGET_OUT)/bin/$(t);)
@@ -115,7 +111,6 @@
 LOCAL_CFLAGS += $(common_cflags)
 LOCAL_MODULE := r
 LOCAL_MODULE_TAGS := debug
-LOCAL_ADDITIONAL_DEPENDENCIES += $(LOCAL_PATH)/Android.mk
 include $(BUILD_EXECUTABLE)
 
 
diff --git a/toolbox/ioctl.c b/toolbox/ioctl.c
index d1cc14a..093e467 100644
--- a/toolbox/ioctl.c
+++ b/toolbox/ioctl.c
@@ -1,36 +1,81 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
+/*
+ * 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.
+ *  * Neither the name of Google, Inc. nor the names of its contributors
+ *    may be used to endorse or promote products derived from this
+ *    software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" 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 <errno.h>
+#include <error.h>
 #include <fcntl.h>
 #include <getopt.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
 #include <string.h>
-#include <linux/kd.h>
-#include <linux/vt.h>
-#include <errno.h>
-#include <pthread.h>
 #include <sys/ioctl.h>
 #include <unistd.h>
 
-int ioctl_main(int argc, char *argv[])
-{
-    int c;
-    int fd;
-    int res;
+static void usage() {
+    fprintf(stderr, "%s [-l <length>] [-a <argsize>] [-rdh] <device> <ioctlnr>\n"
+            "  -l <length>   Length of io buffer\n"
+            "  -a <argsize>  Size of each argument (1-8)\n"
+            "  -r            Open device in read only mode\n"
+            "  -d            Direct argument (no iobuffer)\n"
+            "  -h            Print help\n", getprogname());
+    exit(1);
+}
 
+static int xstrtoi(const char* s, const char* what) {
+    char* endp;
+    errno = 0;
+    long result = strtol(s, &endp, 0);
+    if (errno != 0 || *endp != '\0') {
+        error(1, errno, "couldn't parse %s '%s'", what, s);
+    }
+    if (result > INT_MAX || result < INT_MIN) {
+        error(1, errno, "%s '%s' out of range", what, s);
+    }
+    return result;
+}
+
+int ioctl_main(int argc, char* argv[]) {
     int read_only = 0;
     int length = -1;
     int arg_size = 4;
     int direct_arg = 0;
-    uint32_t ioctl_nr;
+
     void *ioctl_args = NULL;
     uint8_t *ioctl_argp;
     uint8_t *ioctl_argp_save = NULL;
     int rem;
 
-    do {
-        c = getopt(argc, argv, "rdl:a:h");
-        if (c == EOF)
-            break;
+    int c;
+    while ((c = getopt(argc, argv, "rdl:a:h")) != -1) {
         switch (c) {
         case 'r':
             read_only = 1;
@@ -39,43 +84,44 @@
             direct_arg = 1;
             break;
         case 'l':
-            length = strtol(optarg, NULL, 0);
+            length = xstrtoi(optarg, "length");
             break;
         case 'a':
-            arg_size = strtol(optarg, NULL, 0);
+            arg_size = xstrtoi(optarg, "argument size");
             break;
         case 'h':
-            fprintf(stderr, "%s [-l <length>] [-a <argsize>] [-rdh] <device> <ioctlnr>\n"
-                    "  -l <length>   Length of io buffer\n"
-                    "  -a <argsize>  Size of each argument (1-8)\n"
-                    "  -r            Open device in read only mode\n"
-                    "  -d            Direct argument (no iobuffer)\n"
-                    "  -h            Print help\n", argv[0]);
-            return -1;
-        case '?':
-            fprintf(stderr, "%s: invalid option -%c\n",
-                argv[0], optopt);
-            exit(1);
+            usage();
+            break;
+        default:
+            error(1, 0, "invalid option -%c", optopt);
         }
-    } while (1);
-
-    if(optind + 2 > argc) {
-        fprintf(stderr, "%s: too few arguments\n", argv[0]);
-        exit(1);
     }
 
-    if (!strcmp(argv[optind], "-")) {
+    if (optind + 2 > argc) {
+        usage();
+    }
+
+    const char* device = argv[optind];
+    int fd;
+    if (strcmp(device, "-") == 0) {
         fd = STDIN_FILENO;
     } else {
-        fd = open(argv[optind], read_only ? O_RDONLY : (O_RDWR | O_SYNC));
-        if (fd < 0) {
-            fprintf(stderr, "cannot open %s\n", argv[optind]);
-            return 1;
+        fd = open(device, read_only ? O_RDONLY : (O_RDWR | O_SYNC));
+        if (fd == -1) {
+            error(1, errno, "cannot open %s", argv[optind]);
         }
     }
     optind++;
-    
-    ioctl_nr = strtol(argv[optind], NULL, 0);
+
+    // IOCTL(2) wants second parameter as a signed int.
+    // Let's let the user specify either negative numbers or large positive
+    // numbers, for the case where ioctl number is larger than INT_MAX.
+    errno = 0;
+    char* endp;
+    int ioctl_nr = UINT_MAX & strtoll(argv[optind], &endp, 0);
+    if (errno != 0 || *endp != '\0') {
+        error(1, errno, "couldn't parse ioctl number '%s'", argv[optind]);
+    }
     optind++;
 
     if(direct_arg) {
@@ -91,11 +137,10 @@
 
         ioctl_argp_save = ioctl_argp = ioctl_args;
         rem = length;
-        while(optind < argc) {
+        while (optind < argc) {
             uint64_t tmp = strtoull(argv[optind], NULL, 0);
-            if(rem < arg_size) {
-                fprintf(stderr, "%s: too many arguments\n", argv[0]);
-                exit(1);
+            if (rem < arg_size) {
+                error(1, 0, "too many arguments");
             }
             memcpy(ioctl_argp, &tmp, arg_size);
             ioctl_argp += arg_size;
@@ -108,8 +153,9 @@
     while(rem--) {
         printf(" 0x%02x", *ioctl_argp_save++);
     }
-    printf("\n");
+    printf(" to %s\n", device);
 
+    int res;
     if(direct_arg)
         res = ioctl(fd, ioctl_nr, *(uint32_t*)ioctl_args);
     else if(length)
@@ -118,10 +164,10 @@
         res = ioctl(fd, ioctl_nr, 0);
     if (res < 0) {
         free(ioctl_args);
-        fprintf(stderr, "ioctl 0x%x failed, %d\n", ioctl_nr, res);
-        return 1;
+        error(1, errno, "ioctl 0x%x failed (returned %d)", ioctl_nr, res);
     }
-    if(length) {
+
+    if (length) {
         printf("return buf:");
         ioctl_argp = ioctl_args;
         rem = length;
@@ -131,5 +177,6 @@
         printf("\n");
     }
     free(ioctl_args);
+    close(fd);
     return 0;
 }
diff --git a/toolbox/umount.c b/toolbox/umount.c
deleted file mode 100644
index 3e17396..0000000
--- a/toolbox/umount.c
+++ /dev/null
@@ -1,90 +0,0 @@
-
-#include <sys/mount.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-#include <linux/loop.h>
-#include <errno.h>
-
-#define LOOPDEV_MAXLEN 64
-#define LOOP_MAJOR 7
-
-static int is_loop(char *dev)
-{
-    struct stat st;
-    int ret = 0;
-
-    if (stat(dev, &st) == 0) {
-        if (S_ISBLK(st.st_mode) && (major(st.st_rdev) == LOOP_MAJOR)) {
-            ret = 1;
-        }
-    }
-
-    return ret;
-}
-
-static int is_loop_mount(const char* path, char *loopdev)
-{
-    FILE* f;
-    int count;
-    char device[256];
-    char mount_path[256];
-    char rest[256];
-    int result = 0;
-    
-    f = fopen("/proc/mounts", "r");
-    if (!f) {
-        fprintf(stdout, "could not open /proc/mounts: %s\n", strerror(errno));
-        return -1;
-    }
-
-    do {
-        count = fscanf(f, "%255s %255s %255s\n", device, mount_path, rest);
-        if (count == 3) {
-            if (is_loop(device) && strcmp(path, mount_path) == 0) {
-                strlcpy(loopdev, device, LOOPDEV_MAXLEN);
-                result = 1;
-                break;
-            }
-        }
-    } while (count == 3);
-
-    fclose(f);
-    return result;
-}
-
-int umount_main(int argc, char *argv[])
-{
-    int loop, loop_fd;
-    char loopdev[LOOPDEV_MAXLEN];
-
-    if(argc != 2) {
-        fprintf(stderr,"umount <path>\n");
-        return 1;
-    }
-
-    loop = is_loop_mount(argv[1], loopdev);
-    if (umount(argv[1])) {
-        fprintf(stderr, "failed: %s\n", strerror(errno));
-        return 1;
-    }
-
-    if (loop) {
-        // free the loop device
-        loop_fd = open(loopdev, O_RDONLY);
-        if (loop_fd < 0) {
-            fprintf(stderr, "open loop device failed: %s\n", strerror(errno));
-            return 1;
-        }
-        if (ioctl(loop_fd, LOOP_CLR_FD, 0) < 0) {
-            fprintf(stderr, "ioctl LOOP_CLR_FD failed: %s\n", strerror(errno));
-            return 1;
-        }
-
-        close(loop_fd);
-    }
-
-    return 0;
-}