Merge "Add ld.config.txt to /system/etc"
diff --git a/adb/adb_utils.cpp b/adb/adb_utils.cpp
index 7058acb..31d3dc6 100644
--- a/adb/adb_utils.cpp
+++ b/adb/adb_utils.cpp
@@ -75,7 +75,7 @@
 
 bool directory_exists(const std::string& path) {
   struct stat sb;
-  return lstat(path.c_str(), &sb) != -1 && S_ISDIR(sb.st_mode);
+  return stat(path.c_str(), &sb) != -1 && S_ISDIR(sb.st_mode);
 }
 
 std::string escape_arg(const std::string& s) {
diff --git a/adb/adb_utils_test.cpp b/adb/adb_utils_test.cpp
index a3bc445..e1b6287 100644
--- a/adb/adb_utils_test.cpp
+++ b/adb/adb_utils_test.cpp
@@ -55,7 +55,6 @@
   ASSERT_FALSE(directory_exists(subdir(profiles_dir, "does-not-exist")));
 #else
   ASSERT_TRUE(directory_exists("/proc"));
-  ASSERT_FALSE(directory_exists("/proc/self")); // Symbolic link.
   ASSERT_FALSE(directory_exists("/proc/does-not-exist"));
 #endif
 }
diff --git a/adb/bugreport.cpp b/adb/bugreport.cpp
index a5c312b..9dc9811 100644
--- a/adb/bugreport.cpp
+++ b/adb/bugreport.cpp
@@ -47,7 +47,8 @@
           invalid_lines_(),
           show_progress_(show_progress),
           status_(0),
-          line_() {
+          line_(),
+          last_progress_(0) {
         SetLineMessage("generating");
     }
 
@@ -66,6 +67,7 @@
     void OnStderr(const char* buffer, int length) {
         OnStream(nullptr, stderr, buffer, length);
     }
+
     int Done(int unused_) {
         // Process remaining line, if any.
         ProcessLine(line_);
@@ -145,6 +147,11 @@
             size_t idx1 = line.rfind(BUGZ_PROGRESS_PREFIX) + strlen(BUGZ_PROGRESS_PREFIX);
             size_t idx2 = line.rfind(BUGZ_PROGRESS_SEPARATOR);
             int progress = std::stoi(line.substr(idx1, (idx2 - idx1)));
+            if (progress <= last_progress_) {
+                // Ignore.
+                return;
+            }
+            last_progress_ = progress;
             int total = std::stoi(line.substr(idx2 + 1));
             br_->UpdateProgress(line_message_, progress, total);
         } else {
@@ -180,6 +187,10 @@
     // Temporary buffer containing the characters read since the last newline (\n).
     std::string line_;
 
+    // Last displayed progress.
+    // Since dumpstate progress can recede, only forward progress should be displayed
+    int last_progress_;
+
     DISALLOW_COPY_AND_ASSIGN(BugreportStandardStreamsCallback);
 };
 
diff --git a/adb/bugreport_test.cpp b/adb/bugreport_test.cpp
index 1129285..b500c49 100644
--- a/adb/bugreport_test.cpp
+++ b/adb/bugreport_test.cpp
@@ -50,9 +50,7 @@
 
 // Empty functions so tests don't need to be linked against commandline.cpp
 DefaultStandardStreamsCallback DEFAULT_STANDARD_STREAMS_CALLBACK(nullptr, nullptr);
-int usage() {
-    return -42;
-}
+
 int send_shell_command(TransportType transport_type, const char* serial, const std::string& command,
                        bool disable_shell_protocol, StandardStreamsCallbackInterface* callback) {
     ADD_FAILURE() << "send_shell_command() should have been mocked";
@@ -155,7 +153,7 @@
 // Tests when called with invalid number of arguments
 TEST_F(BugreportTest, InvalidNumberArgs) {
     const char* args[] = {"bugreport", "to", "principal"};
-    ASSERT_EQ(-42, br_.DoIt(kTransportLocal, "HannibalLecter", 3, args));
+    ASSERT_EQ(1, br_.DoIt(kTransportLocal, "HannibalLecter", 3, args));
 }
 
 // Tests the 'adb bugreport' option when the device does not support 'bugreportz' - it falls back
@@ -282,6 +280,35 @@
     ASSERT_EQ(0, br_.DoIt(kTransportLocal, "HannibalLecter", 2, args));
 }
 
+// Tests 'adb bugreport file.zip' when it succeeds and displays progress, even if progress recedes.
+TEST_F(BugreportTest, OkProgressAlwaysForward) {
+    ExpectBugreportzVersion("1.1");
+    ExpectProgress(1, 100);
+    ExpectProgress(50, 100);
+    ExpectProgress(75, 100);
+    // clang-format off
+    EXPECT_CALL(br_, SendShellCommand(kTransportLocal, "HannibalLecter", "bugreportz -p", false, _))
+        // NOTE: DoAll accepts at most 10 arguments, and we're almost reached that limit...
+        .WillOnce(DoAll(
+            WithArg<4>(WriteOnStdout("BEGIN:/device/bugreport.zip\n")),
+            WithArg<4>(WriteOnStdout("PROGRESS:1/100\n")),
+            WithArg<4>(WriteOnStdout("PROGRESS:50/100\n")),
+            // 25 should be ignored becaused it receded.
+            WithArg<4>(WriteOnStdout("PROGRESS:25/100\n")),
+            WithArg<4>(WriteOnStdout("PROGRESS:75/100\n")),
+            // 75 should be ignored becaused it didn't change.
+            WithArg<4>(WriteOnStdout("PROGRESS:75/100\n")),
+            WithArg<4>(WriteOnStdout("OK:/device/bugreport.zip")),
+            WithArg<4>(ReturnCallbackDone())));
+    // clang-format on
+    EXPECT_CALL(br_, DoSyncPull(ElementsAre(StrEq("/device/bugreport.zip")), StrEq("file.zip"),
+                                true, StrEq("pulling file.zip")))
+        .WillOnce(Return(true));
+
+    const char* args[] = {"bugreport", "file.zip"};
+    ASSERT_EQ(0, br_.DoIt(kTransportLocal, "HannibalLecter", 2, args));
+}
+
 // Tests 'adb bugreport dir' when it succeeds and destination is a directory.
 TEST_F(BugreportTest, OkDirectory) {
     ExpectBugreportzVersion("1.1");
diff --git a/adb/commandline.cpp b/adb/commandline.cpp
index 3de7be6..4979eef 100644
--- a/adb/commandline.cpp
+++ b/adb/commandline.cpp
@@ -782,9 +782,16 @@
     return RemoteShell(use_shell_protocol, shell_type_arg, escape_char, command);
 }
 
-static int adb_download_buffer(const char *service, const char *fn, const void* data, unsigned sz,
-                               bool show_progress)
-{
+static int adb_download_buffer(const char* service, const char* filename) {
+    std::string content;
+    if (!android::base::ReadFileToString(filename, &content)) {
+        fprintf(stderr, "error: couldn't read %s: %s\n", filename, strerror(errno));
+        return -1;
+    }
+
+    const uint8_t* data = reinterpret_cast<const uint8_t*>(content.data());
+    unsigned sz = content.size();
+
     std::string error;
     int fd = adb_connect(android::base::StringPrintf("%s:%d", service, sz), &error);
     if (fd < 0) {
@@ -798,10 +805,8 @@
     unsigned total = sz;
     const uint8_t* ptr = reinterpret_cast<const uint8_t*>(data);
 
-    if (show_progress) {
-        const char* x = strrchr(service, ':');
-        if (x) service = x + 1;
-    }
+    const char* x = strrchr(service, ':');
+    if (x) service = x + 1;
 
     while (sz > 0) {
         unsigned xfer = (sz > CHUNK_SIZE) ? CHUNK_SIZE : sz;
@@ -814,14 +819,10 @@
         }
         sz -= xfer;
         ptr += xfer;
-        if (show_progress) {
-            printf("sending: '%s' %4d%%    \r", fn, (int)(100LL - ((100LL * sz) / (total))));
-            fflush(stdout);
-        }
+        printf("sending: '%s' %4d%%    \r", filename, (int)(100LL - ((100LL * sz) / (total))));
+        fflush(stdout);
     }
-    if (show_progress) {
-        printf("\n");
-    }
+    printf("\n");
 
     if (!adb_status(fd, &error)) {
         fprintf(stderr,"* error response '%s' *\n", error.c_str());
@@ -854,38 +855,40 @@
  * - When the other side sends "DONEDONE" instead of a block number,
  *   we hang up.
  */
-static int adb_sideload_host(const char* fn) {
-    fprintf(stderr, "loading: '%s'...\n", fn);
-
-    std::string content;
-    if (!android::base::ReadFileToString(fn, &content)) {
-        fprintf(stderr, "failed: %s\n", strerror(errno));
+static int adb_sideload_host(const char* filename) {
+    fprintf(stderr, "opening '%s'...\n", filename);
+    struct stat sb;
+    if (stat(filename, &sb) == -1) {
+        fprintf(stderr, "failed to stat file %s: %s\n", filename, strerror(errno));
+        return -1;
+    }
+    unique_fd package_fd(adb_open(filename, O_RDONLY));
+    if (package_fd == -1) {
+        fprintf(stderr, "failed to open file %s: %s\n", filename, strerror(errno));
         return -1;
     }
 
-    const uint8_t* data = reinterpret_cast<const uint8_t*>(content.data());
-    unsigned sz = content.size();
-
     fprintf(stderr, "connecting...\n");
-    std::string service =
-            android::base::StringPrintf("sideload-host:%d:%d", sz, SIDELOAD_HOST_BLOCK_SIZE);
+    std::string service = android::base::StringPrintf(
+        "sideload-host:%d:%d", static_cast<int>(sb.st_size), SIDELOAD_HOST_BLOCK_SIZE);
     std::string error;
-    unique_fd fd(adb_connect(service, &error));
-    if (fd < 0) {
-        // Try falling back to the older sideload method.  Maybe this
+    unique_fd device_fd(adb_connect(service, &error));
+    if (device_fd < 0) {
+        // Try falling back to the older (<= K) sideload method. Maybe this
         // is an older device that doesn't support sideload-host.
         fprintf(stderr, "falling back to older sideload method...\n");
-        return adb_download_buffer("sideload", fn, data, sz, true);
+        return adb_download_buffer("sideload", filename);
     }
 
     int opt = SIDELOAD_HOST_BLOCK_SIZE;
-    adb_setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &opt, sizeof(opt));
+    adb_setsockopt(device_fd, SOL_SOCKET, SO_SNDBUF, &opt, sizeof(opt));
+
+    char buf[SIDELOAD_HOST_BLOCK_SIZE];
 
     size_t xfer = 0;
     int last_percent = -1;
     while (true) {
-        char buf[9];
-        if (!ReadFdExactly(fd, buf, 8)) {
+        if (!ReadFdExactly(device_fd, buf, 8)) {
             fprintf(stderr, "* failed to read command: %s\n", strerror(errno));
             return -1;
         }
@@ -893,26 +896,35 @@
 
         if (strcmp("DONEDONE", buf) == 0) {
             printf("\rTotal xfer: %.2fx%*s\n",
-                   (double)xfer / (sz ? sz : 1), (int)strlen(fn)+10, "");
+                   static_cast<double>(xfer) / (sb.st_size ? sb.st_size : 1),
+                   static_cast<int>(strlen(filename) + 10), "");
             return 0;
         }
 
         int block = strtol(buf, NULL, 10);
 
         size_t offset = block * SIDELOAD_HOST_BLOCK_SIZE;
-        if (offset >= sz) {
+        if (offset >= static_cast<size_t>(sb.st_size)) {
             fprintf(stderr, "* attempt to read block %d past end\n", block);
             return -1;
         }
-        const uint8_t* start = data + offset;
-        size_t offset_end = offset + SIDELOAD_HOST_BLOCK_SIZE;
+
         size_t to_write = SIDELOAD_HOST_BLOCK_SIZE;
-        if (offset_end > sz) {
-            to_write = sz - offset;
+        if ((offset + SIDELOAD_HOST_BLOCK_SIZE) > static_cast<size_t>(sb.st_size)) {
+            to_write = sb.st_size - offset;
         }
 
-        if (!WriteFdExactly(fd, start, to_write)) {
-            adb_status(fd, &error);
+        if (adb_lseek(package_fd, offset, SEEK_SET) != static_cast<int>(offset)) {
+            fprintf(stderr, "* failed to seek to package block: %s\n", strerror(errno));
+            return -1;
+        }
+        if (!ReadFdExactly(package_fd, buf, to_write)) {
+            fprintf(stderr, "* failed to read package block: %s\n", strerror(errno));
+            return -1;
+        }
+
+        if (!WriteFdExactly(device_fd, buf, to_write)) {
+            adb_status(device_fd, &error);
             fprintf(stderr,"* failed to write data '%s' *\n", error.c_str());
             return -1;
         }
@@ -924,9 +936,9 @@
         // extra access to things like the zip central directory).
         // This estimate of the completion becomes 100% when we've
         // transferred ~2.13 (=100/47) times the package size.
-        int percent = (int)(xfer * 47LL / (sz ? sz : 1));
+        int percent = static_cast<int>(xfer * 47LL / (sb.st_size ? sb.st_size : 1));
         if (percent != last_percent) {
-            printf("\rserving: '%s'  (~%d%%)    ", fn, percent);
+            printf("\rserving: '%s'  (~%d%%)    ", filename, percent);
             fflush(stdout);
             last_percent = percent;
         }
diff --git a/adb/jdwp_service.cpp b/adb/jdwp_service.cpp
index 9589d88..f0dff06 100644
--- a/adb/jdwp_service.cpp
+++ b/adb/jdwp_service.cpp
@@ -179,8 +179,6 @@
     fdevent* fde = nullptr;
 
     std::vector<unique_fd> out_fds;
-    char in_buf[PID_LEN + 1];
-    ssize_t in_len = 0;
 };
 
 static size_t jdwp_process_list(char* buffer, size_t bufferlen) {
@@ -224,33 +222,16 @@
     if (events & FDE_READ) {
         if (proc->pid < 0) {
             /* read the PID as a 4-hexchar string */
-            if (proc->in_len < 0) {
-                fatal("attempting to read JDWP pid again?");
-            }
-
-            char* p = proc->in_buf + proc->in_len;
-            size_t size = PID_LEN - proc->in_len;
-
-            ssize_t rc = TEMP_FAILURE_RETRY(recv(socket, p, size, 0));
-            if (rc < 0) {
-                if (errno == EAGAIN) {
-                    return;
-                }
-
+            char buf[PID_LEN + 1];
+            ssize_t rc = TEMP_FAILURE_RETRY(recv(socket, buf, PID_LEN, 0));
+            if (rc != PID_LEN) {
                 D("failed to read jdwp pid: %s", strerror(errno));
                 goto CloseProcess;
             }
+            buf[PID_LEN] = '\0';
 
-            proc->in_len += rc;
-            if (proc->in_len != PID_LEN) {
-                return;
-            }
-
-            proc->in_buf[PID_LEN] = '\0';
-            proc->in_len = -1;
-
-            if (sscanf(proc->in_buf, "%04x", &proc->pid) != 1) {
-                D("could not decode JDWP %p PID number: '%s'", proc, p);
+            if (sscanf(buf, "%04x", &proc->pid) != 1) {
+                D("could not decode JDWP %p PID number: '%s'", proc, buf);
                 goto CloseProcess;
             }
 
@@ -405,7 +386,7 @@
     addr.sun_family = AF_UNIX;
     memcpy(addr.sun_path, sockname, socknamelen);
 
-    s = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
+    s = socket(AF_UNIX, SOCK_SEQPACKET | SOCK_CLOEXEC, 0);
     if (s < 0) {
         D("could not create vm debug control socket. %d: %s", errno, strerror(errno));
         return -1;
diff --git a/base/file.cpp b/base/file.cpp
index 378a405..d4e5894 100644
--- a/base/file.cpp
+++ b/base/file.cpp
@@ -49,6 +49,14 @@
 bool ReadFdToString(int fd, std::string* content) {
   content->clear();
 
+  // Although original we had small files in mind, this code gets used for
+  // very large files too, where the std::string growth heuristics might not
+  // be suitable. https://code.google.com/p/android/issues/detail?id=258500.
+  struct stat sb;
+  if (fstat(fd, &sb) != -1 && sb.st_size > 0) {
+    content->reserve(sb.st_size);
+  }
+
   char buf[BUFSIZ];
   ssize_t n;
   while ((n = TEMP_FAILURE_RETRY(read(fd, &buf[0], sizeof(buf)))) > 0) {
diff --git a/base/file_test.cpp b/base/file_test.cpp
index 266131e..02b431d 100644
--- a/base/file_test.cpp
+++ b/base/file_test.cpp
@@ -214,3 +214,46 @@
   EXPECT_EQ(".", android::base::Dirname("sh"));
   EXPECT_EQ("/system/bin", android::base::Dirname("/system/bin/sh/"));
 }
+
+TEST(file, ReadFileToString_capacity) {
+  TemporaryFile tf;
+  ASSERT_TRUE(tf.fd != -1);
+
+  // For a huge file, the overhead should still be small.
+  std::string s;
+  size_t size = 16 * 1024 * 1024;
+  ASSERT_TRUE(android::base::WriteStringToFile(std::string(size, 'x'), tf.path));
+  ASSERT_TRUE(android::base::ReadFileToString(tf.path, &s));
+  EXPECT_EQ(size, s.size());
+  EXPECT_LT(s.capacity(), size + 16);
+
+  // Even for weird badly-aligned sizes.
+  size += 12345;
+  ASSERT_TRUE(android::base::WriteStringToFile(std::string(size, 'x'), tf.path));
+  ASSERT_TRUE(android::base::ReadFileToString(tf.path, &s));
+  EXPECT_EQ(size, s.size());
+  EXPECT_LT(s.capacity(), size + 16);
+
+  // We'll shrink an enormous string if you read a small file into it.
+  size = 64;
+  ASSERT_TRUE(android::base::WriteStringToFile(std::string(size, 'x'), tf.path));
+  ASSERT_TRUE(android::base::ReadFileToString(tf.path, &s));
+  EXPECT_EQ(size, s.size());
+  EXPECT_LT(s.capacity(), size + 16);
+}
+
+TEST(file, ReadFileToString_capacity_0) {
+  TemporaryFile tf;
+  ASSERT_TRUE(tf.fd != -1);
+
+  // Because /proc reports its files as zero-length, we don't actually trust
+  // any file that claims to be zero-length. Rather than add increasingly
+  // complex heuristics for shrinking the passed-in string in that case, we
+  // currently leave it alone.
+  std::string s;
+  size_t initial_capacity = s.capacity();
+  ASSERT_TRUE(android::base::WriteStringToFile("", tf.path));
+  ASSERT_TRUE(android::base::ReadFileToString(tf.path, &s));
+  EXPECT_EQ(0U, s.size());
+  EXPECT_EQ(initial_capacity, s.capacity());
+}
diff --git a/cpio/mkbootfs.c b/cpio/mkbootfs.c
index b89c395..e52762e 100644
--- a/cpio/mkbootfs.c
+++ b/cpio/mkbootfs.c
@@ -301,6 +301,7 @@
             allocated *= 2;
             canned_config = (struct fs_config_entry*)realloc(
                 canned_config, allocated * sizeof(struct fs_config_entry));
+            if (canned_config == NULL) die("failed to reallocate memory");
         }
 
         struct fs_config_entry* cc = canned_config + used;
@@ -320,6 +321,7 @@
         ++allocated;
         canned_config = (struct fs_config_entry*)realloc(
             canned_config, allocated * sizeof(struct fs_config_entry));
+        if (canned_config == NULL) die("failed to reallocate memory");
     }
     canned_config[used].name = NULL;
 
diff --git a/debuggerd/handler/debuggerd_handler.cpp b/debuggerd/handler/debuggerd_handler.cpp
index cf24d57..cd00dc5 100644
--- a/debuggerd/handler/debuggerd_handler.cpp
+++ b/debuggerd/handler/debuggerd_handler.cpp
@@ -120,7 +120,7 @@
   }
 
   if (signum == DEBUGGER_SIGNAL) {
-    __libc_format_log(ANDROID_LOG_FATAL, "libc", "Requested dump for tid %d (%s)", gettid(),
+    __libc_format_log(ANDROID_LOG_INFO, "libc", "Requested dump for tid %d (%s)", gettid(),
                       thread_name);
     return;
   }
diff --git a/debuggerd/libdebuggerd/test/tombstone_test.cpp b/debuggerd/libdebuggerd/test/tombstone_test.cpp
index 5ee07cd..325210d 100644
--- a/debuggerd/libdebuggerd/test/tombstone_test.cpp
+++ b/debuggerd/libdebuggerd/test/tombstone_test.cpp
@@ -77,7 +77,9 @@
     resetLogs();
     elf_set_fake_build_id("");
     siginfo_t si;
+    memset(&si, 0, sizeof(si));
     si.si_signo = SIGABRT;
+    si.si_code = SI_KERNEL;
     ptrace_set_fake_getsiginfo(si);
   }
 
@@ -292,7 +294,9 @@
   map_mock_->AddMap(map);
 
   siginfo_t si;
+  memset(&si, 0, sizeof(si));
   si.si_signo = SIGBUS;
+  si.si_code = SI_KERNEL;
   si.si_addr = reinterpret_cast<void*>(0x1000);
   ptrace_set_fake_getsiginfo(si);
   dump_all_maps(backtrace_mock_.get(), map_mock_.get(), &log_, 100);
@@ -348,7 +352,9 @@
   map_mock_->AddMap(map);
 
   siginfo_t si;
+  memset(&si, 0, sizeof(si));
   si.si_signo = SIGBUS;
+  si.si_code = SI_KERNEL;
   si.si_addr = reinterpret_cast<void*>(0xa533000);
   ptrace_set_fake_getsiginfo(si);
   dump_all_maps(backtrace_mock_.get(), map_mock_.get(), &log_, 100);
@@ -404,7 +410,9 @@
   map_mock_->AddMap(map);
 
   siginfo_t si;
+  memset(&si, 0, sizeof(si));
   si.si_signo = SIGBUS;
+  si.si_code = SI_KERNEL;
   si.si_addr = reinterpret_cast<void*>(0xa534040);
   ptrace_set_fake_getsiginfo(si);
   dump_all_maps(backtrace_mock_.get(), map_mock_.get(), &log_, 100);
@@ -458,7 +466,9 @@
   map_mock_->AddMap(map);
 
   siginfo_t si;
+  memset(&si, 0, sizeof(si));
   si.si_signo = SIGBUS;
+  si.si_code = SI_KERNEL;
 #if defined(__LP64__)
   si.si_addr = reinterpret_cast<void*>(0x12345a534040UL);
 #else
@@ -503,7 +513,7 @@
   map_mock_->AddMap(map);
 
   siginfo_t si;
-  si.si_signo = 0;
+  memset(&si, 0, sizeof(si));
   ptrace_set_fake_getsiginfo(si);
   dump_all_maps(backtrace_mock_.get(), map_mock_.get(), &log_, 100);
 
@@ -539,7 +549,9 @@
     ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0);
 
     siginfo_t si;
+    memset(&si, 0, sizeof(si));
     si.si_signo = i;
+    si.si_code = SI_KERNEL;
     si.si_addr = reinterpret_cast<void*>(0x1000);
     ptrace_set_fake_getsiginfo(si);
     dump_all_maps(backtrace_mock_.get(), map_mock_.get(), &log_, 100);
@@ -592,7 +604,7 @@
 
 TEST_F(TombstoneTest, dump_signal_info_error) {
   siginfo_t si;
-  si.si_signo = 0;
+  memset(&si, 0, sizeof(si));
   ptrace_set_fake_getsiginfo(si);
 
   dump_signal_info(&log_, 123);
diff --git a/debuggerd/libdebuggerd/tombstone.cpp b/debuggerd/libdebuggerd/tombstone.cpp
index c23da44..0c38449 100644
--- a/debuggerd/libdebuggerd/tombstone.cpp
+++ b/debuggerd/libdebuggerd/tombstone.cpp
@@ -283,7 +283,7 @@
     if (BacktraceMap::IsValid(map) && !map.name.empty()) {
       line += "  " + map.name;
       uintptr_t offset = 0;
-      std::string func_name(backtrace->GetFunctionName(stack_data[i], &offset));
+      std::string func_name(backtrace->GetFunctionName(stack_data[i], &offset, &map));
       if (!func_name.empty()) {
         line += " (" + func_name;
         if (offset) {
diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp
index 6c84d73..6636be2 100644
--- a/fs_mgr/fs_mgr.cpp
+++ b/fs_mgr/fs_mgr.cpp
@@ -45,8 +45,7 @@
 #include <linux/fs.h>
 #include <linux/loop.h>
 #include <logwrap/logwrap.h>
-#include <private/android_filesystem_config.h>
-#include <private/android_logger.h>
+#include <private/android_logger.h>  // for __android_log_is_debuggable()
 
 #include "fs_mgr_priv.h"
 #include "fs_mgr_priv_avb.h"
diff --git a/fs_mgr/fs_mgr_avb.cpp b/fs_mgr/fs_mgr_avb.cpp
index 2cb7e34..35577e3 100644
--- a/fs_mgr/fs_mgr_avb.cpp
+++ b/fs_mgr/fs_mgr_avb.cpp
@@ -489,7 +489,13 @@
     // fs_mgr only deals with HASHTREE partitions.
     const char *requested_partitions[] = {nullptr};
     std::string ab_suffix;
-    fs_mgr_get_boot_config("slot_suffix", &ab_suffix);
+    std::string slot;
+    if (fs_mgr_get_boot_config("slot", &slot)) {
+        ab_suffix = "_" + slot;
+    } else {
+        // remove slot_suffix once bootloaders update to new androidboot.slot param
+        fs_mgr_get_boot_config("slot_suffix", &ab_suffix);
+    }
     AvbSlotVerifyResult verify_result =
         avb_slot_verify(fs_mgr_avb_ops, requested_partitions, ab_suffix.c_str(),
                         fs_mgr_vbmeta_prop.allow_verification_error, &fs_mgr_avb_verify_data);
diff --git a/fs_mgr/fs_mgr_slotselect.cpp b/fs_mgr/fs_mgr_slotselect.cpp
index f3bba7b..7a45473 100644
--- a/fs_mgr/fs_mgr_slotselect.cpp
+++ b/fs_mgr/fs_mgr_slotselect.cpp
@@ -31,14 +31,16 @@
             char *tmp;
 
             if (!got_suffix) {
-                if (!fs_mgr_get_boot_config("slot_suffix", &suffix)) {
-                  return -1;
+                std::string slot;
+                if (fs_mgr_get_boot_config("slot", &slot)) {
+                    suffix = "_" + slot;
+                } else if (!fs_mgr_get_boot_config("slot_suffix", &suffix)) {
+                    // remove slot_suffix once bootloaders update to new androidboot.slot param
+                    return -1;
                 }
-                got_suffix = 1;
             }
 
-            if (asprintf(&tmp, "%s%s", fstab->recs[n].blk_device,
-                         suffix.c_str()) > 0) {
+            if (asprintf(&tmp, "%s%s", fstab->recs[n].blk_device, suffix.c_str()) > 0) {
                 free(fstab->recs[n].blk_device);
                 fstab->recs[n].blk_device = tmp;
             } else {
diff --git a/fs_mgr/fs_mgr_verity.cpp b/fs_mgr/fs_mgr_verity.cpp
index 54a6f71..8c7a8ca 100644
--- a/fs_mgr/fs_mgr_verity.cpp
+++ b/fs_mgr/fs_mgr_verity.cpp
@@ -39,7 +39,6 @@
 #include <openssl/obj_mac.h>
 #include <openssl/rsa.h>
 #include <openssl/sha.h>
-#include <private/android_filesystem_config.h>
 
 #include "fec/io.h"
 
diff --git a/healthd/BatteryPropertiesRegistrar.cpp b/healthd/BatteryPropertiesRegistrar.cpp
index d28ba41..523e1f1 100644
--- a/healthd/BatteryPropertiesRegistrar.cpp
+++ b/healthd/BatteryPropertiesRegistrar.cpp
@@ -77,6 +77,10 @@
     return healthd_get_property(id, val);
 }
 
+void BatteryPropertiesRegistrar::scheduleUpdate() {
+    healthd_battery_update();
+}
+
 status_t BatteryPropertiesRegistrar::dump(int fd, const Vector<String16>& /*args*/) {
     IPCThreadState* self = IPCThreadState::self();
     const int pid = self->getCallingPid();
diff --git a/healthd/BatteryPropertiesRegistrar.h b/healthd/BatteryPropertiesRegistrar.h
index 095f3d3..14e9145 100644
--- a/healthd/BatteryPropertiesRegistrar.h
+++ b/healthd/BatteryPropertiesRegistrar.h
@@ -32,6 +32,7 @@
 public:
     void publish(const sp<BatteryPropertiesRegistrar>& service);
     void notifyListeners(const struct BatteryProperties& props);
+    void scheduleUpdate();
 
 private:
     Mutex mRegistrationLock;
diff --git a/include/backtrace/Backtrace.h b/include/backtrace/Backtrace.h
index c896ab8..4f73a65 100644
--- a/include/backtrace/Backtrace.h
+++ b/include/backtrace/Backtrace.h
@@ -104,8 +104,10 @@
   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.
-  virtual std::string GetFunctionName(uintptr_t pc, uintptr_t* offset);
+  // If the string is empty, then no valid function name was found,
+  // or the pc is not in any valid map.
+  virtual std::string GetFunctionName(uintptr_t pc, uintptr_t* offset,
+                                      const backtrace_map_t* map = NULL);
 
   // Fill in the map data associated with the given pc.
   virtual void FillInMap(uintptr_t pc, backtrace_map_t* map);
diff --git a/include/backtrace/BacktraceMap.h b/include/backtrace/BacktraceMap.h
index df48dfe..8ab0dfa 100644
--- a/include/backtrace/BacktraceMap.h
+++ b/include/backtrace/BacktraceMap.h
@@ -33,6 +33,10 @@
 #include <string>
 #include <vector>
 
+// Special flag to indicate a map is in /dev/. However, a map in
+// /dev/ashmem/... does not set this flag.
+static constexpr int PROT_DEVICE_MAP = 0x8000;
+
 struct backtrace_map_t {
   uintptr_t start = 0;
   uintptr_t end = 0;
diff --git a/include/private/android_filesystem_capability.h b/include/private/android_filesystem_capability.h
new file mode 120000
index 0000000..f310b35
--- /dev/null
+++ b/include/private/android_filesystem_capability.h
@@ -0,0 +1 @@
+../../libcutils/include/private/android_filesystem_capability.h
\ No newline at end of file
diff --git a/include/private/android_filesystem_config.h b/include/private/android_filesystem_config.h
deleted file mode 100644
index 48a0e61..0000000
--- a/include/private/android_filesystem_config.h
+++ /dev/null
@@ -1,222 +0,0 @@
-/*
- * 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.
-*/
-
-/*
- * This file is consumed by build/tools/fs_config and is used
- * for generating various files. Anything #define AID_<name>
- * becomes the mapping for getpwnam/getpwuid, etc. The <name>
- * field is lowercased.
- * For example:
- * #define AID_FOO_BAR 6666 becomes a friendly name of "foo_bar"
- *
- * The above holds true with the exception of:
- *   mediacodec
- *   mediaex
- *   mediadrm
- * Whose friendly names do not match the #define statements.
- *
- * Additionally, AID_OEM_RESERVED_START and AID_OEM_RESERVED_END
- * can be used to define reserved OEM ranges used for sanity checks
- * during the build process. The rules are, they must end with START/END
- * The proper convention is incrementing a number like so:
- * AID_OEM_RESERVED_START
- * AID_OEM_RESERVED_1_START
- * AID_OEM_RESERVED_2_START
- * ...
- * The same applies to the END.
- * They are not required to be in order, but must not overlap each other and
- * must define a START and END'ing range. START must be smaller than END.
- */
-
-#ifndef _ANDROID_FILESYSTEM_CONFIG_H_
-#define _ANDROID_FILESYSTEM_CONFIG_H_
-
-#include <sys/cdefs.h>
-#include <sys/types.h>
-#include <stdint.h>
-
-#if defined(__ANDROID__)
-#include <linux/capability.h>
-#else
-#include "android_filesystem_capability.h"
-#endif
-
-#define CAP_MASK_LONG(cap_name)  (1ULL << (cap_name))
-
-/* This is the master Users and Groups config for the platform.
- * DO NOT EVER RENUMBER
- */
-
-#define AID_ROOT             0  /* traditional unix root user */
-
-#define AID_SYSTEM        1000  /* system server */
-
-#define AID_RADIO         1001  /* telephony subsystem, RIL */
-#define AID_BLUETOOTH     1002  /* bluetooth subsystem */
-#define AID_GRAPHICS      1003  /* graphics devices */
-#define AID_INPUT         1004  /* input devices */
-#define AID_AUDIO         1005  /* audio devices */
-#define AID_CAMERA        1006  /* camera devices */
-#define AID_LOG           1007  /* log devices */
-#define AID_COMPASS       1008  /* compass device */
-#define AID_MOUNT         1009  /* mountd socket */
-#define AID_WIFI          1010  /* wifi subsystem */
-#define AID_ADB           1011  /* android debug bridge (adbd) */
-#define AID_INSTALL       1012  /* group for installing packages */
-#define AID_MEDIA         1013  /* mediaserver process */
-#define AID_DHCP          1014  /* dhcp client */
-#define AID_SDCARD_RW     1015  /* external storage write access */
-#define AID_VPN           1016  /* vpn system */
-#define AID_KEYSTORE      1017  /* keystore subsystem */
-#define AID_USB           1018  /* USB devices */
-#define AID_DRM           1019  /* DRM server */
-#define AID_MDNSR         1020  /* MulticastDNSResponder (service discovery) */
-#define AID_GPS           1021  /* GPS daemon */
-#define AID_UNUSED1       1022  /* deprecated, DO NOT USE */
-#define AID_MEDIA_RW      1023  /* internal media storage write access */
-#define AID_MTP           1024  /* MTP USB driver access */
-#define AID_UNUSED2       1025  /* deprecated, DO NOT USE */
-#define AID_DRMRPC        1026  /* group for drm rpc */
-#define AID_NFC           1027  /* nfc subsystem */
-#define AID_SDCARD_R      1028  /* external storage read access */
-#define AID_CLAT          1029  /* clat part of nat464 */
-#define AID_LOOP_RADIO    1030  /* loop radio devices */
-#define AID_MEDIA_DRM     1031  /* MediaDrm plugins */
-#define AID_PACKAGE_INFO  1032  /* access to installed package details */
-#define AID_SDCARD_PICS   1033  /* external storage photos access */
-#define AID_SDCARD_AV     1034  /* external storage audio/video access */
-#define AID_SDCARD_ALL    1035  /* access all users external storage */
-#define AID_LOGD          1036  /* log daemon */
-#define AID_SHARED_RELRO  1037  /* creator of shared GNU RELRO files */
-#define AID_DBUS          1038  /* dbus-daemon IPC broker process */
-#define AID_TLSDATE       1039  /* tlsdate unprivileged user */
-#define AID_MEDIA_EX      1040  /* mediaextractor process */
-#define AID_AUDIOSERVER   1041  /* audioserver process */
-#define AID_METRICS_COLL  1042  /* metrics_collector process */
-#define AID_METRICSD      1043  /* metricsd process */
-#define AID_WEBSERV       1044  /* webservd process */
-#define AID_DEBUGGERD     1045  /* debuggerd unprivileged user */
-#define AID_MEDIA_CODEC   1046  /* mediacodec process */
-#define AID_CAMERASERVER  1047  /* cameraserver process */
-#define AID_FIREWALL      1048  /* firewalld process */
-#define AID_TRUNKS        1049  /* trunksd process (TPM daemon) */
-#define AID_NVRAM         1050  /* Access-controlled NVRAM */
-#define AID_DNS           1051  /* DNS resolution daemon (system: netd) */
-#define AID_DNS_TETHER    1052  /* DNS resolution daemon (tether: dnsmasq) */
-#define AID_WEBVIEW_ZYGOTE 1053 /* WebView zygote process */
-#define AID_VEHICLE_NETWORK 1054 /* Vehicle network service */
-#define AID_MEDIA_AUDIO   1055  /* GID for audio files on internal media storage */
-#define AID_MEDIA_VIDEO   1056  /* GID for video files on internal media storage */
-#define AID_MEDIA_IMAGE   1057  /* GID for image files on internal media storage */
-#define AID_TOMBSTONED    1058  /* tombstoned user */
-#define AID_MEDIA_OBB     1059  /* GID for OBB files on internal media storage */
-#define AID_ESE           1060  /* embedded secure element (eSE) subsystem */
-/* Changes to this file must be made in AOSP, *not* in internal branches. */
-
-#define AID_SHELL         2000  /* adb and debug shell user */
-#define AID_CACHE         2001  /* cache access */
-#define AID_DIAG          2002  /* access to diagnostic resources */
-
-/* The range 2900-2999 is reserved for OEM, and must never be
- * used here */
-#define AID_OEM_RESERVED_START 2900
-#define AID_OEM_RESERVED_END   2999
-
-/* The 3000 series are intended for use as supplemental group id's only.
- * They indicate special Android capabilities that the kernel is aware of. */
-#define AID_NET_BT_ADMIN  3001  /* bluetooth: create any socket */
-#define AID_NET_BT        3002  /* bluetooth: create sco, rfcomm or l2cap sockets */
-#define AID_INET          3003  /* can create AF_INET and AF_INET6 sockets */
-#define AID_NET_RAW       3004  /* can create raw INET sockets */
-#define AID_NET_ADMIN     3005  /* can configure interfaces and routing tables. */
-#define AID_NET_BW_STATS  3006  /* read bandwidth statistics */
-#define AID_NET_BW_ACCT   3007  /* change bandwidth statistics accounting */
-#define AID_READPROC      3009  /* Allow /proc read access */
-#define AID_WAKELOCK      3010  /* Allow system wakelock read/write access */
-
-/* The range 5000-5999 is also reserved for OEM, and must never be used here. */
-#define AID_OEM_RESERVED_2_START 5000
-#define AID_OEM_RESERVED_2_END   5999
-
-#define AID_EVERYBODY     9997  /* shared between all apps in the same profile */
-#define AID_MISC          9998  /* access to misc storage */
-#define AID_NOBODY        9999
-
-#define AID_APP              10000 /* TODO: switch users over to AID_APP_START */
-#define AID_APP_START        10000 /* first app user */
-#define AID_APP_END          19999 /* last app user */
-
-#define AID_CACHE_GID_START  20000 /* start of gids for apps to mark cached data */
-#define AID_CACHE_GID_END    29999 /* end of gids for apps to mark cached data */
-
-#define AID_EXT_GID_START    30000 /* start of gids for apps to mark external data */
-#define AID_EXT_GID_END      39999 /* end of gids for apps to mark external data */
-
-#define AID_SHARED_GID_START 50000 /* start of gids for apps in each user to share */
-#define AID_SHARED_GID_END   59999 /* end of gids for apps in each user to share */
-
-#define AID_ISOLATED_START   99000 /* start of uids for fully isolated sandboxed processes */
-#define AID_ISOLATED_END     99999 /* end of uids for fully isolated sandboxed processes */
-
-#define AID_USER            100000 /* TODO: switch users over to AID_USER_OFFSET */
-#define AID_USER_OFFSET     100000 /* offset for uid ranges for each user */
-
-/*
- * android_ids has moved to pwd/grp functionality.
- * If you need to add one, the structure is now
- * auto-generated based on the AID_ constraints
- * documented at the top of this header file.
- * Also see build/tools/fs_config for more details.
- */
-
-#if !defined(EXCLUDE_FS_CONFIG_STRUCTURES)
-
-struct fs_path_config {
-    unsigned mode;
-    unsigned uid;
-    unsigned gid;
-    uint64_t capabilities;
-    const char *prefix;
-};
-
-/* Rules for directories and files has moved to system/code/libcutils/fs_config.c */
-
-__BEGIN_DECLS
-
-/*
- * Used in:
- *  build/tools/fs_config/fs_config.c
- *  build/tools/fs_get_stats/fs_get_stats.c
- *  system/extras/ext4_utils/make_ext4fs_main.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, const char *target_out_path,
-               unsigned *uid, unsigned *gid, unsigned *mode, uint64_t *capabilities);
-
-ssize_t fs_config_generate(char *buffer, size_t length, const struct fs_path_config *pc);
-
-__END_DECLS
-
-#endif
-#endif
diff --git a/include/private/android_filesystem_config.h b/include/private/android_filesystem_config.h
new file mode 120000
index 0000000..f28a564
--- /dev/null
+++ b/include/private/android_filesystem_config.h
@@ -0,0 +1 @@
+../../libcutils/include/private/android_filesystem_config.h
\ No newline at end of file
diff --git a/include/private/canned_fs_config.h b/include/private/canned_fs_config.h
new file mode 120000
index 0000000..8f92b2d
--- /dev/null
+++ b/include/private/canned_fs_config.h
@@ -0,0 +1 @@
+../../libcutils/include/private/canned_fs_config.h
\ No newline at end of file
diff --git a/include/ziparchive/zip_writer.h b/include/ziparchive/zip_writer.h
index 0b6ede4..41ca2e1 100644
--- a/include/ziparchive/zip_writer.h
+++ b/include/ziparchive/zip_writer.h
@@ -17,15 +17,16 @@
 #ifndef LIBZIPARCHIVE_ZIPWRITER_H_
 #define LIBZIPARCHIVE_ZIPWRITER_H_
 
-#include "android-base/macros.h"
-#include <utils/Compat.h>
-
 #include <cstdio>
 #include <ctime>
+#include <zlib.h>
+
 #include <memory>
 #include <string>
 #include <vector>
-#include <zlib.h>
+
+#include "android-base/macros.h"
+#include "utils/Compat.h"
 
 /**
  * Writes a Zip file via a stateful interface.
@@ -63,6 +64,20 @@
     kAlign32 = 0x02,
   };
 
+  /**
+   * A struct representing a zip file entry.
+   */
+  struct FileEntry {
+    std::string path;
+    uint16_t compression_method;
+    uint32_t crc32;
+    uint32_t compressed_size;
+    uint32_t uncompressed_size;
+    uint16_t last_mod_time;
+    uint16_t last_mod_date;
+    uint32_t local_file_header_offset;
+  };
+
   static const char* ErrorCodeString(int32_t error_code);
 
   /**
@@ -122,6 +137,19 @@
   int32_t FinishEntry();
 
   /**
+   * Discards the last-written entry. Can only be called after an entry has been written using
+   * FinishEntry().
+   * Returns 0 on success, and an error value < 0 on failure.
+   */
+  int32_t DiscardLastEntry();
+
+  /**
+   * Sets `out_entry` to the last entry written after a call to FinishEntry().
+   * Returns 0 on success, and an error value < 0 if no entries have been written.
+   */
+  int32_t GetLastEntry(FileEntry* out_entry);
+
+  /**
    * Writes the Central Directory Headers and flushes the zip file stream.
    * Returns 0 on success, and an error value < 0 on failure.
    */
@@ -130,22 +158,11 @@
 private:
   DISALLOW_COPY_AND_ASSIGN(ZipWriter);
 
-  struct FileInfo {
-    std::string path;
-    uint16_t compression_method;
-    uint32_t crc32;
-    uint32_t compressed_size;
-    uint32_t uncompressed_size;
-    uint16_t last_mod_time;
-    uint16_t last_mod_date;
-    uint32_t local_file_header_offset;
-  };
-
   int32_t HandleError(int32_t error_code);
   int32_t PrepareDeflate();
-  int32_t StoreBytes(FileInfo* file, const void* data, size_t len);
-  int32_t CompressBytes(FileInfo* file, const void* data, size_t len);
-  int32_t FlushCompressedBytes(FileInfo* file);
+  int32_t StoreBytes(FileEntry* file, const void* data, size_t len);
+  int32_t CompressBytes(FileEntry* file, const void* data, size_t len);
+  int32_t FlushCompressedBytes(FileEntry* file);
 
   enum class State {
     kWritingZip,
@@ -157,7 +174,8 @@
   FILE* file_;
   off64_t current_offset_;
   State state_;
-  std::vector<FileInfo> files_;
+  std::vector<FileEntry> files_;
+  FileEntry current_file_entry_;
 
   std::unique_ptr<z_stream, void(*)(z_stream*)> z_stream_;
   std::vector<uint8_t> buffer_;
diff --git a/init/Android.mk b/init/Android.mk
index 2a1ad9c..c82a19e 100644
--- a/init/Android.mk
+++ b/init/Android.mk
@@ -5,9 +5,15 @@
 # --
 
 ifneq (,$(filter userdebug eng,$(TARGET_BUILD_VARIANT)))
-init_options += -DALLOW_LOCAL_PROP_OVERRIDE=1 -DALLOW_PERMISSIVE_SELINUX=1
+init_options += \
+    -DALLOW_LOCAL_PROP_OVERRIDE=1 \
+    -DALLOW_PERMISSIVE_SELINUX=1 \
+    -DREBOOT_BOOTLOADER_ON_PANIC=1
 else
-init_options += -DALLOW_LOCAL_PROP_OVERRIDE=0 -DALLOW_PERMISSIVE_SELINUX=0
+init_options += \
+    -DALLOW_LOCAL_PROP_OVERRIDE=0 \
+    -DALLOW_PERMISSIVE_SELINUX=0 \
+    -DREBOOT_BOOTLOADER_ON_PANIC=0
 endif
 
 init_options += -DLOG_UEVENTS=0
@@ -71,6 +77,7 @@
     init.cpp \
     keychords.cpp \
     property_service.cpp \
+    reboot.cpp \
     signal_handler.cpp \
     ueventd.cpp \
     ueventd_parser.cpp \
diff --git a/init/README.md b/init/README.md
index d3dd73a..709c667 100644
--- a/init/README.md
+++ b/init/README.md
@@ -203,7 +203,9 @@
 
 `writepid <file...>`
 > Write the child's pid to the given files when it forks. Meant for
-  cgroup/cpuset usage.
+  cgroup/cpuset usage. If no files under /dev/cpuset/ are specified, but the
+  system property 'ro.cpuset.default' is set to a non-empty cpuset name (e.g.
+  '/foreground'), then the pid is written to file /dev/cpuset/_cpuset\_name_/tasks.
 
 `priority <priority>`
 > Scheduling priority of the service process. This value has to be in range
@@ -280,6 +282,11 @@
 `copy <src> <dst>`
 > Copies a file. Similar to write, but useful for binary/large
   amounts of data.
+  Regarding to the src file, copying from symbol link file and world-writable
+  or group-writable files are not allowed.
+  Regarding to the dst file, the default mode created is 0600 if it does not
+  exist. And it will be truncated if dst file is a normal regular file and
+  already exists.
 
 `domainname <name>`
 > Set the domain name.
diff --git a/init/builtins.cpp b/init/builtins.cpp
index 0b2e761..32e9ef6 100644
--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -64,6 +64,7 @@
 #include "init_parser.h"
 #include "log.h"
 #include "property_service.h"
+#include "reboot.h"
 #include "service.h"
 #include "signal_handler.h"
 #include "util.h"
@@ -71,7 +72,6 @@
 using namespace std::literals::string_literals;
 
 #define chmod DO_NOT_USE_CHMOD_USE_FCHMODAT_SYMLINK_NOFOLLOW
-#define UNMOUNT_CHECK_TIMES 10
 
 static constexpr std::chrono::nanoseconds kCommandRetryTimeout = 5s;
 
@@ -116,114 +116,14 @@
     return ret;
 }
 
-// Turn off backlight while we are performing power down cleanup activities.
-static void turnOffBacklight() {
-    static const char off[] = "0";
-
-    android::base::WriteStringToFile(off, "/sys/class/leds/lcd-backlight/brightness");
-
-    static const char backlightDir[] = "/sys/class/backlight";
-    std::unique_ptr<DIR, int(*)(DIR*)> dir(opendir(backlightDir), closedir);
-    if (!dir) {
-        return;
-    }
-
-    struct dirent *dp;
-    while ((dp = readdir(dir.get())) != NULL) {
-        if (((dp->d_type != DT_DIR) && (dp->d_type != DT_LNK)) ||
-                (dp->d_name[0] == '.')) {
-            continue;
-        }
-
-        std::string fileName = android::base::StringPrintf("%s/%s/brightness",
-                                                           backlightDir,
-                                                           dp->d_name);
-        android::base::WriteStringToFile(off, fileName);
-    }
-}
-
 static int reboot_into_recovery(const std::vector<std::string>& options) {
     std::string err;
     if (!write_bootloader_message(options, &err)) {
         LOG(ERROR) << "failed to set bootloader message: " << err;
         return -1;
     }
-    reboot("recovery");
-}
-
-static void unmount_and_fsck(const struct mntent *entry) {
-    if (strcmp(entry->mnt_type, "f2fs") && strcmp(entry->mnt_type, "ext4"))
-        return;
-
-    /* First, lazily unmount the directory. This unmount request finishes when
-     * all processes that open a file or directory in |entry->mnt_dir| exit.
-     */
-    TEMP_FAILURE_RETRY(umount2(entry->mnt_dir, MNT_DETACH));
-
-    /* Next, kill all processes except init, kthreadd, and kthreadd's
-     * children to finish the lazy unmount. Killing all processes here is okay
-     * because this callback function is only called right before reboot().
-     * It might be cleaner to selectively kill processes that actually use
-     * |entry->mnt_dir| rather than killing all, probably by reusing a function
-     * like killProcessesWithOpenFiles() in vold/, but the selinux policy does
-     * not allow init to scan /proc/<pid> files which the utility function
-     * heavily relies on. The policy does not allow the process to execute
-     * killall/pkill binaries either. Note that some processes might
-     * automatically restart after kill(), but that is not really a problem
-     * because |entry->mnt_dir| is no longer visible to such new processes.
-     */
-    ServiceManager::GetInstance().ForEachService([] (Service* s) { s->Stop(); });
-    TEMP_FAILURE_RETRY(kill(-1, SIGKILL));
-
-    // Restart Watchdogd to allow us to complete umounting and fsck
-    Service *svc = ServiceManager::GetInstance().FindServiceByName("watchdogd");
-    if (svc) {
-        do {
-            sched_yield(); // do not be so eager, let cleanup have priority
-            ServiceManager::GetInstance().ReapAnyOutstandingChildren();
-        } while (svc->flags() & SVC_RUNNING); // Paranoid Cargo
-        svc->Start();
-    }
-
-    turnOffBacklight();
-
-    int count = 0;
-    while (count++ < UNMOUNT_CHECK_TIMES) {
-        int fd = TEMP_FAILURE_RETRY(open(entry->mnt_fsname, O_RDONLY | O_EXCL));
-        if (fd >= 0) {
-            /* |entry->mnt_dir| has sucessfully been unmounted. */
-            close(fd);
-            break;
-        } else if (errno == EBUSY) {
-            // Some processes using |entry->mnt_dir| are still alive. Wait for a
-            // while then retry.
-            std::this_thread::sleep_for(5000ms / UNMOUNT_CHECK_TIMES);
-            continue;
-        } else {
-            /* Cannot open the device. Give up. */
-            return;
-        }
-    }
-
-    // NB: With watchdog still running, there is no cap on the time it takes
-    // to complete the fsck, from the users perspective the device graphics
-    // and responses are locked-up and they may choose to hold the power
-    // button in frustration if it drags out.
-
-    int st;
-    if (!strcmp(entry->mnt_type, "f2fs")) {
-        const char *f2fs_argv[] = {
-            "/system/bin/fsck.f2fs", "-f", entry->mnt_fsname,
-        };
-        android_fork_execvp_ext(arraysize(f2fs_argv), (char **)f2fs_argv,
-                                &st, true, LOG_KLOG, true, NULL, NULL, 0);
-    } else if (!strcmp(entry->mnt_type, "ext4")) {
-        const char *ext4_argv[] = {
-            "/system/bin/e2fsck", "-f", "-y", entry->mnt_fsname,
-        };
-        android_fork_execvp_ext(arraysize(ext4_argv), (char **)ext4_argv,
-                                &st, true, LOG_KLOG, true, NULL, NULL, 0);
-    }
+    DoReboot(ANDROID_RB_RESTART2, "reboot", "recovery", false);
+    return 0;
 }
 
 static int do_class_start(const std::vector<std::string>& args) {
@@ -706,83 +606,51 @@
 }
 
 static int do_powerctl(const std::vector<std::string>& args) {
-    const char* command = args[1].c_str();
-    int len = 0;
+    const std::string& command = args[1];
     unsigned int cmd = 0;
-    const char *reboot_target = "";
-    void (*callback_on_ro_remount)(const struct mntent*) = NULL;
+    std::vector<std::string> cmd_params = android::base::Split(command, ",");
+    std::string reason_string = cmd_params[0];
+    std::string reboot_target = "";
+    bool runFsck = false;
+    bool commandInvalid = false;
 
-    if (strncmp(command, "shutdown", 8) == 0) {
+    if (cmd_params.size() > 2) {
+        commandInvalid = true;
+    } else if (cmd_params[0] == "shutdown") {
         cmd = ANDROID_RB_POWEROFF;
-        len = 8;
-    } else if (strncmp(command, "reboot", 6) == 0) {
+        if (cmd_params.size() == 2 && cmd_params[1] == "userrequested") {
+            // The shutdown reason is PowerManager.SHUTDOWN_USER_REQUESTED.
+            // Run fsck once the file system is remounted in read-only mode.
+            runFsck = true;
+            reason_string = cmd_params[1];
+        }
+    } else if (cmd_params[0] == "reboot") {
         cmd = ANDROID_RB_RESTART2;
-        len = 6;
+        if (cmd_params.size() == 2) {
+            reboot_target = cmd_params[1];
+            // When rebooting to the bootloader notify the bootloader writing
+            // also the BCB.
+            if (reboot_target == "bootloader") {
+                std::string err;
+                if (!write_reboot_bootloader(&err)) {
+                    LOG(ERROR) << "reboot-bootloader: Error writing "
+                                  "bootloader_message: "
+                               << err;
+                }
+            }
+        }
+    } else if (command == "thermal-shutdown") {  // no additional parameter allowed
+        cmd = ANDROID_RB_THERMOFF;
     } else {
+        commandInvalid = true;
+    }
+    if (commandInvalid) {
         LOG(ERROR) << "powerctl: unrecognized command '" << command << "'";
         return -EINVAL;
     }
 
-    if (command[len] == ',') {
-        if (cmd == ANDROID_RB_POWEROFF &&
-            !strcmp(&command[len + 1], "userrequested")) {
-            // The shutdown reason is PowerManager.SHUTDOWN_USER_REQUESTED.
-            // Run fsck once the file system is remounted in read-only mode.
-            callback_on_ro_remount = unmount_and_fsck;
-        } else if (cmd == ANDROID_RB_RESTART2) {
-            reboot_target = &command[len + 1];
-            // When rebooting to the bootloader notify the bootloader writing
-            // also the BCB.
-            if (strcmp(reboot_target, "bootloader") == 0) {
-                std::string err;
-                if (!write_reboot_bootloader(&err)) {
-                    LOG(ERROR) << "reboot-bootloader: Error writing "
-                                  "bootloader_message: " << err;
-                }
-            }
-        }
-    } else if (command[len] != '\0') {
-        LOG(ERROR) << "powerctl: unrecognized reboot target '" << &command[len] << "'";
-        return -EINVAL;
-    }
-
-    std::string timeout = property_get("ro.build.shutdown_timeout");
-    unsigned int delay = 0;
-
-    if (android::base::ParseUint(timeout, &delay) && delay > 0) {
-        Timer t;
-        // Ask all services to terminate.
-        ServiceManager::GetInstance().ForEachService(
-            [] (Service* s) { s->Terminate(); });
-
-        while (t.duration_s() < delay) {
-            ServiceManager::GetInstance().ReapAnyOutstandingChildren();
-
-            int service_count = 0;
-            ServiceManager::GetInstance().ForEachService(
-                [&service_count] (Service* s) {
-                    // Count the number of services running.
-                    // Exclude the console as it will ignore the SIGTERM signal
-                    // and not exit.
-                    // Note: SVC_CONSOLE actually means "requires console" but
-                    // it is only used by the shell.
-                    if (s->pid() != 0 && (s->flags() & SVC_CONSOLE) == 0) {
-                        service_count++;
-                    }
-                });
-
-            if (service_count == 0) {
-                // All terminable services terminated. We can exit early.
-                break;
-            }
-
-            // Wait a bit before recounting the number or running services.
-            std::this_thread::sleep_for(50ms);
-        }
-        LOG(VERBOSE) << "Terminating running services took " << t;
-    }
-
-    return android_reboot_with_callback(cmd, 0, reboot_target, callback_on_ro_remount);
+    DoReboot(cmd, reason_string, reboot_target, runFsck);
+    return 0;
 }
 
 static int do_trigger(const std::vector<std::string>& args) {
@@ -836,61 +704,11 @@
 }
 
 static int do_copy(const std::vector<std::string>& args) {
-    char *buffer = NULL;
-    int rc = 0;
-    int fd1 = -1, fd2 = -1;
-    struct stat info;
-    int brtw, brtr;
-    char *p;
-
-    if (stat(args[1].c_str(), &info) < 0)
-        return -1;
-
-    if ((fd1 = open(args[1].c_str(), O_RDONLY|O_CLOEXEC)) < 0)
-        goto out_err;
-
-    if ((fd2 = open(args[2].c_str(), O_WRONLY|O_CREAT|O_TRUNC|O_CLOEXEC, 0660)) < 0)
-        goto out_err;
-
-    if (!(buffer = (char*) malloc(info.st_size)))
-        goto out_err;
-
-    p = buffer;
-    brtr = info.st_size;
-    while(brtr) {
-        rc = read(fd1, p, brtr);
-        if (rc < 0)
-            goto out_err;
-        if (rc == 0)
-            break;
-        p += rc;
-        brtr -= rc;
+    std::string data;
+    if (read_file(args[1].c_str(), &data)) {
+        return write_file(args[2].c_str(), data.data()) ? 0 : 1;
     }
-
-    p = buffer;
-    brtw = info.st_size;
-    while(brtw) {
-        rc = write(fd2, p, brtw);
-        if (rc < 0)
-            goto out_err;
-        if (rc == 0)
-            break;
-        p += rc;
-        brtw -= rc;
-    }
-
-    rc = 0;
-    goto out;
-out_err:
-    rc = -1;
-out:
-    if (buffer)
-        free(buffer);
-    if (fd1 >= 0)
-        close(fd1);
-    if (fd2 >= 0)
-        close(fd2);
-    return rc;
+    return 1;
 }
 
 static int do_chown(const std::vector<std::string>& args) {
diff --git a/init/init.cpp b/init/init.cpp
index 4e31865..23448d6 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -1099,6 +1099,31 @@
     return success;
 }
 
+static void install_reboot_signal_handlers() {
+    // Instead of panic'ing the kernel as is the default behavior when init crashes,
+    // we prefer to reboot to bootloader on development builds, as this will prevent
+    // boot looping bad configurations and allow both developers and test farms to easily
+    // recover.
+    struct sigaction action;
+    memset(&action, 0, sizeof(action));
+    sigfillset(&action.sa_mask);
+    action.sa_handler = [](int) {
+        // panic() reboots to bootloader
+        panic();
+    };
+    action.sa_flags = SA_RESTART;
+    sigaction(SIGABRT, &action, nullptr);
+    sigaction(SIGBUS, &action, nullptr);
+    sigaction(SIGFPE, &action, nullptr);
+    sigaction(SIGILL, &action, nullptr);
+    sigaction(SIGSEGV, &action, nullptr);
+#if defined(SIGSTKFLT)
+    sigaction(SIGSTKFLT, &action, nullptr);
+#endif
+    sigaction(SIGSYS, &action, nullptr);
+    sigaction(SIGTRAP, &action, nullptr);
+}
+
 int main(int argc, char** argv) {
     if (!strcmp(basename(argv[0]), "ueventd")) {
         return ueventd_main(argc, argv);
@@ -1108,27 +1133,30 @@
         return watchdogd_main(argc, argv);
     }
 
-    boot_clock::time_point start_time = boot_clock::now();
-
-    // Clear the umask.
-    umask(0);
+    if (REBOOT_BOOTLOADER_ON_PANIC) {
+        install_reboot_signal_handlers();
+    }
 
     add_environment("PATH", _PATH_DEFPATH);
 
     bool is_first_stage = (getenv("INIT_SECOND_STAGE") == nullptr);
 
-    // Don't expose the raw commandline to unprivileged processes.
-    chmod("/proc/cmdline", 0440);
-
-    // Get the basic filesystem setup we need put together in the initramdisk
-    // on / and then we'll let the rc file figure out the rest.
     if (is_first_stage) {
+        boot_clock::time_point start_time = boot_clock::now();
+
+        // Clear the umask.
+        umask(0);
+
+        // Get the basic filesystem setup we need put together in the initramdisk
+        // on / and then we'll let the rc file figure out the rest.
         mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755");
         mkdir("/dev/pts", 0755);
         mkdir("/dev/socket", 0755);
         mount("devpts", "/dev/pts", "devpts", 0, NULL);
         #define MAKE_STR(x) __STRING(x)
         mount("proc", "/proc", "proc", 0, "hidepid=2,gid=" MAKE_STR(AID_READPROC));
+        // Don't expose the raw commandline to unprivileged processes.
+        chmod("/proc/cmdline", 0440);
         gid_t groups[] = { AID_READPROC };
         setgroups(arraysize(groups), groups);
         mount("sysfs", "/sys", "sysfs", 0, NULL);
@@ -1136,15 +1164,13 @@
         mknod("/dev/kmsg", S_IFCHR | 0600, makedev(1, 11));
         mknod("/dev/random", S_IFCHR | 0666, makedev(1, 8));
         mknod("/dev/urandom", S_IFCHR | 0666, makedev(1, 9));
-    }
 
-    // Now that tmpfs is mounted on /dev and we have /dev/kmsg, we can actually
-    // talk to the outside world...
-    InitKernelLogging(argv);
+        // Now that tmpfs is mounted on /dev and we have /dev/kmsg, we can actually
+        // talk to the outside world...
+        InitKernelLogging(argv);
 
-    LOG(INFO) << "init " << (is_first_stage ? "first" : "second") << " stage started!";
+        LOG(INFO) << "init first stage started!";
 
-    if (is_first_stage) {
         if (!early_mount()) {
             LOG(ERROR) << "Failed to mount required partitions early ...";
             panic();
@@ -1168,41 +1194,47 @@
 
         char* path = argv[0];
         char* args[] = { path, nullptr };
-        if (execv(path, args) == -1) {
-            PLOG(ERROR) << "execv(\"" << path << "\") failed";
-            security_failure();
-        }
-    } else {
-        // Indicate that booting is in progress to background fw loaders, etc.
-        close(open("/dev/.booting", O_WRONLY | O_CREAT | O_CLOEXEC, 0000));
+        execv(path, args);
 
-        property_init();
-
-        // If arguments are passed both on the command line and in DT,
-        // properties set in DT always have priority over the command-line ones.
-        process_kernel_dt();
-        process_kernel_cmdline();
-
-        // Propagate the kernel variables to internal variables
-        // used by init as well as the current required properties.
-        export_kernel_boot_props();
-
-        // Make the time that init started available for bootstat to log.
-        property_set("ro.boottime.init", getenv("INIT_STARTED_AT"));
-        property_set("ro.boottime.init.selinux", getenv("INIT_SELINUX_TOOK"));
-
-        // Set libavb version for Framework-only OTA match in Treble build.
-        property_set("ro.boot.init.avb_version", std::to_string(AVB_MAJOR_VERSION).c_str());
-
-        // Clean up our environment.
-        unsetenv("INIT_SECOND_STAGE");
-        unsetenv("INIT_STARTED_AT");
-        unsetenv("INIT_SELINUX_TOOK");
-
-        // Now set up SELinux for second stage.
-        selinux_initialize(false);
+        // execv() only returns if an error happened, in which case we
+        // panic and never fall through this conditional.
+        PLOG(ERROR) << "execv(\"" << path << "\") failed";
+        security_failure();
     }
 
+    // At this point we're in the second stage of init.
+    InitKernelLogging(argv);
+    LOG(INFO) << "init second stage started!";
+
+    // Indicate that booting is in progress to background fw loaders, etc.
+    close(open("/dev/.booting", O_WRONLY | O_CREAT | O_CLOEXEC, 0000));
+
+    property_init();
+
+    // If arguments are passed both on the command line and in DT,
+    // properties set in DT always have priority over the command-line ones.
+    process_kernel_dt();
+    process_kernel_cmdline();
+
+    // Propagate the kernel variables to internal variables
+    // used by init as well as the current required properties.
+    export_kernel_boot_props();
+
+    // Make the time that init started available for bootstat to log.
+    property_set("ro.boottime.init", getenv("INIT_STARTED_AT"));
+    property_set("ro.boottime.init.selinux", getenv("INIT_SELINUX_TOOK"));
+
+    // Set libavb version for Framework-only OTA match in Treble build.
+    property_set("ro.boot.init.avb_version", std::to_string(AVB_MAJOR_VERSION).c_str());
+
+    // Clean up our environment.
+    unsetenv("INIT_SECOND_STAGE");
+    unsetenv("INIT_STARTED_AT");
+    unsetenv("INIT_SELINUX_TOOK");
+
+    // Now set up SELinux for second stage.
+    selinux_initialize(false);
+
     // These directories were necessarily created before initial policy load
     // and therefore need their security context restored to the proper value.
     // This must happen before /dev is populated by ueventd.
@@ -1290,22 +1322,24 @@
     am.QueueBuiltinAction(queue_property_triggers_action, "queue_property_triggers");
 
     while (true) {
-        if (!(waiting_for_exec || waiting_for_prop)) {
-            am.ExecuteOneCommand();
-            restart_processes();
-        }
-
         // By default, sleep until something happens.
         int epoll_timeout_ms = -1;
 
-        // If there's a process that needs restarting, wake up in time for that.
-        if (process_needs_restart_at != 0) {
-            epoll_timeout_ms = (process_needs_restart_at - time(nullptr)) * 1000;
-            if (epoll_timeout_ms < 0) epoll_timeout_ms = 0;
+        if (!(waiting_for_exec || waiting_for_prop)) {
+            am.ExecuteOneCommand();
         }
+        if (!(waiting_for_exec || waiting_for_prop)) {
+            restart_processes();
 
-        // If there's more work to do, wake up again immediately.
-        if (am.HasMoreCommands()) epoll_timeout_ms = 0;
+            // If there's a process that needs restarting, wake up in time for that.
+            if (process_needs_restart_at != 0) {
+                epoll_timeout_ms = (process_needs_restart_at - time(nullptr)) * 1000;
+                if (epoll_timeout_ms < 0) epoll_timeout_ms = 0;
+            }
+
+            // If there's more work to do, wake up again immediately.
+            if (am.HasMoreCommands()) epoll_timeout_ms = 0;
+        }
 
         epoll_event ev;
         int nr = TEMP_FAILURE_RETRY(epoll_wait(epoll_fd, &ev, 1, epoll_timeout_ms));
diff --git a/init/reboot.cpp b/init/reboot.cpp
new file mode 100644
index 0000000..1559b6f
--- /dev/null
+++ b/init/reboot.cpp
@@ -0,0 +1,422 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <dirent.h>
+#include <fcntl.h>
+#include <mntent.h>
+#include <sys/cdefs.h>
+#include <sys/mount.h>
+#include <sys/quota.h>
+#include <sys/reboot.h>
+#include <sys/stat.h>
+#include <sys/syscall.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include <memory>
+#include <string>
+#include <thread>
+#include <vector>
+
+#include <android-base/file.h>
+#include <android-base/macros.h>
+#include <android-base/parseint.h>
+#include <android-base/stringprintf.h>
+#include <android-base/strings.h>
+#include <bootloader_message/bootloader_message.h>
+#include <cutils/android_reboot.h>
+#include <cutils/partition_utils.h>
+#include <fs_mgr.h>
+#include <logwrap/logwrap.h>
+
+#include "log.h"
+#include "property_service.h"
+#include "reboot.h"
+#include "service.h"
+#include "util.h"
+
+using android::base::StringPrintf;
+
+// represents umount status during reboot / shutdown.
+enum UmountStat {
+    /* umount succeeded. */
+    UMOUNT_STAT_SUCCESS = 0,
+    /* umount was not run. */
+    UMOUNT_STAT_SKIPPED = 1,
+    /* umount failed with timeout. */
+    UMOUNT_STAT_TIMEOUT = 2,
+    /* could not run due to error */
+    UMOUNT_STAT_ERROR = 3,
+    /* not used by init but reserved for other part to use this to represent the
+       the state where umount status before reboot is not found / available. */
+    UMOUNT_STAT_NOT_AVAILABLE = 4,
+};
+
+// Utility for struct mntent
+class MountEntry {
+  public:
+    explicit MountEntry(const mntent& entry, bool isMounted = true)
+        : mnt_fsname_(entry.mnt_fsname),
+          mnt_dir_(entry.mnt_dir),
+          mnt_type_(entry.mnt_type),
+          is_mounted_(isMounted) {}
+
+    bool IsF2Fs() const { return mnt_type_ == "f2fs"; }
+
+    bool IsExt4() const { return mnt_type_ == "ext4"; }
+
+    bool is_mounted() const { return is_mounted_; }
+
+    void set_is_mounted() { is_mounted_ = false; }
+
+    const std::string& mnt_fsname() const { return mnt_fsname_; }
+
+    const std::string& mnt_dir() const { return mnt_dir_; }
+
+    static bool IsBlockDevice(const struct mntent& mntent) {
+        return android::base::StartsWith(mntent.mnt_fsname, "/dev/block");
+    }
+
+    static bool IsEmulatedDevice(const struct mntent& mntent) {
+        static const std::string SDCARDFS_NAME = "sdcardfs";
+        return android::base::StartsWith(mntent.mnt_fsname, "/data/") &&
+               SDCARDFS_NAME == mntent.mnt_type;
+    }
+
+  private:
+    std::string mnt_fsname_;
+    std::string mnt_dir_;
+    std::string mnt_type_;
+    bool is_mounted_;
+};
+
+// Turn off backlight while we are performing power down cleanup activities.
+static void TurnOffBacklight() {
+    static constexpr char OFF[] = "0";
+
+    android::base::WriteStringToFile(OFF, "/sys/class/leds/lcd-backlight/brightness");
+
+    static const char backlightDir[] = "/sys/class/backlight";
+    std::unique_ptr<DIR, int (*)(DIR*)> dir(opendir(backlightDir), closedir);
+    if (!dir) {
+        return;
+    }
+
+    struct dirent* dp;
+    while ((dp = readdir(dir.get())) != nullptr) {
+        if (((dp->d_type != DT_DIR) && (dp->d_type != DT_LNK)) || (dp->d_name[0] == '.')) {
+            continue;
+        }
+
+        std::string fileName = StringPrintf("%s/%s/brightness", backlightDir, dp->d_name);
+        android::base::WriteStringToFile(OFF, fileName);
+    }
+}
+
+static void DoFsck(const MountEntry& entry) {
+    static constexpr int UNMOUNT_CHECK_TIMES = 10;
+
+    if (!entry.IsF2Fs() && !entry.IsExt4()) return;
+
+    int count = 0;
+    while (count++ < UNMOUNT_CHECK_TIMES) {
+        int fd = TEMP_FAILURE_RETRY(open(entry.mnt_fsname().c_str(), O_RDONLY | O_EXCL));
+        if (fd >= 0) {
+            /* |entry->mnt_dir| has sucessfully been unmounted. */
+            close(fd);
+            break;
+        } else if (errno == EBUSY) {
+            // Some processes using |entry->mnt_dir| are still alive. Wait for a
+            // while then retry.
+            std::this_thread::sleep_for(5000ms / UNMOUNT_CHECK_TIMES);
+            continue;
+        } else {
+            /* Cannot open the device. Give up. */
+            return;
+        }
+    }
+
+    // NB: With watchdog still running, there is no cap on the time it takes
+    // to complete the fsck, from the users perspective the device graphics
+    // and responses are locked-up and they may choose to hold the power
+    // button in frustration if it drags out.
+
+    int st;
+    if (entry.IsF2Fs()) {
+        const char* f2fs_argv[] = {
+            "/system/bin/fsck.f2fs", "-f", entry.mnt_fsname().c_str(),
+        };
+        android_fork_execvp_ext(arraysize(f2fs_argv), (char**)f2fs_argv, &st, true, LOG_KLOG, true,
+                                nullptr, nullptr, 0);
+    } else if (entry.IsExt4()) {
+        const char* ext4_argv[] = {
+            "/system/bin/e2fsck", "-f", "-y", entry.mnt_fsname().c_str(),
+        };
+        android_fork_execvp_ext(arraysize(ext4_argv), (char**)ext4_argv, &st, true, LOG_KLOG, true,
+                                nullptr, nullptr, 0);
+    }
+}
+
+static void ShutdownVold() {
+    const char* vdc_argv[] = {"/system/bin/vdc", "volume", "shutdown"};
+    int status;
+    android_fork_execvp_ext(arraysize(vdc_argv), (char**)vdc_argv, &status, true, LOG_KLOG, true,
+                            nullptr, nullptr, 0);
+}
+
+static void LogShutdownTime(UmountStat stat, Timer* t) {
+    LOG(WARNING) << "powerctl_shutdown_time_ms:" << std::to_string(t->duration_ms()) << ":" << stat;
+}
+
+static void __attribute__((noreturn))
+RebootSystem(unsigned int cmd, const std::string& rebootTarget) {
+    LOG(INFO) << "Reboot ending, jumping to kernel";
+    switch (cmd) {
+        case ANDROID_RB_POWEROFF:
+            reboot(RB_POWER_OFF);
+            break;
+
+        case ANDROID_RB_RESTART2:
+            syscall(__NR_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,
+                    LINUX_REBOOT_CMD_RESTART2, rebootTarget.c_str());
+            break;
+
+        case ANDROID_RB_THERMOFF:
+            reboot(RB_POWER_OFF);
+            break;
+    }
+    // In normal case, reboot should not return.
+    PLOG(FATAL) << "reboot call returned";
+    abort();
+}
+
+static void DoSync() {
+    // quota sync is not done by sync call, so should be done separately.
+    // quota sync is in VFS level, so do it before sync, which goes down to fs level.
+    int r = quotactl(QCMD(Q_SYNC, 0), nullptr, 0 /* do not care */, 0 /* do not care */);
+    if (r < 0) {
+        PLOG(ERROR) << "quotactl failed";
+    }
+    sync();
+}
+
+/* Find all read+write block devices and emulated devices in /proc/mounts
+ * and add them to correpsponding list.
+ */
+static bool FindPartitionsToUmount(std::vector<MountEntry>* blockDevPartitions,
+                                   std::vector<MountEntry>* emulatedPartitions) {
+    std::unique_ptr<std::FILE, int (*)(std::FILE*)> fp(setmntent("/proc/mounts", "r"), endmntent);
+    if (fp == nullptr) {
+        PLOG(ERROR) << "Failed to open /proc/mounts";
+        return false;
+    }
+    mntent* mentry;
+    while ((mentry = getmntent(fp.get())) != nullptr) {
+        if (MountEntry::IsBlockDevice(*mentry) && hasmntopt(mentry, "rw")) {
+            blockDevPartitions->emplace_back(*mentry);
+        } else if (MountEntry::IsEmulatedDevice(*mentry)) {
+            emulatedPartitions->emplace_back(*mentry);
+        }
+    }
+    return true;
+}
+
+static bool UmountPartitions(std::vector<MountEntry>* partitions, int maxRetry, int flags) {
+    static constexpr int SLEEP_AFTER_RETRY_US = 100000;
+
+    bool umountDone;
+    int retryCounter = 0;
+
+    while (true) {
+        umountDone = true;
+        for (auto& entry : *partitions) {
+            if (entry.is_mounted()) {
+                int r = umount2(entry.mnt_dir().c_str(), flags);
+                if (r == 0) {
+                    entry.set_is_mounted();
+                    LOG(INFO) << StringPrintf("umounted %s, flags:0x%x", entry.mnt_fsname().c_str(),
+                                              flags);
+                } else {
+                    umountDone = false;
+                    PLOG(WARNING) << StringPrintf("cannot umount %s, flags:0x%x",
+                                                  entry.mnt_fsname().c_str(), flags);
+                }
+            }
+        }
+        if (umountDone) break;
+        retryCounter++;
+        if (retryCounter >= maxRetry) break;
+        usleep(SLEEP_AFTER_RETRY_US);
+    }
+    return umountDone;
+}
+
+/* Try umounting all emulated file systems R/W block device cfile systems.
+ * This will just try umount and give it up if it fails.
+ * For fs like ext4, this is ok as file system will be marked as unclean shutdown
+ * and necessary check can be done at the next reboot.
+ * For safer shutdown, caller needs to make sure that
+ * all processes / emulated partition for the target fs are all cleaned-up.
+ *
+ * return true when umount was successful. false when timed out.
+ */
+static UmountStat TryUmountAndFsck(bool runFsck) {
+    std::vector<MountEntry> emulatedPartitions;
+    std::vector<MountEntry> blockDevRwPartitions;
+
+    TurnOffBacklight();  // this part can take time. save power.
+
+    if (!FindPartitionsToUmount(&blockDevRwPartitions, &emulatedPartitions)) {
+        return UMOUNT_STAT_ERROR;
+    }
+    if (emulatedPartitions.size() > 0) {
+        LOG(WARNING) << "emulated partitions still exist, will umount";
+        /* Pending writes in emulated partitions can fail umount. After a few trials, detach
+         * it so that it can be umounted when all writes are done.
+         */
+        if (!UmountPartitions(&emulatedPartitions, 1, 0)) {
+            UmountPartitions(&emulatedPartitions, 1, MNT_DETACH);
+        }
+    }
+    DoSync();  // emulated partition change can lead to update
+    UmountStat stat = UMOUNT_STAT_SUCCESS;
+    /* data partition needs all pending writes to be completed and all emulated partitions
+     * umounted. If umount failed in the above step, it DETACH is requested, so umount can
+     * still happen while waiting for /data. If the current waiting is not good enough, give
+     * up and leave it to e2fsck after reboot to fix it.
+     */
+    /* TODO update max waiting time based on usage data */
+    if (!UmountPartitions(&blockDevRwPartitions, 100, 0)) {
+        /* Last resort, detach and hope it finish before shutdown. */
+        UmountPartitions(&blockDevRwPartitions, 1, MNT_DETACH);
+        stat = UMOUNT_STAT_TIMEOUT;
+    }
+    if (stat == UMOUNT_STAT_SUCCESS && runFsck) {
+        for (auto& entry : blockDevRwPartitions) {
+            DoFsck(entry);
+        }
+    }
+
+    return stat;
+}
+
+static void KillAllProcesses() { android::base::WriteStringToFile("i", "/proc/sysrq-trigger"); }
+
+static void __attribute__((noreturn)) DoThermalOff() {
+    LOG(WARNING) << "Thermal system shutdown";
+    DoSync();
+    RebootSystem(ANDROID_RB_THERMOFF, "");
+    abort();
+}
+
+void DoReboot(unsigned int cmd, const std::string& reason, const std::string& rebootTarget,
+              bool runFsck) {
+    Timer t;
+    LOG(INFO) << "Reboot start, reason: " << reason << ", rebootTarget: " << rebootTarget;
+
+    android::base::WriteStringToFile(StringPrintf("%s\n", reason.c_str()), LAST_REBOOT_REASON_FILE);
+
+    if (cmd == ANDROID_RB_THERMOFF) {  // do not wait if it is thermal
+        DoThermalOff();
+        abort();
+    }
+
+    std::string timeout = property_get("ro.build.shutdown_timeout");
+    unsigned int delay = 0;
+    if (!android::base::ParseUint(timeout, &delay)) {
+        delay = 3;  // force service termination by default
+    } else {
+        LOG(INFO) << "ro.build.shutdown_timeout set:" << delay;
+    }
+
+    static const constexpr char* shutdown_critical_services[] = {"vold", "watchdogd"};
+    for (const char* name : shutdown_critical_services) {
+        Service* s = ServiceManager::GetInstance().FindServiceByName(name);
+        if (s == nullptr) {
+            LOG(WARNING) << "Shutdown critical service not found:" << name;
+            continue;
+        }
+        s->Start();  // make sure that it is running.
+        s->SetShutdownCritical();
+    }
+    // optional shutdown step
+    // 1. terminate all services except shutdown critical ones. wait for delay to finish
+    if (delay > 0) {
+        LOG(INFO) << "terminating init services";
+        // tombstoned can write to data when other services are killed. so finish it first.
+        static const constexpr char* first_to_kill[] = {"tombstoned"};
+        for (const char* name : first_to_kill) {
+            Service* s = ServiceManager::GetInstance().FindServiceByName(name);
+            if (s != nullptr) s->Stop();
+        }
+
+        // Ask all services to terminate except shutdown critical ones.
+        ServiceManager::GetInstance().ForEachService([](Service* s) {
+            if (!s->IsShutdownCritical()) s->Terminate();
+        });
+
+        int service_count = 0;
+        while (t.duration_s() < delay) {
+            ServiceManager::GetInstance().ReapAnyOutstandingChildren();
+
+            service_count = 0;
+            ServiceManager::GetInstance().ForEachService([&service_count](Service* s) {
+                // Count the number of services running except shutdown critical.
+                // Exclude the console as it will ignore the SIGTERM signal
+                // and not exit.
+                // Note: SVC_CONSOLE actually means "requires console" but
+                // it is only used by the shell.
+                if (!s->IsShutdownCritical() && s->pid() != 0 && (s->flags() & SVC_CONSOLE) == 0) {
+                    service_count++;
+                }
+            });
+
+            if (service_count == 0) {
+                // All terminable services terminated. We can exit early.
+                break;
+            }
+
+            // Wait a bit before recounting the number or running services.
+            std::this_thread::sleep_for(50ms);
+        }
+        LOG(INFO) << "Terminating running services took " << t
+                  << " with remaining services:" << service_count;
+    }
+
+    // minimum safety steps before restarting
+    // 2. kill all services except ones that are necessary for the shutdown sequence.
+    ServiceManager::GetInstance().ForEachService([](Service* s) {
+        if (!s->IsShutdownCritical()) s->Stop();
+    });
+    ServiceManager::GetInstance().ReapAnyOutstandingChildren();
+
+    // 3. send volume shutdown to vold
+    Service* voldService = ServiceManager::GetInstance().FindServiceByName("vold");
+    if (voldService != nullptr && voldService->IsRunning()) {
+        ShutdownVold();
+    } else {
+        LOG(INFO) << "vold not running, skipping vold shutdown";
+    }
+    if (delay == 0) {  // no processes terminated. kill all instead.
+        KillAllProcesses();
+    }
+    // 4. sync, try umount, and optionally run fsck for user shutdown
+    DoSync();
+    UmountStat stat = TryUmountAndFsck(runFsck);
+    LogShutdownTime(stat, &t);
+    // Reboot regardless of umount status. If umount fails, fsck after reboot will fix it.
+    RebootSystem(cmd, rebootTarget);
+    abort();
+}
diff --git a/init/reboot.h b/init/reboot.h
new file mode 100644
index 0000000..3956249
--- /dev/null
+++ b/init/reboot.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _INIT_REBOOT_H
+#define _INIT_REBOOT_H
+
+/* Reboot / shutdown the system.
+ * cmd ANDROID_RB_* as defined in android_reboot.h
+ * reason Reason string like "reboot", "userrequested"
+ * rebootTarget Reboot target string like "bootloader". Otherwise, it should be an
+ *              empty string.
+ * runFsck Whether to run fsck after umount is done.
+ */
+void DoReboot(unsigned int cmd, const std::string& reason, const std::string& rebootTarget,
+              bool runFsck) __attribute__((__noreturn__));
+
+#endif
diff --git a/init/service.cpp b/init/service.cpp
index ba901fd..c8d1cb1 100644
--- a/init/service.cpp
+++ b/init/service.cpp
@@ -630,6 +630,28 @@
         std::for_each(descriptors_.begin(), descriptors_.end(),
                       std::bind(&DescriptorInfo::CreateAndPublish, std::placeholders::_1, scon));
 
+        // See if there were "writepid" instructions to write to files under /dev/cpuset/.
+        auto cpuset_predicate = [](const std::string& path) {
+            return android::base::StartsWith(path, "/dev/cpuset/");
+        };
+        auto iter = std::find_if(writepid_files_.begin(), writepid_files_.end(), cpuset_predicate);
+        if (iter == writepid_files_.end()) {
+            // There were no "writepid" instructions for cpusets, check if the system default
+            // cpuset is specified to be used for the process.
+            std::string default_cpuset = property_get("ro.cpuset.default");
+            if (!default_cpuset.empty()) {
+                // Make sure the cpuset name starts and ends with '/'.
+                // A single '/' means the 'root' cpuset.
+                if (default_cpuset.front() != '/') {
+                    default_cpuset.insert(0, 1, '/');
+                }
+                if (default_cpuset.back() != '/') {
+                    default_cpuset.push_back('/');
+                }
+                writepid_files_.push_back(
+                    StringPrintf("/dev/cpuset%stasks", default_cpuset.c_str()));
+            }
+        }
         std::string pid_str = StringPrintf("%d", getpid());
         for (const auto& file : writepid_files_) {
             if (!WriteStringToFile(pid_str, file)) {
@@ -867,15 +889,10 @@
         }
     }
 
-    std::unique_ptr<Service> svc_p(new Service(name, "default", flags, uid, gid, supp_gids,
-                                               no_capabilities, namespace_flags, seclabel,
-                                               str_args));
-    if (!svc_p) {
-        LOG(ERROR) << "Couldn't allocate service for exec of '" << str_args[0] << "'";
-        return nullptr;
-    }
+    auto svc_p = std::make_unique<Service>(name, "default", flags, uid, gid, supp_gids,
+                                           no_capabilities, namespace_flags, seclabel, str_args);
     Service* svc = svc_p.get();
-    services_.push_back(std::move(svc_p));
+    services_.emplace_back(std::move(svc_p));
 
     return svc;
 }
diff --git a/init/service.h b/init/service.h
index 013e65f..08388e2 100644
--- a/init/service.h
+++ b/init/service.h
@@ -32,18 +32,21 @@
 #include "keyword_map.h"
 #include "util.h"
 
-#define SVC_DISABLED       0x001  // do not autostart with class
-#define SVC_ONESHOT        0x002  // do not restart on exit
-#define SVC_RUNNING        0x004  // currently active
-#define SVC_RESTARTING     0x008  // waiting to restart
-#define SVC_CONSOLE        0x010  // requires console
-#define SVC_CRITICAL       0x020  // will reboot into recovery if keeps crashing
-#define SVC_RESET          0x040  // Use when stopping a process,
+#define SVC_DISABLED 0x001        // do not autostart with class
+#define SVC_ONESHOT 0x002         // do not restart on exit
+#define SVC_RUNNING 0x004         // currently active
+#define SVC_RESTARTING 0x008      // waiting to restart
+#define SVC_CONSOLE 0x010         // requires console
+#define SVC_CRITICAL 0x020        // will reboot into recovery if keeps crashing
+#define SVC_RESET 0x040           // Use when stopping a process,
                                   // but not disabling so it can be restarted with its class.
-#define SVC_RC_DISABLED    0x080  // Remember if the disabled flag was set in the rc script.
-#define SVC_RESTART        0x100  // Use to safely restart (stop, wait, start) a service.
+#define SVC_RC_DISABLED 0x080     // Remember if the disabled flag was set in the rc script.
+#define SVC_RESTART 0x100         // Use to safely restart (stop, wait, start) a service.
 #define SVC_DISABLED_START 0x200  // A start was requested but it was disabled at the time.
-#define SVC_EXEC           0x400  // This synthetic service corresponds to an 'exec'.
+#define SVC_EXEC 0x400            // This synthetic service corresponds to an 'exec'.
+
+#define SVC_SHUTDOWN_CRITICAL 0x800  // This service is critical for shutdown and
+                                     // should not be killed during shutdown
 
 #define NR_SVC_SUPP_GIDS 12    // twelve supplementary groups
 
@@ -68,6 +71,7 @@
             unsigned namespace_flags, const std::string& seclabel,
             const std::vector<std::string>& args);
 
+    bool IsRunning() { return (flags_ & SVC_RUNNING) != 0; }
     bool ParseLine(const std::vector<std::string>& args, std::string* err);
     bool Start();
     bool StartIfNotDisabled();
@@ -79,6 +83,8 @@
     void RestartIfNeeded(time_t* process_needs_restart_at);
     bool Reap();
     void DumpState() const;
+    void SetShutdownCritical() { flags_ |= SVC_SHUTDOWN_CRITICAL; }
+    bool IsShutdownCritical() { return (flags_ & SVC_SHUTDOWN_CRITICAL) != 0; }
 
     const std::string& name() const { return name_; }
     const std::string& classname() const { return classname_; }
diff --git a/init/util.cpp b/init/util.cpp
index 888a366..0ba9800 100644
--- a/init/util.cpp
+++ b/init/util.cpp
@@ -49,6 +49,7 @@
 #include "init.h"
 #include "log.h"
 #include "property_service.h"
+#include "reboot.h"
 #include "util.h"
 
 static unsigned int do_decode_uid(const char *s)
@@ -163,7 +164,7 @@
 bool read_file(const char* path, std::string* content) {
     content->clear();
 
-    int fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY|O_NOFOLLOW|O_CLOEXEC));
+    android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_NOFOLLOW | O_CLOEXEC)));
     if (fd == -1) {
         return false;
     }
@@ -176,17 +177,16 @@
         return false;
     }
     if ((sb.st_mode & (S_IWGRP | S_IWOTH)) != 0) {
-        PLOG(ERROR) << "skipping insecure file '" << path << "'";
+        LOG(ERROR) << "skipping insecure file '" << path << "'";
         return false;
     }
 
-    bool okay = android::base::ReadFdToString(fd, content);
-    close(fd);
-    return okay;
+    return android::base::ReadFdToString(fd, content);
 }
 
 bool write_file(const char* path, const char* content) {
-    int fd = TEMP_FAILURE_RETRY(open(path, O_WRONLY|O_CREAT|O_NOFOLLOW|O_CLOEXEC, 0600));
+    android::base::unique_fd fd(TEMP_FAILURE_RETRY(
+        open(path, O_WRONLY | O_CREAT | O_NOFOLLOW | O_TRUNC | O_CLOEXEC, 0600)));
     if (fd == -1) {
         PLOG(ERROR) << "write_file: Unable to open '" << path << "'";
         return false;
@@ -195,7 +195,6 @@
     if (!success) {
         PLOG(ERROR) << "write_file: Unable to write to '" << path << "'";
     }
-    close(fd);
     return success;
 }
 
@@ -412,18 +411,9 @@
     return true;
 }
 
-void reboot(const char* destination) {
-    android_reboot(ANDROID_RB_RESTART2, 0, destination);
-    // We're init, so android_reboot will actually have been a syscall so there's nothing
-    // to wait for. If android_reboot returns, just abort so that the kernel will reboot
-    // itself when init dies.
-    PLOG(FATAL) << "reboot failed";
-    abort();
-}
-
 void panic() {
     LOG(ERROR) << "panic: rebooting to bootloader";
-    reboot("bootloader");
+    DoReboot(ANDROID_RB_RESTART2, "reboot", "bootloader", false);
 }
 
 std::ostream& operator<<(std::ostream& os, const Timer& t) {
diff --git a/init/util.h b/init/util.h
index 5c38dc3..81c64d7 100644
--- a/init/util.h
+++ b/init/util.h
@@ -78,7 +78,6 @@
 bool is_dir(const char* pathname);
 bool expand_props(const std::string& src, std::string* dst);
 
-void reboot(const char* destination) __attribute__((__noreturn__));
 void panic() __attribute__((__noreturn__));
 
 #endif
diff --git a/init/util_test.cpp b/init/util_test.cpp
index 24c75c4..4e82e76 100644
--- a/init/util_test.cpp
+++ b/init/util_test.cpp
@@ -17,9 +17,15 @@
 #include "util.h"
 
 #include <errno.h>
+#include <fcntl.h>
+
+#include <sys/stat.h>
 
 #include <gtest/gtest.h>
 
+#include <android-base/stringprintf.h>
+#include <android-base/test_utils.h>
+
 TEST(util, read_file_ENOENT) {
   std::string s("hello");
   errno = 0;
@@ -28,6 +34,35 @@
   EXPECT_EQ("", s); // s was cleared.
 }
 
+TEST(util, read_file_group_writeable) {
+    std::string s("hello");
+    TemporaryFile tf;
+    ASSERT_TRUE(tf.fd != -1);
+    EXPECT_TRUE(write_file(tf.path, s.c_str())) << strerror(errno);
+    EXPECT_NE(-1, fchmodat(AT_FDCWD, tf.path, 0620, AT_SYMLINK_NOFOLLOW)) << strerror(errno);
+    EXPECT_FALSE(read_file(tf.path, &s)) << strerror(errno);
+    EXPECT_EQ("", s);  // s was cleared.
+}
+
+TEST(util, read_file_world_writeable) {
+    std::string s("hello");
+    TemporaryFile tf;
+    ASSERT_TRUE(tf.fd != -1);
+    EXPECT_TRUE(write_file(tf.path, s.c_str())) << strerror(errno);
+    EXPECT_NE(-1, fchmodat(AT_FDCWD, tf.path, 0602, AT_SYMLINK_NOFOLLOW)) << strerror(errno);
+    EXPECT_FALSE(read_file(tf.path, &s)) << strerror(errno);
+    EXPECT_EQ("", s);  // s was cleared.
+}
+
+TEST(util, read_file_symbol_link) {
+    std::string s("hello");
+    errno = 0;
+    // lrwxrwxrwx 1 root root 13 1970-01-01 00:00 charger -> /sbin/healthd
+    EXPECT_FALSE(read_file("/charger", &s));
+    EXPECT_EQ(ELOOP, errno);
+    EXPECT_EQ("", s);  // s was cleared.
+}
+
 TEST(util, read_file_success) {
   std::string s("hello");
   EXPECT_TRUE(read_file("/proc/version", &s));
@@ -37,6 +72,42 @@
   EXPECT_STREQ("Linux", s.c_str());
 }
 
+TEST(util, write_file_not_exist) {
+    std::string s("hello");
+    std::string s2("hello");
+    TemporaryDir test_dir;
+    std::string path = android::base::StringPrintf("%s/does-not-exist", test_dir.path);
+    EXPECT_TRUE(write_file(path.c_str(), s.c_str()));
+    EXPECT_TRUE(read_file(path.c_str(), &s2));
+    EXPECT_EQ(s, s2);
+    struct stat sb;
+    int fd = open(path.c_str(), O_RDONLY | O_NOFOLLOW | O_CLOEXEC);
+    EXPECT_NE(-1, fd);
+    EXPECT_EQ(0, fstat(fd, &sb));
+    EXPECT_NE(0u, sb.st_mode & S_IRUSR);
+    EXPECT_NE(0u, sb.st_mode & S_IWUSR);
+    EXPECT_EQ(0u, sb.st_mode & S_IXUSR);
+    EXPECT_EQ(0u, sb.st_mode & S_IRGRP);
+    EXPECT_EQ(0u, sb.st_mode & S_IWGRP);
+    EXPECT_EQ(0u, sb.st_mode & S_IXGRP);
+    EXPECT_EQ(0u, sb.st_mode & S_IROTH);
+    EXPECT_EQ(0u, sb.st_mode & S_IWOTH);
+    EXPECT_EQ(0u, sb.st_mode & S_IXOTH);
+    EXPECT_EQ(0, unlink(path.c_str()));
+}
+
+TEST(util, write_file_exist) {
+    std::string s2("");
+    TemporaryFile tf;
+    ASSERT_TRUE(tf.fd != -1);
+    EXPECT_TRUE(write_file(tf.path, "1hello1")) << strerror(errno);
+    EXPECT_TRUE(read_file(tf.path, &s2));
+    EXPECT_STREQ("1hello1", s2.c_str());
+    EXPECT_TRUE(write_file(tf.path, "2hello2"));
+    EXPECT_TRUE(read_file(tf.path, &s2));
+    EXPECT_STREQ("2hello2", s2.c_str());
+}
+
 TEST(util, decode_uid) {
   EXPECT_EQ(0U, decode_uid("root"));
   EXPECT_EQ(UINT_MAX, decode_uid("toot"));
diff --git a/libbacktrace/Android.bp b/libbacktrace/Android.bp
index 0e7c6f3..8f74a1a 100644
--- a/libbacktrace/Android.bp
+++ b/libbacktrace/Android.bp
@@ -114,7 +114,7 @@
         none: true,
     },
     cflags: ["-O0"],
-    srcs: ["backtrace_testlib.c"],
+    srcs: ["backtrace_testlib.cpp"],
 
     target: {
         linux: {
diff --git a/libbacktrace/Backtrace.cpp b/libbacktrace/Backtrace.cpp
index 0d2e11b..3545661 100644
--- a/libbacktrace/Backtrace.cpp
+++ b/libbacktrace/Backtrace.cpp
@@ -52,7 +52,16 @@
   }
 }
 
-std::string Backtrace::GetFunctionName(uintptr_t pc, uintptr_t* offset) {
+std::string Backtrace::GetFunctionName(uintptr_t pc, uintptr_t* offset, const backtrace_map_t* map) {
+  backtrace_map_t map_value;
+  if (map == nullptr) {
+    FillInMap(pc, &map_value);
+    map = &map_value;
+  }
+  // If no map is found, or this map is backed by a device, then return nothing.
+  if (map->start == 0 || (map->flags & PROT_DEVICE_MAP)) {
+    return "";
+  }
   std::string func_name = GetFunctionNameRaw(pc, offset);
   return func_name;
 }
@@ -146,7 +155,7 @@
   case BACKTRACE_UNWIND_ERROR_THREAD_DOESNT_EXIST:
     return "Thread doesn't exist";
   case BACKTRACE_UNWIND_ERROR_THREAD_TIMEOUT:
-    return "Thread has not repsonded to signal in time";
+    return "Thread has not responded to signal in time";
   case BACKTRACE_UNWIND_ERROR_UNSUPPORTED_OPERATION:
     return "Attempt to use an unsupported feature";
   case BACKTRACE_UNWIND_ERROR_NO_CONTEXT:
diff --git a/libbacktrace/BacktraceCurrent.h b/libbacktrace/BacktraceCurrent.h
index 8aad36d..072ffd2 100644
--- a/libbacktrace/BacktraceCurrent.h
+++ b/libbacktrace/BacktraceCurrent.h
@@ -36,7 +36,7 @@
 class BacktraceMap;
 
 class BacktraceCurrent : public Backtrace {
-public:
+ public:
   BacktraceCurrent(pid_t pid, pid_t tid, BacktraceMap* map) : Backtrace(pid, tid, map) {}
   virtual ~BacktraceCurrent() {}
 
@@ -46,10 +46,10 @@
 
   bool Unwind(size_t num_ignore_frames, ucontext_t* ucontext) override;
 
-protected:
+ protected:
   bool DiscardFrame(const backtrace_frame_data_t& frame);
 
-private:
+ private:
   bool UnwindThread(size_t num_ignore_frames);
 
   virtual bool UnwindFromContext(size_t num_ignore_frames, ucontext_t* ucontext) = 0;
diff --git a/libbacktrace/BacktracePtrace.h b/libbacktrace/BacktracePtrace.h
index 1d49811..760817b 100644
--- a/libbacktrace/BacktracePtrace.h
+++ b/libbacktrace/BacktracePtrace.h
@@ -25,7 +25,7 @@
 class BacktraceMap;
 
 class BacktracePtrace : public Backtrace {
-public:
+ public:
   BacktracePtrace(pid_t pid, pid_t tid, BacktraceMap* map) : Backtrace(pid, tid, map) {}
   virtual ~BacktracePtrace() {}
 
diff --git a/libbacktrace/ThreadEntry.h b/libbacktrace/ThreadEntry.h
index 11924a3..caa5497 100644
--- a/libbacktrace/ThreadEntry.h
+++ b/libbacktrace/ThreadEntry.h
@@ -22,7 +22,7 @@
 #include <ucontext.h>
 
 class ThreadEntry {
-public:
+ public:
   static ThreadEntry* Get(pid_t pid, pid_t tid, bool create = true);
 
   static void Remove(ThreadEntry* entry);
@@ -47,7 +47,7 @@
 
   inline ucontext_t* GetUcontext() { return &ucontext_; }
 
-private:
+ private:
   ThreadEntry(pid_t pid, pid_t tid);
   ~ThreadEntry();
 
diff --git a/libbacktrace/UnwindCurrent.cpp b/libbacktrace/UnwindCurrent.cpp
index 666c481..3c509e6 100644
--- a/libbacktrace/UnwindCurrent.cpp
+++ b/libbacktrace/UnwindCurrent.cpp
@@ -23,12 +23,23 @@
 #define UNW_LOCAL_ONLY
 #include <libunwind.h>
 
+#include <android-base/logging.h>
 #include <backtrace/Backtrace.h>
 
 #include "BacktraceLog.h"
 #include "UnwindCurrent.h"
 
 std::string UnwindCurrent::GetFunctionNameRaw(uintptr_t pc, uintptr_t* offset) {
+  if (!initialized_) {
+    // If init local is not called, then trying to get a function name will
+    // fail, so try to initialize first.
+    std::unique_ptr<unw_cursor_t> cursor(new unw_cursor_t);
+    if (unw_init_local(cursor.get(), &context_) < 0) {
+      return "";
+    }
+    initialized_ = true;
+  }
+
   *offset = 0;
   char buf[512];
   unw_word_t value;
@@ -85,6 +96,7 @@
     error_ = BACKTRACE_UNWIND_ERROR_SETUP_FAILED;
     return false;
   }
+  initialized_ = true;
 
   size_t num_frames = 0;
   do {
@@ -115,7 +127,7 @@
       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);
+        frame->func_name = GetFunctionName(frame->pc, &frame->func_offset, &frame->map);
         if (num_frames > 0) {
           // Set the stack size for the previous frame.
           backtrace_frame_data_t* prev = &frames_.at(num_frames-1);
@@ -124,8 +136,23 @@
         num_frames++;
       } else {
         num_ignore_frames--;
+        // Set the number of frames to zero to remove the frame added
+        // above. By definition, if we still have frames to ignore
+        // there should only be one frame in the vector.
+        CHECK(num_frames == 0);
+        frames_.resize(0);
       }
     }
+    // If the pc is in a device map, then don't try to step.
+    if (frame->map.flags & PROT_DEVICE_MAP) {
+      break;
+    }
+    // Verify the sp is not in a device map too.
+    backtrace_map_t map;
+    FillInMap(frame->sp, &map);
+    if (map.flags & PROT_DEVICE_MAP) {
+      break;
+    }
     ret = unw_step (cursor.get());
   } while (ret > 0 && num_frames < MAX_BACKTRACE_FRAMES);
 
diff --git a/libbacktrace/UnwindCurrent.h b/libbacktrace/UnwindCurrent.h
index 3023996..3656104 100644
--- a/libbacktrace/UnwindCurrent.h
+++ b/libbacktrace/UnwindCurrent.h
@@ -32,18 +32,20 @@
 #include <libunwind.h>
 
 class UnwindCurrent : public BacktraceCurrent {
-public:
+ public:
   UnwindCurrent(pid_t pid, pid_t tid, BacktraceMap* map) : BacktraceCurrent(pid, tid, map) {}
   virtual ~UnwindCurrent() {}
 
   std::string GetFunctionNameRaw(uintptr_t pc, uintptr_t* offset) override;
 
-private:
+ private:
   void GetUnwContextFromUcontext(const ucontext_t* ucontext);
 
   bool UnwindFromContext(size_t num_ignore_frames, ucontext_t* ucontext) override;
 
   unw_context_t context_;
+
+  bool initialized_ = false;
 };
 
 #endif // _LIBBACKTRACE_UNWIND_CURRENT_H
diff --git a/libbacktrace/UnwindMap.h b/libbacktrace/UnwindMap.h
index d5bec06..6ffdafd 100644
--- a/libbacktrace/UnwindMap.h
+++ b/libbacktrace/UnwindMap.h
@@ -28,28 +28,28 @@
 // libunwind.h first then this header.
 
 class UnwindMap : public BacktraceMap {
-public:
+ public:
   explicit UnwindMap(pid_t pid);
 
   unw_map_cursor_t* GetMapCursor() { return &map_cursor_; }
 
-protected:
+ protected:
   unw_map_cursor_t map_cursor_;
 };
 
 class UnwindMapRemote : public UnwindMap {
-public:
+ public:
   explicit UnwindMapRemote(pid_t pid);
   virtual ~UnwindMapRemote();
 
   bool Build() override;
 
-private:
+ private:
   bool GenerateMap();
 };
 
 class UnwindMapLocal : public UnwindMap {
-public:
+ public:
   UnwindMapLocal();
   virtual ~UnwindMapLocal();
 
@@ -60,7 +60,7 @@
   void LockIterator() override { pthread_rwlock_rdlock(&map_lock_); }
   void UnlockIterator() override { pthread_rwlock_unlock(&map_lock_); }
 
-private:
+ private:
   bool GenerateMap();
 
   bool map_created_;
diff --git a/libbacktrace/UnwindPtrace.cpp b/libbacktrace/UnwindPtrace.cpp
index 306d2ac..42ac1bc 100644
--- a/libbacktrace/UnwindPtrace.cpp
+++ b/libbacktrace/UnwindPtrace.cpp
@@ -37,6 +37,7 @@
     _UPT_destroy(upt_info_);
     upt_info_ = nullptr;
   }
+
   if (addr_space_) {
     // Remove the map from the address space before destroying it.
     // It will be freed in the UnwindMap destructor.
@@ -47,18 +48,14 @@
   }
 }
 
-bool UnwindPtrace::Unwind(size_t num_ignore_frames, ucontext_t* ucontext) {
-  if (GetMap() == nullptr) {
-    // Without a map object, we can't do anything.
-    error_ = BACKTRACE_UNWIND_ERROR_MAP_MISSING;
-    return false;
+bool UnwindPtrace::Init() {
+  if (upt_info_) {
+    return true;
   }
 
-  error_ = BACKTRACE_UNWIND_NO_ERROR;
-
-  if (ucontext) {
-    BACK_LOGW("Unwinding from a specified context not supported yet.");
-    error_ = BACKTRACE_UNWIND_ERROR_UNSUPPORTED_OPERATION;
+  if (addr_space_) {
+    // If somehow the addr_space_ gets initialized but upt_info_ doesn't,
+    // then that indicates there is some kind of failure.
     return false;
   }
 
@@ -79,6 +76,28 @@
     return false;
   }
 
+  return true;
+}
+
+bool UnwindPtrace::Unwind(size_t num_ignore_frames, ucontext_t* ucontext) {
+  if (GetMap() == nullptr) {
+    // Without a map object, we can't do anything.
+    error_ = BACKTRACE_UNWIND_ERROR_MAP_MISSING;
+    return false;
+  }
+
+  error_ = BACKTRACE_UNWIND_NO_ERROR;
+
+  if (ucontext) {
+    BACK_LOGW("Unwinding from a specified context not supported yet.");
+    error_ = BACKTRACE_UNWIND_ERROR_UNSUPPORTED_OPERATION;
+    return false;
+  }
+
+  if (!Init()) {
+    return false;
+  }
+
   unw_cursor_t cursor;
   int ret = unw_init_remote(&cursor, addr_space_, upt_info_);
   if (ret < 0) {
@@ -115,14 +134,30 @@
         prev->stack_size = frame->sp - prev->sp;
       }
 
-      frame->func_name = GetFunctionName(frame->pc, &frame->func_offset);
-
       FillInMap(frame->pc, &frame->map);
 
+      frame->func_name = GetFunctionName(frame->pc, &frame->func_offset, &frame->map);
+
       num_frames++;
+      // If the pc is in a device map, then don't try to step.
+      if (frame->map.flags & PROT_DEVICE_MAP) {
+        break;
+      }
     } else {
+      // If the pc is in a device map, then don't try to step.
+      backtrace_map_t map;
+      FillInMap(pc, &map);
+      if (map.flags & PROT_DEVICE_MAP) {
+        break;
+      }
       num_ignore_frames--;
     }
+    // Verify the sp is not in a device map.
+    backtrace_map_t map;
+    FillInMap(sp, &map);
+    if (map.flags & PROT_DEVICE_MAP) {
+      break;
+    }
     ret = unw_step (&cursor);
   } while (ret > 0 && num_frames < MAX_BACKTRACE_FRAMES);
 
@@ -130,6 +165,10 @@
 }
 
 std::string UnwindPtrace::GetFunctionNameRaw(uintptr_t pc, uintptr_t* offset) {
+  if (!Init()) {
+    return "";
+  }
+
   *offset = 0;
   char buf[512];
   unw_word_t value;
diff --git a/libbacktrace/UnwindPtrace.h b/libbacktrace/UnwindPtrace.h
index ab04abf..4688110 100644
--- a/libbacktrace/UnwindPtrace.h
+++ b/libbacktrace/UnwindPtrace.h
@@ -30,7 +30,7 @@
 #include "BacktracePtrace.h"
 
 class UnwindPtrace : public BacktracePtrace {
-public:
+ public:
   UnwindPtrace(pid_t pid, pid_t tid, BacktraceMap* map);
   virtual ~UnwindPtrace();
 
@@ -38,7 +38,9 @@
 
   std::string GetFunctionNameRaw(uintptr_t pc, uintptr_t* offset) override;
 
-private:
+ private:
+  bool Init();
+
   unw_addr_space_t addr_space_;
   struct UPT_info* upt_info_;
 };
diff --git a/libbacktrace/backtrace_test.cpp b/libbacktrace/backtrace_test.cpp
index e25c8e9..fb463b0 100644
--- a/libbacktrace/backtrace_test.cpp
+++ b/libbacktrace/backtrace_test.cpp
@@ -36,13 +36,16 @@
 #include <algorithm>
 #include <list>
 #include <memory>
+#include <ostream>
 #include <string>
 #include <vector>
 
 #include <backtrace/Backtrace.h>
 #include <backtrace/BacktraceMap.h>
 
+#include <android-base/macros.h>
 #include <android-base/stringprintf.h>
+#include <android-base/unique_fd.h>
 #include <cutils/atomic.h>
 #include <cutils/threads.h>
 
@@ -50,6 +53,7 @@
 
 // For the THREAD_SIGNAL definition.
 #include "BacktraceCurrent.h"
+#include "backtrace_testlib.h"
 #include "thread_utils.h"
 
 // Number of microseconds per milliseconds.
@@ -78,20 +82,13 @@
   int32_t done;
 };
 
-extern "C" {
-// Prototypes for functions in the test library.
-int test_level_one(int, int, int, int, void (*)(void*), void*);
-
-int test_recursive_call(int, void (*)(void*), void*);
-}
-
-uint64_t NanoTime() {
+static uint64_t NanoTime() {
   struct timespec t = { 0, 0 };
   clock_gettime(CLOCK_MONOTONIC, &t);
   return static_cast<uint64_t>(t.tv_sec * NS_PER_SEC + t.tv_nsec);
 }
 
-std::string DumpFrames(Backtrace* backtrace) {
+static std::string DumpFrames(Backtrace* backtrace) {
   if (backtrace->NumFrames() == 0) {
     return "   No frames to dump.\n";
   }
@@ -103,7 +100,7 @@
   return frame;
 }
 
-void WaitForStop(pid_t pid) {
+static void WaitForStop(pid_t pid) {
   uint64_t start = NanoTime();
 
   siginfo_t si;
@@ -116,7 +113,28 @@
   }
 }
 
-bool ReadyLevelBacktrace(Backtrace* backtrace) {
+static void CreateRemoteProcess(pid_t* pid) {
+  if ((*pid = fork()) == 0) {
+    while (true)
+      ;
+    _exit(0);
+  }
+  ASSERT_NE(-1, *pid);
+
+  ASSERT_TRUE(ptrace(PTRACE_ATTACH, *pid, 0, 0) == 0);
+
+  // Wait for the process to get to a stopping point.
+  WaitForStop(*pid);
+}
+
+static void FinishRemoteProcess(pid_t pid) {
+  ASSERT_TRUE(ptrace(PTRACE_DETACH, pid, 0, 0) == 0);
+
+  kill(pid, SIGKILL);
+  ASSERT_EQ(waitpid(pid, nullptr, 0), pid);
+}
+
+static bool ReadyLevelBacktrace(Backtrace* backtrace) {
   // See if test_level_four is in the backtrace.
   bool found = false;
   for (Backtrace::const_iterator it = backtrace->begin(); it != backtrace->end(); ++it) {
@@ -129,7 +147,7 @@
   return found;
 }
 
-void VerifyLevelDump(Backtrace* backtrace) {
+static void VerifyLevelDump(Backtrace* backtrace) {
   ASSERT_GT(backtrace->NumFrames(), static_cast<size_t>(0))
     << DumpFrames(backtrace);
   ASSERT_LT(backtrace->NumFrames(), static_cast<size_t>(MAX_BACKTRACE_FRAMES))
@@ -157,7 +175,7 @@
     << DumpFrames(backtrace);
 }
 
-void VerifyLevelBacktrace(void*) {
+static void VerifyLevelBacktrace(void*) {
   std::unique_ptr<Backtrace> backtrace(
       Backtrace::Create(BACKTRACE_CURRENT_PROCESS, BACKTRACE_CURRENT_THREAD));
   ASSERT_TRUE(backtrace.get() != nullptr);
@@ -167,11 +185,11 @@
   VerifyLevelDump(backtrace.get());
 }
 
-bool ReadyMaxBacktrace(Backtrace* backtrace) {
+static bool ReadyMaxBacktrace(Backtrace* backtrace) {
   return (backtrace->NumFrames() == MAX_BACKTRACE_FRAMES);
 }
 
-void VerifyMaxDump(Backtrace* backtrace) {
+static void VerifyMaxDump(Backtrace* backtrace) {
   ASSERT_EQ(backtrace->NumFrames(), static_cast<size_t>(MAX_BACKTRACE_FRAMES))
     << DumpFrames(backtrace);
   // Verify that the last frame is our recursive call.
@@ -179,7 +197,7 @@
     << DumpFrames(backtrace);
 }
 
-void VerifyMaxBacktrace(void*) {
+static void VerifyMaxBacktrace(void*) {
   std::unique_ptr<Backtrace> backtrace(
       Backtrace::Create(BACKTRACE_CURRENT_PROCESS, BACKTRACE_CURRENT_THREAD));
   ASSERT_TRUE(backtrace.get() != nullptr);
@@ -189,7 +207,7 @@
   VerifyMaxDump(backtrace.get());
 }
 
-void ThreadSetState(void* data) {
+static void ThreadSetState(void* data) {
   thread_t* thread = reinterpret_cast<thread_t*>(data);
   android_atomic_acquire_store(1, &thread->state);
   volatile int i = 0;
@@ -198,16 +216,7 @@
   }
 }
 
-void VerifyThreadTest(pid_t tid, void (*VerifyFunc)(Backtrace*)) {
-  std::unique_ptr<Backtrace> backtrace(Backtrace::Create(getpid(), tid));
-  ASSERT_TRUE(backtrace.get() != nullptr);
-  ASSERT_TRUE(backtrace->Unwind(0));
-  ASSERT_EQ(BACKTRACE_UNWIND_NO_ERROR, backtrace->GetError());
-
-  VerifyFunc(backtrace.get());
-}
-
-bool WaitForNonZero(int32_t* value, uint64_t seconds) {
+static bool WaitForNonZero(int32_t* value, uint64_t seconds) {
   uint64_t start = NanoTime();
   do {
     if (android_atomic_acquire_load(value)) {
@@ -240,9 +249,8 @@
   ASSERT_NE(test_level_one(1, 2, 3, 4, VerifyLevelBacktrace, nullptr), 0);
 }
 
-void VerifyIgnoreFrames(
-    Backtrace* bt_all, Backtrace* bt_ign1,
-    Backtrace* bt_ign2, const char* cur_proc) {
+static void VerifyIgnoreFrames(Backtrace* bt_all, Backtrace* bt_ign1, Backtrace* bt_ign2,
+                               const char* cur_proc) {
   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)
@@ -266,7 +274,7 @@
   }
 }
 
-void VerifyLevelIgnoreFrames(void*) {
+static void VerifyLevelIgnoreFrames(void*) {
   std::unique_ptr<Backtrace> all(
       Backtrace::Create(BACKTRACE_CURRENT_PROCESS, BACKTRACE_CURRENT_THREAD));
   ASSERT_TRUE(all.get() != nullptr);
@@ -296,9 +304,8 @@
   ASSERT_NE(test_recursive_call(MAX_BACKTRACE_FRAMES+10, VerifyMaxBacktrace, nullptr), 0);
 }
 
-void VerifyProcTest(pid_t pid, pid_t tid, bool share_map,
-                    bool (*ReadyFunc)(Backtrace*),
-                    void (*VerifyFunc)(Backtrace*)) {
+static void VerifyProcTest(pid_t pid, pid_t tid, bool share_map, bool (*ReadyFunc)(Backtrace*),
+                           void (*VerifyFunc)(Backtrace*)) {
   pid_t ptrace_tid;
   if (tid < 0) {
     ptrace_tid = pid;
@@ -376,7 +383,7 @@
   ASSERT_EQ(waitpid(pid, &status, 0), pid);
 }
 
-void VerifyProcessIgnoreFrames(Backtrace* bt_all) {
+static void VerifyProcessIgnoreFrames(Backtrace* bt_all) {
   std::unique_ptr<Backtrace> ign1(Backtrace::Create(bt_all->Pid(), BACKTRACE_CURRENT_THREAD));
   ASSERT_TRUE(ign1.get() != nullptr);
   ASSERT_TRUE(ign1->Unwind(1));
@@ -404,12 +411,12 @@
 }
 
 // Create a process with multiple threads and dump all of the threads.
-void* PtraceThreadLevelRun(void*) {
+static void* PtraceThreadLevelRun(void*) {
   EXPECT_NE(test_level_one(1, 2, 3, 4, nullptr, nullptr), 0);
   return nullptr;
 }
 
-void GetThreads(pid_t pid, std::vector<pid_t>* threads) {
+static void GetThreads(pid_t pid, std::vector<pid_t>* threads) {
   // Get the list of tasks.
   char task_path[128];
   snprintf(task_path, sizeof(task_path), "/proc/%d/task", pid);
@@ -461,11 +468,8 @@
     }
     VerifyProcTest(pid, *it, false, ReadyLevelBacktrace, VerifyLevelDump);
   }
-  ASSERT_TRUE(ptrace(PTRACE_DETACH, pid, 0, 0) == 0);
 
-  kill(pid, SIGKILL);
-  int status;
-  ASSERT_EQ(waitpid(pid, &status, 0), pid);
+  FinishRemoteProcess(pid);
 }
 
 void VerifyLevelThread(void*) {
@@ -481,7 +485,7 @@
   ASSERT_NE(test_level_one(1, 2, 3, 4, VerifyLevelThread, nullptr), 0);
 }
 
-void VerifyMaxThread(void*) {
+static void VerifyMaxThread(void*) {
   std::unique_ptr<Backtrace> backtrace(Backtrace::Create(getpid(), gettid()));
   ASSERT_TRUE(backtrace.get() != nullptr);
   ASSERT_TRUE(backtrace->Unwind(0));
@@ -494,7 +498,7 @@
   ASSERT_NE(test_recursive_call(MAX_BACKTRACE_FRAMES+10, VerifyMaxThread, nullptr), 0);
 }
 
-void* ThreadLevelRun(void* data) {
+static void* ThreadLevelRun(void* data) {
   thread_t* thread = reinterpret_cast<thread_t*>(data);
 
   thread->tid = gettid();
@@ -585,7 +589,7 @@
   android_atomic_acquire_store(0, &thread_data.state);
 }
 
-void* ThreadMaxRun(void* data) {
+static void* ThreadMaxRun(void* data) {
   thread_t* thread = reinterpret_cast<thread_t*>(data);
 
   thread->tid = gettid();
@@ -616,7 +620,7 @@
   android_atomic_acquire_store(0, &thread_data.state);
 }
 
-void* ThreadDump(void* data) {
+static void* ThreadDump(void* data) {
   dump_thread_t* dump = reinterpret_cast<dump_thread_t*>(data);
   while (true) {
     if (android_atomic_acquire_load(dump->now)) {
@@ -873,11 +877,9 @@
   uintptr_t end;
 };
 
-bool map_sort(map_test_t i, map_test_t j) {
-  return i.start < j.start;
-}
+static bool map_sort(map_test_t i, map_test_t j) { return i.start < j.start; }
 
-void VerifyMap(pid_t pid) {
+static void VerifyMap(pid_t pid) {
   char buffer[4096];
   snprintf(buffer, sizeof(buffer), "/proc/%d/maps", pid);
 
@@ -908,29 +910,15 @@
 
 TEST(libbacktrace, verify_map_remote) {
   pid_t pid;
-
-  if ((pid = fork()) == 0) {
-    while (true) {
-    }
-    _exit(0);
-  }
-  ASSERT_LT(0, pid);
-
-  ASSERT_TRUE(ptrace(PTRACE_ATTACH, pid, 0, 0) == 0);
-
-  // Wait for the process to get to a stopping point.
-  WaitForStop(pid);
+  CreateRemoteProcess(&pid);
 
   // The maps should match exactly since the forked process has been paused.
   VerifyMap(pid);
 
-  ASSERT_TRUE(ptrace(PTRACE_DETACH, pid, 0, 0) == 0);
-
-  kill(pid, SIGKILL);
-  ASSERT_EQ(waitpid(pid, nullptr, 0), pid);
+  FinishRemoteProcess(pid);
 }
 
-void InitMemory(uint8_t* memory, size_t bytes) {
+static void InitMemory(uint8_t* memory, size_t bytes) {
   for (size_t i = 0; i < bytes; i++) {
     memory[i] = i;
     if (memory[i] == '\0') {
@@ -941,7 +929,7 @@
   }
 }
 
-void* ThreadReadTest(void* data) {
+static void* ThreadReadTest(void* data) {
   thread_t* thread_data = reinterpret_cast<thread_t*>(data);
 
   thread_data->tid = gettid();
@@ -982,7 +970,7 @@
   return nullptr;
 }
 
-void RunReadTest(Backtrace* backtrace, uintptr_t read_addr) {
+static void RunReadTest(Backtrace* backtrace, uintptr_t read_addr) {
   size_t pagesize = static_cast<size_t>(sysconf(_SC_PAGE_SIZE));
 
   // Create a page of data to use to do quick compares.
@@ -1043,7 +1031,7 @@
 volatile uintptr_t g_ready = 0;
 volatile uintptr_t g_addr = 0;
 
-void ForkedReadTest() {
+static void ForkedReadTest() {
   // Create two map pages.
   size_t pagesize = static_cast<size_t>(sysconf(_SC_PAGE_SIZE));
   uint8_t* memory;
@@ -1117,7 +1105,7 @@
   ASSERT_TRUE(test_executed);
 }
 
-void VerifyFunctionsFound(const std::vector<std::string>& found_functions) {
+static void VerifyFunctionsFound(const std::vector<std::string>& found_functions) {
   // We expect to find these functions in libbacktrace_test. If we don't
   // find them, that's a bug in the memory read handling code in libunwind.
   std::list<std::string> expected_functions;
@@ -1137,7 +1125,7 @@
   ASSERT_TRUE(expected_functions.empty()) << "Not all functions found in shared library.";
 }
 
-const char* CopySharedLibrary() {
+static const char* CopySharedLibrary() {
 #if defined(__LP64__)
   const char* lib_name = "lib64";
 #else
@@ -1293,7 +1281,7 @@
   VerifyFunctionsFound(found_functions);
 }
 
-bool FindFuncFrameInBacktrace(Backtrace* backtrace, uintptr_t test_func, size_t* frame_num) {
+static bool FindFuncFrameInBacktrace(Backtrace* backtrace, uintptr_t test_func, size_t* frame_num) {
   backtrace_map_t map;
   backtrace->FillInMap(test_func, &map);
   if (!BacktraceMap::IsValid(map)) {
@@ -1312,7 +1300,7 @@
   return false;
 }
 
-void VerifyUnreadableElfFrame(Backtrace* backtrace, uintptr_t test_func, size_t frame_num) {
+static void VerifyUnreadableElfFrame(Backtrace* backtrace, uintptr_t test_func, size_t frame_num) {
   ASSERT_LT(backtrace->NumFrames(), static_cast<size_t>(MAX_BACKTRACE_FRAMES))
     << DumpFrames(backtrace);
 
@@ -1324,7 +1312,7 @@
   ASSERT_LT(diff, 200U) << DumpFrames(backtrace);
 }
 
-void VerifyUnreadableElfBacktrace(uintptr_t test_func) {
+static void VerifyUnreadableElfBacktrace(uintptr_t test_func) {
   std::unique_ptr<Backtrace> backtrace(Backtrace::Create(BACKTRACE_CURRENT_PROCESS,
                                                          BACKTRACE_CURRENT_THREAD));
   ASSERT_TRUE(backtrace.get() != nullptr);
@@ -1418,12 +1406,347 @@
   ASSERT_EQ(BACKTRACE_UNWIND_ERROR_THREAD_DOESNT_EXIST, backtrace->GetError());
 }
 
+TEST(libbacktrace, local_get_function_name_before_unwind) {
+  std::unique_ptr<Backtrace> backtrace(
+      Backtrace::Create(BACKTRACE_CURRENT_PROCESS, BACKTRACE_CURRENT_THREAD));
+  ASSERT_TRUE(backtrace.get() != nullptr);
+
+  // Verify that trying to get a function name before doing an unwind works.
+  uintptr_t cur_func_offset = reinterpret_cast<uintptr_t>(&test_level_one) + 1;
+  size_t offset;
+  ASSERT_NE(std::string(""), backtrace->GetFunctionName(cur_func_offset, &offset));
+}
+
+TEST(libbacktrace, remote_get_function_name_before_unwind) {
+  pid_t pid;
+  CreateRemoteProcess(&pid);
+
+  // Now create an unwind object.
+  std::unique_ptr<Backtrace> backtrace(Backtrace::Create(pid, pid));
+
+  // Verify that trying to get a function name before doing an unwind works.
+  uintptr_t cur_func_offset = reinterpret_cast<uintptr_t>(&test_level_one) + 1;
+  size_t offset;
+  ASSERT_NE(std::string(""), backtrace->GetFunctionName(cur_func_offset, &offset));
+
+  FinishRemoteProcess(pid);
+}
+
+static void SetUcontextSp(uintptr_t sp, ucontext_t* ucontext) {
+#if defined(__arm__)
+  ucontext->uc_mcontext.arm_sp = sp;
+#elif defined(__aarch64__)
+  ucontext->uc_mcontext.sp = sp;
+#elif defined(__i386__)
+  ucontext->uc_mcontext.gregs[REG_ESP] = sp;
+#elif defined(__x86_64__)
+  ucontext->uc_mcontext.gregs[REG_RSP] = sp;
+#else
+  UNUSED(sp);
+  UNUSED(ucontext);
+  ASSERT_TRUE(false) << "Unsupported architecture";
+#endif
+}
+
+static void SetUcontextPc(uintptr_t pc, ucontext_t* ucontext) {
+#if defined(__arm__)
+  ucontext->uc_mcontext.arm_pc = pc;
+#elif defined(__aarch64__)
+  ucontext->uc_mcontext.pc = pc;
+#elif defined(__i386__)
+  ucontext->uc_mcontext.gregs[REG_EIP] = pc;
+#elif defined(__x86_64__)
+  ucontext->uc_mcontext.gregs[REG_RIP] = pc;
+#else
+  UNUSED(pc);
+  UNUSED(ucontext);
+  ASSERT_TRUE(false) << "Unsupported architecture";
+#endif
+}
+
+static void SetUcontextLr(uintptr_t lr, ucontext_t* ucontext) {
+#if defined(__arm__)
+  ucontext->uc_mcontext.arm_lr = lr;
+#elif defined(__aarch64__)
+  ucontext->uc_mcontext.regs[30] = lr;
+#elif defined(__i386__)
+  // The lr is on the stack.
+  ASSERT_TRUE(lr != 0);
+  ASSERT_TRUE(ucontext != nullptr);
+#elif defined(__x86_64__)
+  // The lr is on the stack.
+  ASSERT_TRUE(lr != 0);
+  ASSERT_TRUE(ucontext != nullptr);
+#else
+  UNUSED(lr);
+  UNUSED(ucontext);
+  ASSERT_TRUE(false) << "Unsupported architecture";
+#endif
+}
+
+static constexpr size_t DEVICE_MAP_SIZE = 1024;
+
+static void SetupDeviceMap(void** device_map) {
+  // Make sure that anything in a device map will result in fails
+  // to read.
+  android::base::unique_fd device_fd(open("/dev/zero", O_RDONLY | O_CLOEXEC));
+
+  *device_map = mmap(nullptr, 1024, PROT_READ, MAP_PRIVATE, device_fd, 0);
+  ASSERT_TRUE(*device_map != MAP_FAILED);
+
+  // Make sure the map is readable.
+  ASSERT_EQ(0, reinterpret_cast<int*>(*device_map)[0]);
+}
+
+static void UnwindFromDevice(Backtrace* backtrace, void* device_map) {
+  uintptr_t device_map_uint = reinterpret_cast<uintptr_t>(device_map);
+
+  backtrace_map_t map;
+  backtrace->FillInMap(device_map_uint, &map);
+  // Verify the flag is set.
+  ASSERT_EQ(PROT_DEVICE_MAP, map.flags & PROT_DEVICE_MAP);
+
+  // Quick sanity checks.
+  size_t offset;
+  ASSERT_EQ(std::string(""), backtrace->GetFunctionName(device_map_uint, &offset));
+  ASSERT_EQ(std::string(""), backtrace->GetFunctionName(device_map_uint, &offset, &map));
+  ASSERT_EQ(std::string(""), backtrace->GetFunctionName(0, &offset));
+
+  uintptr_t cur_func_offset = reinterpret_cast<uintptr_t>(&test_level_one) + 1;
+  // Now verify the device map flag actually causes the function name to be empty.
+  backtrace->FillInMap(cur_func_offset, &map);
+  ASSERT_TRUE((map.flags & PROT_DEVICE_MAP) == 0);
+  ASSERT_NE(std::string(""), backtrace->GetFunctionName(cur_func_offset, &offset, &map));
+  map.flags |= PROT_DEVICE_MAP;
+  ASSERT_EQ(std::string(""), backtrace->GetFunctionName(cur_func_offset, &offset, &map));
+
+  ucontext_t ucontext;
+
+  // Create a context that has the pc in the device map, but the sp
+  // in a non-device map.
+  memset(&ucontext, 0, sizeof(ucontext));
+  SetUcontextSp(reinterpret_cast<uintptr_t>(&ucontext), &ucontext);
+  SetUcontextPc(device_map_uint, &ucontext);
+  SetUcontextLr(cur_func_offset, &ucontext);
+
+  ASSERT_TRUE(backtrace->Unwind(0, &ucontext));
+
+  // The buffer should only be a single element.
+  ASSERT_EQ(1U, backtrace->NumFrames());
+  const backtrace_frame_data_t* frame = backtrace->GetFrame(0);
+  ASSERT_EQ(device_map_uint, frame->pc);
+  ASSERT_EQ(reinterpret_cast<uintptr_t>(&ucontext), frame->sp);
+
+  // Check what happens when skipping the first frame.
+  ASSERT_TRUE(backtrace->Unwind(1, &ucontext));
+  ASSERT_EQ(0U, backtrace->NumFrames());
+
+  // Create a context that has the sp in the device map, but the pc
+  // in a non-device map.
+  memset(&ucontext, 0, sizeof(ucontext));
+  SetUcontextSp(device_map_uint, &ucontext);
+  SetUcontextPc(cur_func_offset, &ucontext);
+  SetUcontextLr(cur_func_offset, &ucontext);
+
+  ASSERT_TRUE(backtrace->Unwind(0, &ucontext));
+
+  // The buffer should only be a single element.
+  ASSERT_EQ(1U, backtrace->NumFrames());
+  frame = backtrace->GetFrame(0);
+  ASSERT_EQ(cur_func_offset, frame->pc);
+  ASSERT_EQ(device_map_uint, frame->sp);
+
+  // Check what happens when skipping the first frame.
+  ASSERT_TRUE(backtrace->Unwind(1, &ucontext));
+  ASSERT_EQ(0U, backtrace->NumFrames());
+}
+
+TEST(libbacktrace, unwind_disallow_device_map_local) {
+  void* device_map;
+  SetupDeviceMap(&device_map);
+
+  // Now create an unwind object.
+  std::unique_ptr<Backtrace> backtrace(
+      Backtrace::Create(BACKTRACE_CURRENT_PROCESS, BACKTRACE_CURRENT_THREAD));
+  ASSERT_TRUE(backtrace);
+
+  UnwindFromDevice(backtrace.get(), device_map);
+
+  munmap(device_map, DEVICE_MAP_SIZE);
+}
+
+TEST(libbacktrace, unwind_disallow_device_map_remote) {
+  void* device_map;
+  SetupDeviceMap(&device_map);
+
+  // Fork a process to do a remote backtrace.
+  pid_t pid;
+  CreateRemoteProcess(&pid);
+
+  // Now create an unwind object.
+  std::unique_ptr<Backtrace> backtrace(Backtrace::Create(pid, pid));
+
+  // TODO: Currently unwind from context doesn't work on remote
+  // unwind. Keep this test because the new unwinder should support
+  // this eventually, or we can delete this test.
+  // properly with unwind from context.
+  // UnwindFromDevice(backtrace.get(), device_map);
+
+  FinishRemoteProcess(pid);
+
+  munmap(device_map, DEVICE_MAP_SIZE);
+}
+
+class ScopedSignalHandler {
+ public:
+  ScopedSignalHandler(int signal_number, void (*handler)(int)) : signal_number_(signal_number) {
+    memset(&action_, 0, sizeof(action_));
+    action_.sa_handler = handler;
+    sigaction(signal_number_, &action_, &old_action_);
+  }
+
+  ScopedSignalHandler(int signal_number, void (*action)(int, siginfo_t*, void*))
+      : signal_number_(signal_number) {
+    memset(&action_, 0, sizeof(action_));
+    action_.sa_flags = SA_SIGINFO;
+    action_.sa_sigaction = action;
+    sigaction(signal_number_, &action_, &old_action_);
+  }
+
+  ~ScopedSignalHandler() { sigaction(signal_number_, &old_action_, nullptr); }
+
+ private:
+  struct sigaction action_;
+  struct sigaction old_action_;
+  const int signal_number_;
+};
+
+static void SetValueAndLoop(void* data) {
+  volatile int* value = reinterpret_cast<volatile int*>(data);
+
+  *value = 1;
+  for (volatile int i = 0;; i++)
+    ;
+}
+
+static void UnwindThroughSignal(bool use_action) {
+  volatile int value = 0;
+  pid_t pid;
+  if ((pid = fork()) == 0) {
+    if (use_action) {
+      ScopedSignalHandler ssh(SIGUSR1, test_signal_action);
+
+      test_level_one(1, 2, 3, 4, SetValueAndLoop, const_cast<int*>(&value));
+    } else {
+      ScopedSignalHandler ssh(SIGUSR1, test_signal_handler);
+
+      test_level_one(1, 2, 3, 4, SetValueAndLoop, const_cast<int*>(&value));
+    }
+  }
+  ASSERT_NE(-1, pid);
+
+  int read_value = 0;
+  uint64_t start = NanoTime();
+  while (read_value == 0) {
+    usleep(1000);
+
+    // Loop until the remote function gets into the final function.
+    ASSERT_TRUE(ptrace(PTRACE_ATTACH, pid, 0, 0) == 0);
+
+    WaitForStop(pid);
+
+    std::unique_ptr<Backtrace> backtrace(Backtrace::Create(pid, pid));
+
+    size_t bytes_read = backtrace->Read(reinterpret_cast<uintptr_t>(const_cast<int*>(&value)),
+                                        reinterpret_cast<uint8_t*>(&read_value), sizeof(read_value));
+    ASSERT_EQ(sizeof(read_value), bytes_read);
+
+    ASSERT_TRUE(ptrace(PTRACE_DETACH, pid, 0, 0) == 0);
+
+    ASSERT_TRUE(NanoTime() - start < 5 * NS_PER_SEC)
+        << "Remote process did not execute far enough in 5 seconds.";
+  }
+
+  // Now need to send a signal to the remote process.
+  kill(pid, SIGUSR1);
+
+  // Wait for the process to get to the signal handler loop.
+  Backtrace::const_iterator frame_iter;
+  start = NanoTime();
+  std::unique_ptr<Backtrace> backtrace;
+  while (true) {
+    usleep(1000);
+
+    ASSERT_TRUE(ptrace(PTRACE_ATTACH, pid, 0, 0) == 0);
+
+    WaitForStop(pid);
+
+    backtrace.reset(Backtrace::Create(pid, pid));
+    ASSERT_TRUE(backtrace->Unwind(0));
+    bool found = false;
+    for (frame_iter = backtrace->begin(); frame_iter != backtrace->end(); ++frame_iter) {
+      if (frame_iter->func_name == "test_loop_forever") {
+        ++frame_iter;
+        found = true;
+        break;
+      }
+    }
+    if (found) {
+      break;
+    }
+
+    ASSERT_TRUE(ptrace(PTRACE_DETACH, pid, 0, 0) == 0);
+
+    ASSERT_TRUE(NanoTime() - start < 5 * NS_PER_SEC)
+        << "Remote process did not get in signal handler in 5 seconds." << std::endl
+        << DumpFrames(backtrace.get());
+  }
+
+  std::vector<std::string> names;
+  // Loop through the frames, and save the function names.
+  size_t frame = 0;
+  for (; frame_iter != backtrace->end(); ++frame_iter) {
+    if (frame_iter->func_name == "test_level_four") {
+      frame = names.size() + 1;
+    }
+    names.push_back(frame_iter->func_name);
+  }
+  ASSERT_NE(0U, frame) << "Unable to find test_level_four in backtrace" << std::endl
+                       << DumpFrames(backtrace.get());
+
+  // The expected order of the frames:
+  //   test_loop_forever
+  //   test_signal_handler|test_signal_action
+  //   <OPTIONAL_FRAME> May or may not exist.
+  //   SetValueAndLoop (but the function name might be empty)
+  //   test_level_four
+  //   test_level_three
+  //   test_level_two
+  //   test_level_one
+  ASSERT_LE(frame + 2, names.size()) << DumpFrames(backtrace.get());
+  ASSERT_LE(2U, frame) << DumpFrames(backtrace.get());
+  if (use_action) {
+    ASSERT_EQ("test_signal_action", names[0]) << DumpFrames(backtrace.get());
+  } else {
+    ASSERT_EQ("test_signal_handler", names[0]) << DumpFrames(backtrace.get());
+  }
+  ASSERT_EQ("test_level_three", names[frame]) << DumpFrames(backtrace.get());
+  ASSERT_EQ("test_level_two", names[frame + 1]) << DumpFrames(backtrace.get());
+  ASSERT_EQ("test_level_one", names[frame + 2]) << DumpFrames(backtrace.get());
+
+  FinishRemoteProcess(pid);
+}
+
+TEST(libbacktrace, unwind_remote_through_signal_using_handler) { UnwindThroughSignal(false); }
+
+TEST(libbacktrace, unwind_remote_through_signal_using_action) { UnwindThroughSignal(true); }
+
 #if defined(ENABLE_PSS_TESTS)
 #include "GetPss.h"
 
 #define MAX_LEAK_BYTES (32*1024UL)
 
-void CheckForLeak(pid_t pid, pid_t tid) {
+static void CheckForLeak(pid_t pid, pid_t tid) {
   // Do a few runs to get the PSS stable.
   for (size_t i = 0; i < 100; i++) {
     Backtrace* backtrace = Backtrace::Create(pid, tid);
@@ -1472,24 +1795,10 @@
 
 TEST(libbacktrace, check_for_leak_remote) {
   pid_t pid;
-
-  if ((pid = fork()) == 0) {
-    while (true) {
-    }
-    _exit(0);
-  }
-  ASSERT_LT(0, pid);
-
-  ASSERT_TRUE(ptrace(PTRACE_ATTACH, pid, 0, 0) == 0);
-
-  // Wait for the process to get to a stopping point.
-  WaitForStop(pid);
+  CreateRemoteProcess(&pid);
 
   CheckForLeak(pid, BACKTRACE_CURRENT_THREAD);
 
-  ASSERT_TRUE(ptrace(PTRACE_DETACH, pid, 0, 0) == 0);
-
-  kill(pid, SIGKILL);
-  ASSERT_EQ(waitpid(pid, nullptr, 0), pid);
+  FinishRemoteProcess(pid);
 }
 #endif
diff --git a/libbacktrace/backtrace_testlib.c b/libbacktrace/backtrace_testlib.cpp
similarity index 61%
rename from libbacktrace/backtrace_testlib.c
rename to libbacktrace/backtrace_testlib.cpp
index 6f6b535..3081d64 100644
--- a/libbacktrace/backtrace_testlib.c
+++ b/libbacktrace/backtrace_testlib.cpp
@@ -15,32 +15,42 @@
  */
 
 #include <libunwind.h>
+#include <signal.h>
 #include <stdio.h>
 
-int test_level_four(int one, int two, int three, int four,
-                    void (*callback_func)(void*), void* data) {
+#include "backtrace_testlib.h"
+
+void test_loop_forever() {
+  while (1)
+    ;
+}
+
+void test_signal_handler(int) { test_loop_forever(); }
+
+void test_signal_action(int, siginfo_t*, void*) { test_loop_forever(); }
+
+int test_level_four(int one, int two, int three, int four, void (*callback_func)(void*),
+                    void* data) {
   if (callback_func != NULL) {
     callback_func(data);
   } else {
-    while (1) {
-    }
+    while (1)
+      ;
   }
   return one + two + three + four;
 }
 
-int test_level_three(int one, int two, int three, int four,
-                     void (*callback_func)(void*), void* data) {
-  return test_level_four(one+3, two+6, three+9, four+12, callback_func, data) + 3;
+int test_level_three(int one, int two, int three, int four, void (*callback_func)(void*),
+                     void* data) {
+  return test_level_four(one + 3, two + 6, three + 9, four + 12, callback_func, data) + 3;
 }
 
-int test_level_two(int one, int two, int three, int four,
-                   void (*callback_func)(void*), void* data) {
-  return test_level_three(one+2, two+4, three+6, four+8, callback_func, data) + 2;
+int test_level_two(int one, int two, int three, int four, void (*callback_func)(void*), void* data) {
+  return test_level_three(one + 2, two + 4, three + 6, four + 8, callback_func, data) + 2;
 }
 
-int test_level_one(int one, int two, int three, int four,
-                   void (*callback_func)(void*), void* data) {
-  return test_level_two(one+1, two+2, three+3, four+4, callback_func, data) + 1;
+int test_level_one(int one, int two, int three, int four, void (*callback_func)(void*), void* data) {
+  return test_level_two(one + 1, two + 2, three + 3, four + 4, callback_func, data) + 1;
 }
 
 int test_recursive_call(int level, void (*callback_func)(void*), void* data) {
diff --git a/libbacktrace/backtrace_testlib.h b/libbacktrace/backtrace_testlib.h
new file mode 100644
index 0000000..16fedc4
--- /dev/null
+++ b/libbacktrace/backtrace_testlib.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _LIBBACKTRACE_BACKTRACE_TESTLIB_H
+#define _LIBBACKTRACE_BACKTRACE_TESTLIB_H
+
+#include <sys/cdefs.h>
+
+#include <libunwind.h>
+
+__BEGIN_DECLS
+
+void test_loop_forever();
+void test_signal_handler(int);
+void test_signal_action(int, siginfo_t*, void*);
+int test_level_four(int, int, int, int, void (*)(void*), void*);
+int test_level_three(int, int, int, int, void (*)(void*), void*);
+int test_level_two(int, int, int, int, void (*)(void*), void*);
+int test_level_one(int, int, int, int, void (*)(void*), void*);
+int test_recursive_call(int, void (*)(void*), void*);
+void test_get_context_and_wait(unw_context_t*, volatile int*);
+
+__END_DECLS
+
+#endif  // _LIBBACKTRACE_BACKTRACE_TESTLIB_H
diff --git a/libcutils/android_reboot.c b/libcutils/android_reboot.c
index 6bdcc13..a33e45f 100644
--- a/libcutils/android_reboot.c
+++ b/libcutils/android_reboot.c
@@ -13,214 +13,39 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
-#include <errno.h>
-#include <fcntl.h>
-#include <mntent.h>
-#include <stdbool.h>
 #include <stdio.h>
 #include <stdlib.h>
-#include <string.h>
-#include <sys/cdefs.h>
-#include <sys/mount.h>
-#include <sys/reboot.h>
-#include <sys/stat.h>
-#include <sys/syscall.h>
-#include <sys/types.h>
-#include <unistd.h>
 
 #include <cutils/android_reboot.h>
-#include <cutils/klog.h>
-#include <cutils/list.h>
+#include <cutils/properties.h>
 
 #define TAG "android_reboot"
-#define READONLY_CHECK_MS 5000
-#define READONLY_CHECK_TIMES 50
 
-typedef struct {
-    struct listnode list;
-    struct mntent entry;
-} mntent_list;
-
-static bool is_block_device(const char* fsname)
-{
-    return !strncmp(fsname, "/dev/block", 10);
-}
-
-/* Find all read+write block devices in /proc/mounts and add them to
- * |rw_entries|.
- */
-static void find_rw(struct listnode* rw_entries)
-{
-    FILE* fp;
-    struct mntent* mentry;
-
-    if ((fp = setmntent("/proc/mounts", "r")) == NULL) {
-        KLOG_WARNING(TAG, "Failed to open /proc/mounts.\n");
-        return;
-    }
-    while ((mentry = getmntent(fp)) != NULL) {
-        if (is_block_device(mentry->mnt_fsname) && hasmntopt(mentry, "rw")) {
-            mntent_list* item = (mntent_list*)calloc(1, sizeof(mntent_list));
-            item->entry = *mentry;
-            item->entry.mnt_fsname = strdup(mentry->mnt_fsname);
-            item->entry.mnt_dir = strdup(mentry->mnt_dir);
-            item->entry.mnt_type = strdup(mentry->mnt_type);
-            item->entry.mnt_opts = strdup(mentry->mnt_opts);
-            list_add_tail(rw_entries, &item->list);
-        }
-    }
-    endmntent(fp);
-}
-
-static void free_entries(struct listnode* entries)
-{
-    struct listnode* node;
-    struct listnode* n;
-    list_for_each_safe(node, n, entries) {
-        mntent_list* item = node_to_item(node, mntent_list, list);
-        free(item->entry.mnt_fsname);
-        free(item->entry.mnt_dir);
-        free(item->entry.mnt_type);
-        free(item->entry.mnt_opts);
-        free(item);
-    }
-}
-
-static mntent_list* find_item(struct listnode* rw_entries, const char* fsname_to_find)
-{
-    struct listnode* node;
-    list_for_each(node, rw_entries) {
-        mntent_list* item = node_to_item(node, mntent_list, list);
-        if (!strcmp(item->entry.mnt_fsname, fsname_to_find)) {
-            return item;
-        }
-    }
-    return NULL;
-}
-
-/* Remounting filesystems read-only is difficult when there are files
- * opened for writing or pending deletes on the filesystem.  There is
- * no way to force the remount with the mount(2) syscall.  The magic sysrq
- * 'u' command does an emergency remount read-only on all writable filesystems
- * that have a block device (i.e. not tmpfs filesystems) by calling
- * emergency_remount(), which knows how to force the remount to read-only.
- * Unfortunately, that is asynchronous, and just schedules the work and
- * returns.  The best way to determine if it is done is to read /proc/mounts
- * repeatedly until there are no more writable filesystems mounted on
- * block devices.
- */
-static void remount_ro(void (*cb_on_remount)(const struct mntent*))
-{
-    int fd, cnt;
-    FILE* fp;
-    struct mntent* mentry;
-    struct listnode* node;
-
-    list_declare(rw_entries);
-    list_declare(ro_entries);
-
-    sync();
-    find_rw(&rw_entries);
-
-    /* Trigger the remount of the filesystems as read-only,
-     * which also marks them clean.
-     */
-    fd = TEMP_FAILURE_RETRY(open("/proc/sysrq-trigger", O_WRONLY));
-    if (fd < 0) {
-        KLOG_WARNING(TAG, "Failed to open sysrq-trigger.\n");
-        /* TODO: Try to remount each rw parition manually in readonly mode.
-         * This may succeed if no process is using the partition.
-         */
-        goto out;
-    }
-    if (TEMP_FAILURE_RETRY(write(fd, "u", 1)) != 1) {
-        close(fd);
-        KLOG_WARNING(TAG, "Failed to write to sysrq-trigger.\n");
-        /* TODO: The same. Manually remount the paritions. */
-        goto out;
-    }
-    close(fd);
-
-    /* Now poll /proc/mounts till it's done */
-    cnt = 0;
-    while (cnt < READONLY_CHECK_TIMES) {
-        if ((fp = setmntent("/proc/mounts", "r")) == NULL) {
-            /* If we can't read /proc/mounts, just give up. */
-            KLOG_WARNING(TAG, "Failed to open /proc/mounts.\n");
-            goto out;
-        }
-        while ((mentry = getmntent(fp)) != NULL) {
-            if (!is_block_device(mentry->mnt_fsname) || !hasmntopt(mentry, "ro")) {
-                continue;
-            }
-            mntent_list* item = find_item(&rw_entries, mentry->mnt_fsname);
-            if (item) {
-                /* |item| has now been ro remounted. */
-                list_remove(&item->list);
-                list_add_tail(&ro_entries, &item->list);
-            }
-        }
-        endmntent(fp);
-        if (list_empty(&rw_entries)) {
-            /* All rw block devices are now readonly. */
-            break;
-        }
-        TEMP_FAILURE_RETRY(
-            usleep(READONLY_CHECK_MS * 1000 / READONLY_CHECK_TIMES));
-        cnt++;
-    }
-
-    list_for_each(node, &rw_entries) {
-        mntent_list* item = node_to_item(node, mntent_list, list);
-        KLOG_WARNING(TAG, "Failed to remount %s in readonly mode.\n",
-                     item->entry.mnt_fsname);
-    }
-
-    if (cb_on_remount) {
-        list_for_each(node, &ro_entries) {
-            mntent_list* item = node_to_item(node, mntent_list, list);
-            cb_on_remount(&item->entry);
-        }
-    }
-
-out:
-    free_entries(&rw_entries);
-    free_entries(&ro_entries);
-}
-
-int android_reboot_with_callback(
-    int cmd, int flags __unused, const char *arg,
-    void (*cb_on_remount)(const struct mntent*))
-{
+int android_reboot(int cmd, int flags __unused, const char* arg) {
     int ret;
-    remount_ro(cb_on_remount);
+    const char* restart_cmd = NULL;
+    char* prop_value;
+
     switch (cmd) {
-        case ANDROID_RB_RESTART:
-            ret = reboot(RB_AUTOBOOT);
-            break;
-
-        case ANDROID_RB_POWEROFF:
-            ret = reboot(RB_POWER_OFF);
-            break;
-
+        case ANDROID_RB_RESTART:  // deprecated
         case ANDROID_RB_RESTART2:
-            ret = syscall(__NR_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,
-                           LINUX_REBOOT_CMD_RESTART2, arg);
+            restart_cmd = "reboot";
             break;
-
+        case ANDROID_RB_POWEROFF:
+            restart_cmd = "shutdown";
+            break;
         case ANDROID_RB_THERMOFF:
-            ret = reboot(RB_POWER_OFF);
+            restart_cmd = "thermal-shutdown";
             break;
-
-        default:
-            ret = -1;
     }
-
+    if (!restart_cmd) return -1;
+    if (arg) {
+        ret = asprintf(&prop_value, "%s,%s", restart_cmd, arg);
+    } else {
+        ret = asprintf(&prop_value, "%s", restart_cmd);
+    }
+    if (ret < 0) return -1;
+    ret = property_set(ANDROID_RB_PROPERTY, prop_value);
+    free(prop_value);
     return ret;
 }
-
-int android_reboot(int cmd, int flags, const char *arg)
-{
-    return android_reboot_with_callback(cmd, flags, arg, NULL);
-}
diff --git a/libcutils/fs_config.c b/libcutils/fs_config.c
index 1915ced..6a57a41 100644
--- a/libcutils/fs_config.c
+++ b/libcutils/fs_config.c
@@ -52,21 +52,17 @@
 } __attribute__((__aligned__(sizeof(uint64_t))));
 
 /* My kingdom for <endian.h> */
-static inline uint16_t get2LE(const uint8_t* src)
-{
-    return src[0] | (src[1] << 8);
-}
+static inline uint16_t get2LE(const uint8_t* src) { return src[0] | (src[1] << 8); }
 
-static inline uint64_t get8LE(const uint8_t* src)
-{
+static inline uint64_t get8LE(const uint8_t* src) {
     uint32_t low, high;
 
     low = src[0] | (src[1] << 8) | (src[2] << 16) | (src[3] << 24);
     high = src[4] | (src[5] << 8) | (src[6] << 16) | (src[7] << 24);
-    return ((uint64_t) high << 32) | (uint64_t) low;
+    return ((uint64_t)high << 32) | (uint64_t)low;
 }
 
-#define ALIGN(x, alignment) ( ((x) + ((alignment) - 1)) & ~((alignment) - 1) )
+#define ALIGN(x, alignment) (((x) + ((alignment)-1)) & ~((alignment)-1))
 
 /* Rules for directories.
 ** These rules are applied based on "first match", so they
@@ -75,35 +71,37 @@
 */
 
 static const struct fs_path_config android_dirs[] = {
-    { 00770, AID_SYSTEM, AID_CACHE,  0, "cache" },
-    { 00500, AID_ROOT,   AID_ROOT,   0, "config" },
-    { 00771, AID_SYSTEM, AID_SYSTEM, 0, "data/app" },
-    { 00771, AID_SYSTEM, AID_SYSTEM, 0, "data/app-private" },
-    { 00771, AID_SYSTEM, AID_SYSTEM, 0, "data/app-ephemeral" },
-    { 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" },
+    /* clang-format off */
+    { 00770, AID_SYSTEM,       AID_CACHE,        0, "cache" },
+    { 00500, AID_ROOT,         AID_ROOT,         0, "config" },
+    { 00771, AID_SYSTEM,       AID_SYSTEM,       0, "data/app" },
+    { 00771, AID_SYSTEM,       AID_SYSTEM,       0, "data/app-private" },
+    { 00771, AID_SYSTEM,       AID_SYSTEM,       0, "data/app-ephemeral" },
+    { 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" },
+    { 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" },
-    { 00750, AID_ROOT,   AID_SHELL,  0, "data/nativetest" },
-    { 00750, AID_ROOT,   AID_SHELL,  0, "data/nativetest64" },
-    { 00775, AID_ROOT,   AID_ROOT,   0, "data/preloads" },
-    { 00771, AID_SYSTEM, AID_SYSTEM, 0, "data" },
-    { 00755, AID_ROOT,   AID_SYSTEM, 0, "mnt" },
-    { 00755, AID_ROOT,   AID_ROOT,   0, "root" },
-    { 00750, AID_ROOT,   AID_SHELL,  0, "sbin" },
-    { 00751, AID_ROOT,   AID_SDCARD_R, 0, "storage" },
-    { 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 },
+    { 01771, AID_SYSTEM,       AID_MISC,         0, "data/misc" },
+    { 00775, AID_MEDIA_RW,     AID_MEDIA_RW,     0, "data/media/Music" },
+    { 00775, AID_MEDIA_RW,     AID_MEDIA_RW,     0, "data/media" },
+    { 00750, AID_ROOT,         AID_SHELL,        0, "data/nativetest" },
+    { 00750, AID_ROOT,         AID_SHELL,        0, "data/nativetest64" },
+    { 00775, AID_ROOT,         AID_ROOT,         0, "data/preloads" },
+    { 00771, AID_SYSTEM,       AID_SYSTEM,       0, "data" },
+    { 00755, AID_ROOT,         AID_SYSTEM,       0, "mnt" },
+    { 00755, AID_ROOT,         AID_ROOT,         0, "root" },
+    { 00750, AID_ROOT,         AID_SHELL,        0, "sbin" },
+    { 00777, AID_ROOT,         AID_ROOT,         0, "sdcard" },
+    { 00751, AID_ROOT,         AID_SDCARD_R,     0, "storage" },
+    { 00755, AID_ROOT,         AID_SHELL,        0, "system/bin" },
+    { 00755, AID_ROOT,         AID_ROOT,         0, "system/etc/ppp" },
+    { 00755, AID_ROOT,         AID_SHELL,        0, "system/vendor" },
+    { 00755, AID_ROOT,         AID_SHELL,        0, "system/xbin" },
+    { 00755, AID_ROOT,         AID_SHELL,        0, "vendor" },
+    { 00755, AID_ROOT,         AID_ROOT,         0, 0 },
+    /* clang-format on */
 };
 
 /* Rules for files.
@@ -112,34 +110,78 @@
 ** way up to the root. Prefixes ending in * denotes wildcard
 ** and will allow partial matches.
 */
-static const char conf_dir[] = "/system/etc/fs_config_dirs";
-static const char conf_file[] = "/system/etc/fs_config_files";
+static const char sys_conf_dir[] = "/system/etc/fs_config_dirs";
+static const char sys_conf_file[] = "/system/etc/fs_config_files";
+/* No restrictions are placed on the vendor and oem file-system config files,
+ * although the developer is advised to restrict the scope to the /vendor or
+ * oem/ file-system since the intent is to provide support for customized
+ * portions of a separate vendor.img or oem.img.  Has to remain open so that
+ * customization can also land on /system/vendor, /system/oem or /system/odm.
+ * We expect build-time checking or filtering when constructing the associated
+ * fs_config_* files (see build/tools/fs_config/fs_config_generate.c)
+ */
+static const char ven_conf_dir[] = "/vendor/etc/fs_config_dirs";
+static const char ven_conf_file[] = "/vendor/etc/fs_config_files";
+static const char oem_conf_dir[] = "/oem/etc/fs_config_dirs";
+static const char oem_conf_file[] = "/oem/etc/fs_config_files";
+static const char odm_conf_dir[] = "/odm/etc/fs_config_dirs";
+static const char odm_conf_file[] = "/odm/etc/fs_config_files";
+static const char* conf[][2] = {
+    {sys_conf_file, sys_conf_dir},
+    {ven_conf_file, ven_conf_dir},
+    {oem_conf_file, oem_conf_dir},
+    {odm_conf_file, odm_conf_dir},
+};
 
 static const struct fs_path_config android_files[] = {
+    /* clang-format off */
+    { 00644, AID_SYSTEM,    AID_SYSTEM,    0, "data/app/*" },
+    { 00644, AID_SYSTEM,    AID_SYSTEM,    0, "data/app-ephemeral/*" },
+    { 00644, AID_SYSTEM,    AID_SYSTEM,    0, "data/app-private/*" },
+    { 00644, AID_APP,       AID_APP,       0, "data/data/*" },
+    { 00644, AID_MEDIA_RW,  AID_MEDIA_RW,  0, "data/media/*" },
+    { 00640, AID_ROOT,      AID_SHELL,     0, "data/nativetest/tests.txt" },
+    { 00640, AID_ROOT,      AID_SHELL,     0, "data/nativetest64/tests.txt" },
+    { 00750, AID_ROOT,      AID_SHELL,     0, "data/nativetest/*" },
+    { 00750, AID_ROOT,      AID_SHELL,     0, "data/nativetest64/*" },
+    { 00600, AID_ROOT,      AID_ROOT,      0, "default.prop" },
+    { 00600, AID_ROOT,      AID_ROOT,      0, "odm/build.prop" },
+    { 00600, AID_ROOT,      AID_ROOT,      0, "odm/default.prop" },
+    { 00444, AID_ROOT,      AID_ROOT,      0, odm_conf_dir + 1 },
+    { 00444, AID_ROOT,      AID_ROOT,      0, odm_conf_file + 1 },
+    { 00444, AID_ROOT,      AID_ROOT,      0, oem_conf_dir + 1 },
+    { 00444, AID_ROOT,      AID_ROOT,      0, oem_conf_file + 1 },
+    { 00750, AID_ROOT,      AID_SHELL,     0, "sbin/fs_mgr" },
+    { 00755, AID_ROOT,      AID_SHELL,     0, "system/bin/crash_dump32" },
+    { 00755, AID_ROOT,      AID_SHELL,     0, "system/bin/crash_dump64" },
+    { 00755, AID_ROOT,      AID_SHELL,     0, "system/bin/debuggerd" },
+    { 00750, AID_ROOT,      AID_ROOT,      0, "system/bin/install-recovery.sh" },
+    { 00700, AID_ROOT,      AID_ROOT,      0, "system/bin/secilc" },
+    { 00750, AID_ROOT,      AID_ROOT,      0, "system/bin/uncrypt" },
+    { 00600, AID_ROOT,      AID_ROOT,      0, "system/build.prop" },
+    { 00444, AID_ROOT,      AID_ROOT,      0, sys_conf_dir + 1 },
+    { 00444, AID_ROOT,      AID_ROOT,      0, sys_conf_file + 1 },
     { 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" },
     { 00555, AID_ROOT,      AID_ROOT,      0, "system/etc/ppp/*" },
     { 00555, AID_ROOT,      AID_ROOT,      0, "system/etc/rc.*" },
     { 00440, AID_ROOT,      AID_ROOT,      0, "system/etc/recovery.img" },
-    { 00444, AID_ROOT,      AID_ROOT,      0, conf_dir + 1 },
-    { 00444, AID_ROOT,      AID_ROOT,      0, conf_file + 1 },
-    { 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_SYSTEM,    AID_SYSTEM,    0, "data/app-ephemeral/*" },
-    { 00644, AID_APP,       AID_APP,       0, "data/data/*" },
-    { 00640, AID_ROOT,      AID_SHELL,     0, "data/nativetest/tests.txt" },
-    { 00640, AID_ROOT,      AID_SHELL,     0, "data/nativetest64/tests.txt" },
-    { 00750, AID_ROOT,      AID_SHELL,     0, "data/nativetest/*" },
-    { 00750, AID_ROOT,      AID_SHELL,     0, "data/nativetest64/*" },
+    { 00440, AID_RADIO,     AID_ROOT,      0, "system/etc/xtables.lock" },
+    { 00600, AID_ROOT,      AID_ROOT,      0, "vendor/build.prop" },
+    { 00600, AID_ROOT,      AID_ROOT,      0, "vendor/default.prop" },
+    { 00444, AID_ROOT,      AID_ROOT,      0, ven_conf_dir + 1 },
+    { 00444, AID_ROOT,      AID_ROOT,      0, ven_conf_file + 1 },
 
     /* the following two 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/procmem" },
+    { 04750, AID_ROOT,      AID_SHELL,     0, "system/xbin/su" },
 
-    /* the following files have enhanced capabilities and ARE included in user builds. */
+    /* the following files have enhanced capabilities and ARE included
+     * in user builds. */
+    { 00700, AID_SYSTEM,    AID_SHELL,     CAP_MASK_LONG(CAP_BLOCK_SUSPEND),
+                                              "system/bin/inputflinger" },
     { 00550, AID_LOGD,      AID_LOGD,      CAP_MASK_LONG(CAP_SYSLOG) |
                                            CAP_MASK_LONG(CAP_AUDIT_CONTROL) |
                                            CAP_MASK_LONG(CAP_SETGID),
@@ -147,27 +189,27 @@
     { 00750, AID_ROOT,      AID_SHELL,     CAP_MASK_LONG(CAP_SETUID) |
                                            CAP_MASK_LONG(CAP_SETGID),
                                               "system/bin/run-as" },
-    { 00700, AID_SYSTEM,    AID_SHELL,     CAP_MASK_LONG(CAP_BLOCK_SUSPEND),
-                                              "system/bin/inputflinger" },
 
     /* Support FIFO scheduling mode in SurfaceFlinger. */
-    { 00755, AID_SYSTEM,    AID_GRAPHICS,     CAP_MASK_LONG(CAP_SYS_NICE), "system/bin/surfaceflinger" },
+    { 00755, AID_SYSTEM,    AID_GRAPHICS,  CAP_MASK_LONG(CAP_SYS_NICE),
+                                              "system/bin/surfaceflinger" },
 
     /* Support hostapd administering a network interface. */
     { 00755, AID_WIFI,      AID_WIFI,      CAP_MASK_LONG(CAP_NET_ADMIN) |
                                            CAP_MASK_LONG(CAP_NET_RAW),
                                               "system/bin/hostapd" },
 
+    /* Support Bluetooth legacy hal accessing /sys/class/rfkill */
+    { 00700, AID_BLUETOOTH, AID_BLUETOOTH, CAP_MASK_LONG(CAP_NET_ADMIN),
+                                              "vendor/bin/hw/android.hardware.bluetooth@1.0-service" },
+
     /* Support wifi_hal_legacy administering a network interface. */
     { 00755, AID_WIFI,      AID_WIFI,      CAP_MASK_LONG(CAP_NET_ADMIN) |
                                            CAP_MASK_LONG(CAP_NET_RAW),
                                               "vendor/bin/hw/android.hardware.wifi@1.0-service" },
 
-    /* Support Bluetooth legacy hal accessing /sys/class/rfkill */
-    { 00700, AID_BLUETOOTH, AID_BLUETOOTH, CAP_MASK_LONG(CAP_NET_ADMIN),
-                                              "vendor/bin/hw/android.hardware.bluetooth@1.0-service" },
-
-    /* A non-privileged zygote that spawns isolated processes for web rendering. */
+    /* A non-privileged zygote that spawns
+     * isolated processes for web rendering. */
     { 0750,  AID_ROOT,      AID_ROOT,      CAP_MASK_LONG(CAP_SETUID) |
                                            CAP_MASK_LONG(CAP_SETGID) |
                                            CAP_MASK_LONG(CAP_SETPCAP),
@@ -177,62 +219,49 @@
                                            CAP_MASK_LONG(CAP_SETPCAP),
                                               "system/bin/webview_zygote64" },
 
-    { 00755, AID_ROOT,      AID_SHELL,     0, "system/bin/crash_dump32" },
-    { 00755, AID_ROOT,      AID_SHELL,     0, "system/bin/crash_dump64" },
-    { 00755, AID_ROOT,      AID_SHELL,     0, "system/bin/debuggerd" },
-    { 00700, AID_ROOT,      AID_ROOT,      0, "system/bin/secilc" },
-    { 00750, AID_ROOT,      AID_ROOT,      0, "system/bin/uncrypt" },
-    { 00750, AID_ROOT,      AID_ROOT,      0, "system/bin/install-recovery.sh" },
+    /* generic defaults */
+    { 00755, AID_ROOT,      AID_ROOT,      0, "bin/*" },
+    { 00640, AID_ROOT,      AID_SHELL,     0, "fstab.*" },
+    { 00750, AID_ROOT,      AID_SHELL,     0, "init*" },
+    { 00750, AID_ROOT,      AID_SHELL,     0, "sbin/*" },
     { 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, "system/vendor/xbin/*" },
+    { 00755, AID_ROOT,      AID_SHELL,     0, "system/xbin/*" },
     { 00755, AID_ROOT,      AID_SHELL,     0, "vendor/bin/*" },
     { 00755, AID_ROOT,      AID_SHELL,     0, "vendor/xbin/*" },
-    { 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.*" },
-    { 00600, AID_ROOT,      AID_ROOT,      0, "system/build.prop" },
-    { 00600, AID_ROOT,      AID_ROOT,      0, "vendor/build.prop" },
-    { 00600, AID_ROOT,      AID_ROOT,      0, "odm/build.prop" },
-    { 00600, AID_ROOT,      AID_ROOT,      0, "default.prop" },
-    { 00600, AID_ROOT,      AID_ROOT,      0, "vendor/default.prop" },
-    { 00600, AID_ROOT,      AID_ROOT,      0, "odm/default.prop" },
     { 00644, AID_ROOT,      AID_ROOT,      0, 0 },
+    /* clang-format on */
 };
 
-static int fs_config_open(int dir, const char *target_out_path)
-{
+static int fs_config_open(int dir, int which, const char* target_out_path) {
     int fd = -1;
 
     if (target_out_path && *target_out_path) {
-        /* target_out_path is the path to the directory holding content of system partition
-           but as we cannot guaranty it ends with '/system' we need this below skip_len logic */
-        char *name = NULL;
+        /* target_out_path is the path to the directory holding content of
+         * system partition but as we cannot guaranty it ends with '/system'
+         * we need this below skip_len logic */
+        char* name = NULL;
         int target_out_path_len = strlen(target_out_path);
         int skip_len = strlen("/system");
 
         if (target_out_path[target_out_path_len] == '/') {
             skip_len++;
         }
-        if (asprintf(&name, "%s%s", target_out_path, (dir ? conf_dir : conf_file) + skip_len) != -1) {
+        if (asprintf(&name, "%s%s", target_out_path, conf[which][dir] + skip_len) != -1) {
             fd = TEMP_FAILURE_RETRY(open(name, O_RDONLY | O_BINARY));
             free(name);
         }
     }
     if (fd < 0) {
-        fd = TEMP_FAILURE_RETRY(open(dir ? conf_dir : conf_file, O_RDONLY | O_BINARY));
+        fd = TEMP_FAILURE_RETRY(open(conf[which][dir], O_RDONLY | O_BINARY));
     }
     return fd;
 }
 
-static bool fs_config_cmp(bool dir, const char *prefix, size_t len,
-                                    const char *path, size_t plen)
-{
+static bool fs_config_cmp(bool dir, const char* prefix, size_t len, const char* path, size_t plen) {
     if (dir) {
         if (plen < len) {
             return false;
@@ -249,11 +278,10 @@
     return !strncmp(prefix, path, len);
 }
 
-void fs_config(const char *path, int dir, const char *target_out_path,
-               unsigned *uid, unsigned *gid, unsigned *mode, uint64_t *capabilities)
-{
-    const struct fs_path_config *pc;
-    int fd, plen;
+void fs_config(const char* path, int dir, const char* target_out_path, unsigned* uid, unsigned* gid,
+               unsigned* mode, uint64_t* capabilities) {
+    const struct fs_path_config* pc;
+    size_t which, plen;
 
     if (path[0] == '/') {
         path++;
@@ -261,41 +289,43 @@
 
     plen = strlen(path);
 
-    fd = fs_config_open(dir, target_out_path);
-    if (fd >= 0) {
+    for (which = 0; which < (sizeof(conf) / sizeof(conf[0])); ++which) {
         struct fs_path_config_from_file header;
 
+        int fd = fs_config_open(dir, which, target_out_path);
+        if (fd < 0) continue;
+
         while (TEMP_FAILURE_RETRY(read(fd, &header, sizeof(header))) == sizeof(header)) {
-            char *prefix;
-            uint16_t host_len = get2LE((const uint8_t *)&header.len);
+            char* prefix;
+            uint16_t host_len = get2LE((const uint8_t*)&header.len);
             ssize_t len, remainder = host_len - sizeof(header);
             if (remainder <= 0) {
-                ALOGE("%s len is corrupted", dir ? conf_dir : conf_file);
+                ALOGE("%s len is corrupted", conf[which][dir]);
                 break;
             }
             prefix = calloc(1, remainder);
             if (!prefix) {
-                ALOGE("%s out of memory", dir ? conf_dir : conf_file);
+                ALOGE("%s out of memory", conf[which][dir]);
                 break;
             }
             if (TEMP_FAILURE_RETRY(read(fd, prefix, remainder)) != remainder) {
                 free(prefix);
-                ALOGE("%s prefix is truncated", dir ? conf_dir : conf_file);
+                ALOGE("%s prefix is truncated", conf[which][dir]);
                 break;
             }
             len = strnlen(prefix, remainder);
             if (len >= remainder) { /* missing a terminating null */
                 free(prefix);
-                ALOGE("%s is corrupted", dir ? conf_dir : conf_file);
+                ALOGE("%s is corrupted", conf[which][dir]);
                 break;
             }
             if (fs_config_cmp(dir, prefix, len, path, plen)) {
                 free(prefix);
                 close(fd);
-                *uid = get2LE((const uint8_t *)&(header.uid));
-                *gid = get2LE((const uint8_t *)&(header.gid));
-                *mode = (*mode & (~07777)) | get2LE((const uint8_t *)&(header.mode));
-                *capabilities = get8LE((const uint8_t *)&(header.capabilities));
+                *uid = get2LE((const uint8_t*)&(header.uid));
+                *gid = get2LE((const uint8_t*)&(header.gid));
+                *mode = (*mode & (~07777)) | get2LE((const uint8_t*)&(header.mode));
+                *capabilities = get8LE((const uint8_t*)&(header.capabilities));
                 return;
             }
             free(prefix);
@@ -303,8 +333,7 @@
         close(fd);
     }
 
-    pc = dir ? android_dirs : android_files;
-    for(; pc->prefix; pc++){
+    for (pc = dir ? android_dirs : android_files; pc->prefix; pc++) {
         if (fs_config_cmp(dir, pc->prefix, strlen(pc->prefix), path, plen)) {
             break;
         }
@@ -315,9 +344,8 @@
     *capabilities = pc->capabilities;
 }
 
-ssize_t fs_config_generate(char *buffer, size_t length, const struct fs_path_config *pc)
-{
-    struct fs_path_config_from_file *p = (struct fs_path_config_from_file *)buffer;
+ssize_t fs_config_generate(char* buffer, size_t length, const struct fs_path_config* pc) {
+    struct fs_path_config_from_file* p = (struct fs_path_config_from_file*)buffer;
     size_t len = ALIGN(sizeof(*p) + strlen(pc->prefix) + 1, sizeof(uint64_t));
 
     if ((length < len) || (len > UINT16_MAX)) {
@@ -325,11 +353,11 @@
     }
     memset(p, 0, len);
     uint16_t host_len = len;
-    p->len = get2LE((const uint8_t *)&host_len);
-    p->mode = get2LE((const uint8_t *)&(pc->mode));
-    p->uid = get2LE((const uint8_t *)&(pc->uid));
-    p->gid = get2LE((const uint8_t *)&(pc->gid));
-    p->capabilities = get8LE((const uint8_t *)&(pc->capabilities));
+    p->len = get2LE((const uint8_t*)&host_len);
+    p->mode = get2LE((const uint8_t*)&(pc->mode));
+    p->uid = get2LE((const uint8_t*)&(pc->uid));
+    p->gid = get2LE((const uint8_t*)&(pc->gid));
+    p->capabilities = get8LE((const uint8_t*)&(pc->capabilities));
     strcpy(p->prefix, pc->prefix);
     return len;
 }
diff --git a/libcutils/include/cutils/android_reboot.h b/libcutils/include/cutils/android_reboot.h
index 549f258..716567a 100644
--- a/libcutils/include/cutils/android_reboot.h
+++ b/libcutils/include/cutils/android_reboot.h
@@ -17,12 +17,11 @@
 #ifndef __CUTILS_ANDROID_REBOOT_H__
 #define __CUTILS_ANDROID_REBOOT_H__
 
-#include <mntent.h>
 
 __BEGIN_DECLS
 
 /* Commands */
-#define ANDROID_RB_RESTART  0xDEAD0001
+#define ANDROID_RB_RESTART 0xDEAD0001 /* deprecated. Use RESTART2. */
 #define ANDROID_RB_POWEROFF 0xDEAD0002
 #define ANDROID_RB_RESTART2 0xDEAD0003
 #define ANDROID_RB_THERMOFF 0xDEAD0004
@@ -30,10 +29,15 @@
 /* Properties */
 #define ANDROID_RB_PROPERTY "sys.powerctl"
 
+/* Android reboot reason stored in this file */
+#define LAST_REBOOT_REASON_FILE "/data/misc/reboot/last_reboot_reason"
+
+/* Reboot or shutdown the system.
+ * This call uses ANDROID_RB_PROPERTY to request reboot to init process.
+ * Due to that, process calling this should have proper selinux permission
+ * to write to the property. Otherwise, the call will fail.
+ */
 int android_reboot(int cmd, int flags, const char *arg);
-int android_reboot_with_callback(
-    int cmd, int flags, const char *arg,
-    void (*cb_on_remount)(const struct mntent*));
 
 __END_DECLS
 
diff --git a/libcutils/include/cutils/qtaguid.h b/libcutils/include/cutils/qtaguid.h
index f8550fd..803fe0d 100644
--- a/libcutils/include/cutils/qtaguid.h
+++ b/libcutils/include/cutils/qtaguid.h
@@ -26,13 +26,15 @@
 #endif
 
 /*
- * Set tags (and owning UIDs) for network sockets.
-*/
+ * Set tags (and owning UIDs) for network sockets. The socket must be untagged
+ * by calling qtaguid_untagSocket() before closing it, otherwise the qtaguid
+ * module will keep a reference to it even after close.
+ */
 extern int qtaguid_tagSocket(int sockfd, int tag, uid_t uid);
 
 /*
  * Untag a network socket before closing.
-*/
+ */
 extern int qtaguid_untagSocket(int sockfd);
 
 /*
diff --git a/include/private/android_filesystem_capability.h b/libcutils/include/private/android_filesystem_capability.h
similarity index 86%
rename from include/private/android_filesystem_capability.h
rename to libcutils/include/private/android_filesystem_capability.h
index b92d3db..0227b1d 100644
--- a/include/private/android_filesystem_capability.h
+++ b/libcutils/include/private/android_filesystem_capability.h
@@ -35,15 +35,15 @@
 #define _LINUX_CAPABILITY_U32S_3 2
 
 typedef struct __user_cap_header_struct {
- __u32 version;
- int pid;
-} __user *cap_user_header_t;
+    __u32 version;
+    int pid;
+} __user* cap_user_header_t;
 
 typedef struct __user_cap_data_struct {
- __u32 effective;
- __u32 permitted;
- __u32 inheritable;
-} __user *cap_user_data_t;
+    __u32 effective;
+    __u32 permitted;
+    __u32 inheritable;
+} __user* cap_user_data_t;
 
 #define VFS_CAP_REVISION_MASK 0xFF000000
 #define VFS_CAP_REVISION_SHIFT 24
@@ -51,20 +51,20 @@
 #define VFS_CAP_FLAGS_EFFECTIVE 0x000001
 #define VFS_CAP_REVISION_1 0x01000000
 #define VFS_CAP_U32_1 1
-#define XATTR_CAPS_SZ_1 (sizeof(__le32)*(1 + 2*VFS_CAP_U32_1))
+#define XATTR_CAPS_SZ_1 (sizeof(__le32) * (1 + 2 * VFS_CAP_U32_1))
 #define VFS_CAP_REVISION_2 0x02000000
 #define VFS_CAP_U32_2 2
-#define XATTR_CAPS_SZ_2 (sizeof(__le32)*(1 + 2*VFS_CAP_U32_2))
+#define XATTR_CAPS_SZ_2 (sizeof(__le32) * (1 + 2 * VFS_CAP_U32_2))
 #define XATTR_CAPS_SZ XATTR_CAPS_SZ_2
 #define VFS_CAP_U32 VFS_CAP_U32_2
 #define VFS_CAP_REVISION VFS_CAP_REVISION_2
 
 struct vfs_cap_data {
- __le32 magic_etc;
- struct {
- __le32 permitted;
- __le32 inheritable;
- } data[VFS_CAP_U32];
+    __le32 magic_etc;
+    struct {
+        __le32 permitted;
+        __le32 inheritable;
+    } data[VFS_CAP_U32];
 };
 
 #define _LINUX_CAPABILITY_VERSION _LINUX_CAPABILITY_VERSION_1
@@ -110,7 +110,7 @@
 #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))
+#define CAP_TO_MASK(x) (1 << ((x)&31))
 
 #undef __user
 #undef __u32
diff --git a/libcutils/include/private/android_filesystem_config.h b/libcutils/include/private/android_filesystem_config.h
new file mode 100644
index 0000000..0037f15
--- /dev/null
+++ b/libcutils/include/private/android_filesystem_config.h
@@ -0,0 +1,223 @@
+/*
+ * 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.
+*/
+
+/*
+ * This file is consumed by build/tools/fs_config and is used
+ * for generating various files. Anything #define AID_<name>
+ * becomes the mapping for getpwnam/getpwuid, etc. The <name>
+ * field is lowercased.
+ * For example:
+ * #define AID_FOO_BAR 6666 becomes a friendly name of "foo_bar"
+ *
+ * The above holds true with the exception of:
+ *   mediacodec
+ *   mediaex
+ *   mediadrm
+ * Whose friendly names do not match the #define statements.
+ *
+ * Additionally, AID_OEM_RESERVED_START and AID_OEM_RESERVED_END
+ * can be used to define reserved OEM ranges used for sanity checks
+ * during the build process. The rules are, they must end with START/END
+ * The proper convention is incrementing a number like so:
+ * AID_OEM_RESERVED_START
+ * AID_OEM_RESERVED_1_START
+ * AID_OEM_RESERVED_2_START
+ * ...
+ * The same applies to the END.
+ * They are not required to be in order, but must not overlap each other and
+ * must define a START and END'ing range. START must be smaller than END.
+ */
+
+#ifndef _ANDROID_FILESYSTEM_CONFIG_H_
+#define _ANDROID_FILESYSTEM_CONFIG_H_
+
+#include <stdint.h>
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+#if defined(__ANDROID__)
+#include <linux/capability.h>
+#else
+#include "android_filesystem_capability.h"
+#endif
+
+#define CAP_MASK_LONG(cap_name) (1ULL << (cap_name))
+
+/* This is the master Users and Groups config for the platform.
+ * DO NOT EVER RENUMBER
+ */
+
+#define AID_ROOT 0 /* traditional unix root user */
+
+#define AID_SYSTEM 1000 /* system server */
+
+#define AID_RADIO 1001           /* telephony subsystem, RIL */
+#define AID_BLUETOOTH 1002       /* bluetooth subsystem */
+#define AID_GRAPHICS 1003        /* graphics devices */
+#define AID_INPUT 1004           /* input devices */
+#define AID_AUDIO 1005           /* audio devices */
+#define AID_CAMERA 1006          /* camera devices */
+#define AID_LOG 1007             /* log devices */
+#define AID_COMPASS 1008         /* compass device */
+#define AID_MOUNT 1009           /* mountd socket */
+#define AID_WIFI 1010            /* wifi subsystem */
+#define AID_ADB 1011             /* android debug bridge (adbd) */
+#define AID_INSTALL 1012         /* group for installing packages */
+#define AID_MEDIA 1013           /* mediaserver process */
+#define AID_DHCP 1014            /* dhcp client */
+#define AID_SDCARD_RW 1015       /* external storage write access */
+#define AID_VPN 1016             /* vpn system */
+#define AID_KEYSTORE 1017        /* keystore subsystem */
+#define AID_USB 1018             /* USB devices */
+#define AID_DRM 1019             /* DRM server */
+#define AID_MDNSR 1020           /* MulticastDNSResponder (service discovery) */
+#define AID_GPS 1021             /* GPS daemon */
+#define AID_UNUSED1 1022         /* deprecated, DO NOT USE */
+#define AID_MEDIA_RW 1023        /* internal media storage write access */
+#define AID_MTP 1024             /* MTP USB driver access */
+#define AID_UNUSED2 1025         /* deprecated, DO NOT USE */
+#define AID_DRMRPC 1026          /* group for drm rpc */
+#define AID_NFC 1027             /* nfc subsystem */
+#define AID_SDCARD_R 1028        /* external storage read access */
+#define AID_CLAT 1029            /* clat part of nat464 */
+#define AID_LOOP_RADIO 1030      /* loop radio devices */
+#define AID_MEDIA_DRM 1031       /* MediaDrm plugins */
+#define AID_PACKAGE_INFO 1032    /* access to installed package details */
+#define AID_SDCARD_PICS 1033     /* external storage photos access */
+#define AID_SDCARD_AV 1034       /* external storage audio/video access */
+#define AID_SDCARD_ALL 1035      /* access all users external storage */
+#define AID_LOGD 1036            /* log daemon */
+#define AID_SHARED_RELRO 1037    /* creator of shared GNU RELRO files */
+#define AID_DBUS 1038            /* dbus-daemon IPC broker process */
+#define AID_TLSDATE 1039         /* tlsdate unprivileged user */
+#define AID_MEDIA_EX 1040        /* mediaextractor process */
+#define AID_AUDIOSERVER 1041     /* audioserver process */
+#define AID_METRICS_COLL 1042    /* metrics_collector process */
+#define AID_METRICSD 1043        /* metricsd process */
+#define AID_WEBSERV 1044         /* webservd process */
+#define AID_DEBUGGERD 1045       /* debuggerd unprivileged user */
+#define AID_MEDIA_CODEC 1046     /* mediacodec process */
+#define AID_CAMERASERVER 1047    /* cameraserver process */
+#define AID_FIREWALL 1048        /* firewalld process */
+#define AID_TRUNKS 1049          /* trunksd process (TPM daemon) */
+#define AID_NVRAM 1050           /* Access-controlled NVRAM */
+#define AID_DNS 1051             /* DNS resolution daemon (system: netd) */
+#define AID_DNS_TETHER 1052      /* DNS resolution daemon (tether: dnsmasq) */
+#define AID_WEBVIEW_ZYGOTE 1053  /* WebView zygote process */
+#define AID_VEHICLE_NETWORK 1054 /* Vehicle network service */
+#define AID_MEDIA_AUDIO 1055     /* GID for audio files on internal media storage */
+#define AID_MEDIA_VIDEO 1056     /* GID for video files on internal media storage */
+#define AID_MEDIA_IMAGE 1057     /* GID for image files on internal media storage */
+#define AID_TOMBSTONED 1058      /* tombstoned user */
+#define AID_MEDIA_OBB 1059       /* GID for OBB files on internal media storage */
+#define AID_ESE 1060             /* embedded secure element (eSE) subsystem */
+#define AID_OTA_UPDATE 1061      /* resource tracking UID for OTA updates */
+/* Changes to this file must be made in AOSP, *not* in internal branches. */
+
+#define AID_SHELL 2000 /* adb and debug shell user */
+#define AID_CACHE 2001 /* cache access */
+#define AID_DIAG 2002  /* access to diagnostic resources */
+
+/* The range 2900-2999 is reserved for OEM, and must never be
+ * used here */
+#define AID_OEM_RESERVED_START 2900
+#define AID_OEM_RESERVED_END 2999
+
+/* The 3000 series are intended for use as supplemental group id's only.
+ * They indicate special Android capabilities that the kernel is aware of. */
+#define AID_NET_BT_ADMIN 3001 /* bluetooth: create any socket */
+#define AID_NET_BT 3002       /* bluetooth: create sco, rfcomm or l2cap sockets */
+#define AID_INET 3003         /* can create AF_INET and AF_INET6 sockets */
+#define AID_NET_RAW 3004      /* can create raw INET sockets */
+#define AID_NET_ADMIN 3005    /* can configure interfaces and routing tables. */
+#define AID_NET_BW_STATS 3006 /* read bandwidth statistics */
+#define AID_NET_BW_ACCT 3007  /* change bandwidth statistics accounting */
+#define AID_READPROC 3009     /* Allow /proc read access */
+#define AID_WAKELOCK 3010     /* Allow system wakelock read/write access */
+
+/* The range 5000-5999 is also reserved for OEM, and must never be used here. */
+#define AID_OEM_RESERVED_2_START 5000
+#define AID_OEM_RESERVED_2_END 5999
+
+#define AID_EVERYBODY 9997 /* shared between all apps in the same profile */
+#define AID_MISC 9998      /* access to misc storage */
+#define AID_NOBODY 9999
+
+#define AID_APP 10000       /* TODO: switch users over to AID_APP_START */
+#define AID_APP_START 10000 /* first app user */
+#define AID_APP_END 19999   /* last app user */
+
+#define AID_CACHE_GID_START 20000 /* start of gids for apps to mark cached data */
+#define AID_CACHE_GID_END 29999   /* end of gids for apps to mark cached data */
+
+#define AID_EXT_GID_START 30000 /* start of gids for apps to mark external data */
+#define AID_EXT_GID_END 39999   /* end of gids for apps to mark external data */
+
+#define AID_SHARED_GID_START 50000 /* start of gids for apps in each user to share */
+#define AID_SHARED_GID_END 59999   /* end of gids for apps in each user to share */
+
+#define AID_ISOLATED_START 99000 /* start of uids for fully isolated sandboxed processes */
+#define AID_ISOLATED_END 99999   /* end of uids for fully isolated sandboxed processes */
+
+#define AID_USER 100000        /* TODO: switch users over to AID_USER_OFFSET */
+#define AID_USER_OFFSET 100000 /* offset for uid ranges for each user */
+
+/*
+ * android_ids has moved to pwd/grp functionality.
+ * If you need to add one, the structure is now
+ * auto-generated based on the AID_ constraints
+ * documented at the top of this header file.
+ * Also see build/tools/fs_config for more details.
+ */
+
+#if !defined(EXCLUDE_FS_CONFIG_STRUCTURES)
+
+struct fs_path_config {
+    unsigned mode;
+    unsigned uid;
+    unsigned gid;
+    uint64_t capabilities;
+    const char* prefix;
+};
+
+/* Rules for directories and files has moved to system/code/libcutils/fs_config.c */
+
+__BEGIN_DECLS
+
+/*
+ * Used in:
+ *  build/tools/fs_config/fs_config.c
+ *  build/tools/fs_get_stats/fs_get_stats.c
+ *  system/extras/ext4_utils/make_ext4fs_main.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, const char* target_out_path, unsigned* uid, unsigned* gid,
+               unsigned* mode, uint64_t* capabilities);
+
+ssize_t fs_config_generate(char* buffer, size_t length, const struct fs_path_config* pc);
+
+__END_DECLS
+
+#endif
+#endif
diff --git a/include/private/canned_fs_config.h b/libcutils/include/private/canned_fs_config.h
similarity index 88%
rename from include/private/canned_fs_config.h
rename to libcutils/include/private/canned_fs_config.h
index d9f51ca..71e1537 100644
--- a/include/private/canned_fs_config.h
+++ b/libcutils/include/private/canned_fs_config.h
@@ -20,7 +20,7 @@
 #include <inttypes.h>
 
 int load_canned_fs_config(const char* fn);
-void canned_fs_config(const char* path, int dir, const char* target_out_path,
-                      unsigned* uid, unsigned* gid, unsigned* mode, uint64_t* capabilities);
+void canned_fs_config(const char* path, int dir, const char* target_out_path, unsigned* uid,
+                      unsigned* gid, unsigned* mode, uint64_t* capabilities);
 
 #endif
diff --git a/libcutils/include_vndk/private b/libcutils/include_vndk/private
new file mode 120000
index 0000000..2245a85
--- /dev/null
+++ b/libcutils/include_vndk/private
@@ -0,0 +1 @@
+../include/private
\ No newline at end of file
diff --git a/libcutils/sched_policy.cpp b/libcutils/sched_policy.cpp
index 7e3ad59..40144cf 100644
--- a/libcutils/sched_policy.cpp
+++ b/libcutils/sched_policy.cpp
@@ -464,7 +464,7 @@
             break;
         }
 
-        if (add_tid_to_cgroup(tid, fd) != 0) {
+        if (fd > 0 && add_tid_to_cgroup(tid, fd) != 0) {
             if (errno != ESRCH && errno != ENOENT)
                 return -errno;
         }
diff --git a/liblog/tests/liblog_test.cpp b/liblog/tests/liblog_test.cpp
index e68c8f2..0538c4c 100644
--- a/liblog/tests/liblog_test.cpp
+++ b/liblog/tests/liblog_test.cpp
@@ -42,7 +42,10 @@
 #include <private/android_logger.h>
 
 #ifndef TEST_PREFIX
-#ifdef __ANDROID__  // make sure we always run code if compiled for android
+#ifdef TEST_LOGGER
+#define TEST_PREFIX android_set_log_transport(TEST_LOGGER);
+// make sure we always run code despite overrides if compiled for android
+#elif defined(__ANDROID__)
 #define TEST_PREFIX
 #endif
 #endif
@@ -1851,8 +1854,22 @@
     fprintf(stderr, "WARNING: setting ro.device_owner to a domain\n");
     static const char domain[] = "com.google.android.SecOps.DeviceOwner";
     property_set(readonly_key, domain);
-    usleep(20000);  // property system does not guarantee performance, rest ...
-    property_get(readonly_key, readonly, nothing_val);
+    useconds_t total_time = 0;
+    static const useconds_t seconds = 1000000;
+    static const useconds_t max_time = 5 * seconds;  // not going to happen
+    static const useconds_t rest = 20 * 1000;
+    for (; total_time < max_time; total_time += rest) {
+      usleep(rest);  // property system does not guarantee performance.
+      property_get(readonly_key, readonly, nothing_val);
+      if (!strcmp(readonly, domain)) {
+        if (total_time > rest) {
+          fprintf(stderr, "INFO: took %u.%06u seconds to set property\n",
+                  (unsigned)(total_time / seconds),
+                  (unsigned)(total_time % seconds));
+        }
+        break;
+      }
+    }
     EXPECT_STREQ(readonly, domain);
   } else if (!strcasecmp(readonly, "false") || !readonly[0]) {
     // not enough permissions to run
@@ -2137,10 +2154,19 @@
 }
 #endif
 
+// Make multiple tests and re-tests orthogonal to prevent falsing.
+#ifdef TEST_LOGGER
+#define UNIQUE_TAG(X) \
+  (0x12340000 + (((X) + sizeof(int) + sizeof(void*)) << 8) + TEST_LOGGER)
+#else
+#define UNIQUE_TAG(X) \
+  (0x12340000 + (((X) + sizeof(int) + sizeof(void*)) << 8) + 0xBA)
+#endif
+
 TEST(liblog, android_errorWriteWithInfoLog__android_logger_list_read__typical) {
 #ifdef TEST_PREFIX
   int count;
-  android_errorWriteWithInfoLog_helper(123456781, "test-subtag", -1,
+  android_errorWriteWithInfoLog_helper(UNIQUE_TAG(1), "test-subtag", -1,
                                        max_payload_buf, 200, count);
   EXPECT_EQ(SUPPORTS_END_TO_END, count);
 #else
@@ -2152,7 +2178,7 @@
      android_errorWriteWithInfoLog__android_logger_list_read__data_too_large) {
 #ifdef TEST_PREFIX
   int count;
-  android_errorWriteWithInfoLog_helper(123456782, "test-subtag", -1,
+  android_errorWriteWithInfoLog_helper(UNIQUE_TAG(2), "test-subtag", -1,
                                        max_payload_buf, sizeof(max_payload_buf),
                                        count);
   EXPECT_EQ(SUPPORTS_END_TO_END, count);
@@ -2165,8 +2191,8 @@
      android_errorWriteWithInfoLog__android_logger_list_read__null_data) {
 #ifdef TEST_PREFIX
   int count;
-  android_errorWriteWithInfoLog_helper(123456783, "test-subtag", -1, NULL, 200,
-                                       count);
+  android_errorWriteWithInfoLog_helper(UNIQUE_TAG(3), "test-subtag", -1, NULL,
+                                       200, count);
   EXPECT_EQ(0, count);
 #else
   GTEST_LOG_(INFO) << "This test does nothing.\n";
@@ -2178,7 +2204,7 @@
 #ifdef TEST_PREFIX
   int count;
   android_errorWriteWithInfoLog_helper(
-      123456784, "abcdefghijklmnopqrstuvwxyz now i know my abc", -1,
+      UNIQUE_TAG(4), "abcdefghijklmnopqrstuvwxyz now i know my abc", -1,
       max_payload_buf, 200, count);
   EXPECT_EQ(SUPPORTS_END_TO_END, count);
 #else
@@ -2313,7 +2339,7 @@
 TEST(liblog, android_errorWriteLog__android_logger_list_read__success) {
 #ifdef TEST_PREFIX
   int count;
-  android_errorWriteLog_helper(123456785, "test-subtag", count);
+  android_errorWriteLog_helper(UNIQUE_TAG(5), "test-subtag", count);
   EXPECT_EQ(SUPPORTS_END_TO_END, count);
 #else
   GTEST_LOG_(INFO) << "This test does nothing.\n";
@@ -2323,7 +2349,7 @@
 TEST(liblog, android_errorWriteLog__android_logger_list_read__null_subtag) {
 #ifdef TEST_PREFIX
   int count;
-  android_errorWriteLog_helper(123456786, NULL, count);
+  android_errorWriteLog_helper(UNIQUE_TAG(6), NULL, count);
   EXPECT_EQ(0, count);
 #else
   GTEST_LOG_(INFO) << "This test does nothing.\n";
diff --git a/liblog/tests/liblog_test_default.cpp b/liblog/tests/liblog_test_default.cpp
index cbd0d25..9fc443c 100644
--- a/liblog/tests/liblog_test_default.cpp
+++ b/liblog/tests/liblog_test_default.cpp
@@ -1,5 +1,5 @@
 #ifdef __ANDROID__
 #include <log/log_transport.h>
-#define TEST_PREFIX android_set_log_transport(LOGGER_DEFAULT);
+#define TEST_LOGGER LOGGER_DEFAULT
 #endif
 #include "liblog_test.cpp"
diff --git a/liblog/tests/liblog_test_local.cpp b/liblog/tests/liblog_test_local.cpp
index 9d7b3d7..451beca 100644
--- a/liblog/tests/liblog_test_local.cpp
+++ b/liblog/tests/liblog_test_local.cpp
@@ -1,4 +1,4 @@
 #include <log/log_transport.h>
 #define liblog liblog_local
-#define TEST_PREFIX android_set_log_transport(LOGGER_LOCAL);
+#define TEST_LOGGER LOGGER_LOCAL
 #include "liblog_test.cpp"
diff --git a/liblog/tests/liblog_test_stderr.cpp b/liblog/tests/liblog_test_stderr.cpp
index f9e4e1f..abc1b9c 100644
--- a/liblog/tests/liblog_test_stderr.cpp
+++ b/liblog/tests/liblog_test_stderr.cpp
@@ -1,5 +1,5 @@
 #include <log/log_transport.h>
 #define liblog liblog_stderr
-#define TEST_PREFIX android_set_log_transport(LOGGER_STDERR);
+#define TEST_LOGGER LOGGER_STDERR
 #define USING_LOGGER_STDERR
 #include "liblog_test.cpp"
diff --git a/liblog/tests/liblog_test_stderr_local.cpp b/liblog/tests/liblog_test_stderr_local.cpp
index 21406ca..bb5c7ae 100644
--- a/liblog/tests/liblog_test_stderr_local.cpp
+++ b/liblog/tests/liblog_test_stderr_local.cpp
@@ -1,4 +1,4 @@
 #include <log/log_transport.h>
 #define liblog liblog_stderr_local
-#define TEST_PREFIX android_set_log_transport(LOGGER_LOCAL | LOGGER_STDERR);
+#define TEST_LOGGER (LOGGER_LOCAL | LOGGER_STDERR)
 #include "liblog_test.cpp"
diff --git a/libunwindstack/.clang-format b/libunwindstack/.clang-format
new file mode 120000
index 0000000..fd0645f
--- /dev/null
+++ b/libunwindstack/.clang-format
@@ -0,0 +1 @@
+../.clang-format-2
\ No newline at end of file
diff --git a/libutils/Android.bp b/libutils/Android.bp
index 2b98fef..2b7412b 100644
--- a/libutils/Android.bp
+++ b/libutils/Android.bp
@@ -45,6 +45,7 @@
         "StopWatch.cpp",
         "String8.cpp",
         "String16.cpp",
+        "StrongPointer.cpp",
         "SystemClock.cpp",
         "Threads.cpp",
         "Timers.cpp",
diff --git a/include/private/canned_fs_config.h b/libutils/StrongPointer.cpp
similarity index 61%
copy from include/private/canned_fs_config.h
copy to libutils/StrongPointer.cpp
index d9f51ca..ba52502 100644
--- a/include/private/canned_fs_config.h
+++ b/libutils/StrongPointer.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2014 The Android Open Source Project
+ * Copyright (C) 2017 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,13 +14,11 @@
  * limitations under the License.
  */
 
-#ifndef _CANNED_FS_CONFIG_H
-#define _CANNED_FS_CONFIG_H
+#define LOG_TAG "sp"
 
-#include <inttypes.h>
+#include <log/log.h>
 
-int load_canned_fs_config(const char* fn);
-void canned_fs_config(const char* path, int dir, const char* target_out_path,
-                      unsigned* uid, unsigned* gid, unsigned* mode, uint64_t* capabilities);
+namespace android {
 
-#endif
+void sp_report_race() { LOG_ALWAYS_FATAL("sp<> assignment detected data race"); }
+}
diff --git a/libutils/include/utils/Compat.h b/libutils/include/utils/Compat.h
index 2709e3b..dee577e 100644
--- a/libutils/include/utils/Compat.h
+++ b/libutils/include/utils/Compat.h
@@ -37,6 +37,10 @@
     return pwrite(fd, buf, nbytes, offset);
 }
 
+static inline int ftruncate64(int fd, off64_t length) {
+    return ftruncate(fd, length);
+}
+
 #endif /* __APPLE__ */
 
 #if defined(_WIN32)
diff --git a/libutils/include/utils/StrongPointer.h b/libutils/include/utils/StrongPointer.h
index 294e6b6..c2f7722 100644
--- a/libutils/include/utils/StrongPointer.h
+++ b/libutils/include/utils/StrongPointer.h
@@ -108,6 +108,9 @@
     T* m_ptr;
 };
 
+// For code size reasons, we do not want this inlined or templated.
+void sp_report_race();
+
 #undef COMPARE
 
 // ---------------------------------------------------------------------------
@@ -161,19 +164,21 @@
 
 template<typename T>
 sp<T>& sp<T>::operator =(const sp<T>& other) {
+    // Force m_ptr to be read twice, to heuristically check for data races.
+    T* oldPtr(*const_cast<T* volatile*>(&m_ptr));
     T* otherPtr(other.m_ptr);
-    if (otherPtr)
-        otherPtr->incStrong(this);
-    if (m_ptr)
-        m_ptr->decStrong(this);
+    if (otherPtr) otherPtr->incStrong(this);
+    if (oldPtr) oldPtr->decStrong(this);
+    if (oldPtr != *const_cast<T* volatile*>(&m_ptr)) sp_report_race();
     m_ptr = otherPtr;
     return *this;
 }
 
 template<typename T>
 sp<T>& sp<T>::operator =(sp<T>&& other) {
-    if (m_ptr)
-        m_ptr->decStrong(this);
+    T* oldPtr(*const_cast<T* volatile*>(&m_ptr));
+    if (oldPtr) oldPtr->decStrong(this);
+    if (oldPtr != *const_cast<T* volatile*>(&m_ptr)) sp_report_race();
     m_ptr = other.m_ptr;
     other.m_ptr = nullptr;
     return *this;
@@ -181,29 +186,30 @@
 
 template<typename T>
 sp<T>& sp<T>::operator =(T* other) {
-    if (other)
-        other->incStrong(this);
-    if (m_ptr)
-        m_ptr->decStrong(this);
+    T* oldPtr(*const_cast<T* volatile*>(&m_ptr));
+    if (other) other->incStrong(this);
+    if (oldPtr) oldPtr->decStrong(this);
+    if (oldPtr != *const_cast<T* volatile*>(&m_ptr)) sp_report_race();
     m_ptr = other;
     return *this;
 }
 
 template<typename T> template<typename U>
 sp<T>& sp<T>::operator =(const sp<U>& other) {
+    T* oldPtr(*const_cast<T* volatile*>(&m_ptr));
     T* otherPtr(other.m_ptr);
-    if (otherPtr)
-        otherPtr->incStrong(this);
-    if (m_ptr)
-        m_ptr->decStrong(this);
+    if (otherPtr) otherPtr->incStrong(this);
+    if (oldPtr) oldPtr->decStrong(this);
+    if (oldPtr != *const_cast<T* volatile*>(&m_ptr)) sp_report_race();
     m_ptr = otherPtr;
     return *this;
 }
 
 template<typename T> template<typename U>
 sp<T>& sp<T>::operator =(sp<U>&& other) {
-    if (m_ptr)
-        m_ptr->decStrong(this);
+    T* oldPtr(*const_cast<T* volatile*>(&m_ptr));
+    if (m_ptr) m_ptr->decStrong(this);
+    if (oldPtr != *const_cast<T* volatile*>(&m_ptr)) sp_report_race();
     m_ptr = other.m_ptr;
     other.m_ptr = nullptr;
     return *this;
@@ -211,10 +217,10 @@
 
 template<typename T> template<typename U>
 sp<T>& sp<T>::operator =(U* other) {
-    if (other)
-        (static_cast<T*>(other))->incStrong(this);
-    if (m_ptr)
-        m_ptr->decStrong(this);
+    T* oldPtr(*const_cast<T* volatile*>(&m_ptr));
+    if (other) (static_cast<T*>(other))->incStrong(this);
+    if (oldPtr) oldPtr->decStrong(this);
+    if (oldPtr != *const_cast<T* volatile*>(&m_ptr)) sp_report_race();
     m_ptr = other;
     return *this;
 }
diff --git a/libziparchive/zip_writer.cc b/libziparchive/zip_writer.cc
index b72ed7f..7600528 100644
--- a/libziparchive/zip_writer.cc
+++ b/libziparchive/zip_writer.cc
@@ -14,21 +14,23 @@
  * limitations under the License.
  */
 
-#include "entry_name_utils-inl.h"
-#include "zip_archive_common.h"
 #include "ziparchive/zip_writer.h"
 
-#include <utils/Log.h>
-
-#include <sys/param.h>
-
-#include <cassert>
 #include <cstdio>
-#include <memory>
-#include <vector>
+#include <sys/param.h>
 #include <zlib.h>
 #define DEF_MEM_LEVEL 8                // normally in zutil.h?
 
+#include <memory>
+#include <vector>
+
+#include "android-base/logging.h"
+#include "utils/Compat.h"
+#include "utils/Log.h"
+
+#include "entry_name_utils-inl.h"
+#include "zip_archive_common.h"
+
 #if !defined(powerof2)
 #define powerof2(x) ((((x)-1)&(x))==0)
 #endif
@@ -171,12 +173,12 @@
     return kInvalidAlignment;
   }
 
-  FileInfo fileInfo = {};
-  fileInfo.path = std::string(path);
-  fileInfo.local_file_header_offset = current_offset_;
+  current_file_entry_ = {};
+  current_file_entry_.path = path;
+  current_file_entry_.local_file_header_offset = current_offset_;
 
-  if (!IsValidEntryName(reinterpret_cast<const uint8_t*>(fileInfo.path.data()),
-                       fileInfo.path.size())) {
+  if (!IsValidEntryName(reinterpret_cast<const uint8_t*>(current_file_entry_.path.data()),
+                        current_file_entry_.path.size())) {
     return kInvalidEntryName;
   }
 
@@ -188,24 +190,24 @@
   header.gpb_flags |= kGPBDDFlagMask;
 
   if (flags & ZipWriter::kCompress) {
-    fileInfo.compression_method = kCompressDeflated;
+    current_file_entry_.compression_method = kCompressDeflated;
 
     int32_t result = PrepareDeflate();
     if (result != kNoError) {
       return result;
     }
   } else {
-    fileInfo.compression_method = kCompressStored;
+    current_file_entry_.compression_method = kCompressStored;
   }
-  header.compression_method = fileInfo.compression_method;
+  header.compression_method = current_file_entry_.compression_method;
 
-  ExtractTimeAndDate(time, &fileInfo.last_mod_time, &fileInfo.last_mod_date);
-  header.last_mod_time = fileInfo.last_mod_time;
-  header.last_mod_date = fileInfo.last_mod_date;
+  ExtractTimeAndDate(time, &current_file_entry_.last_mod_time, &current_file_entry_.last_mod_date);
+  header.last_mod_time = current_file_entry_.last_mod_time;
+  header.last_mod_date = current_file_entry_.last_mod_date;
 
-  header.file_name_length = fileInfo.path.size();
+  header.file_name_length = current_file_entry_.path.size();
 
-  off64_t offset = current_offset_ + sizeof(header) + fileInfo.path.size();
+  off64_t offset = current_offset_ + sizeof(header) + current_file_entry_.path.size();
   std::vector<char> zero_padding;
   if (alignment != 0 && (offset & (alignment - 1))) {
     // Pad the extra field so the data will be aligned.
@@ -220,7 +222,8 @@
     return HandleError(kIoError);
   }
 
-  if (fwrite(path, sizeof(*path), fileInfo.path.size(), file_) != fileInfo.path.size()) {
+  if (fwrite(path, sizeof(*path), current_file_entry_.path.size(), file_)
+      != current_file_entry_.path.size()) {
     return HandleError(kIoError);
   }
 
@@ -230,15 +233,37 @@
     return HandleError(kIoError);
   }
 
-  files_.emplace_back(std::move(fileInfo));
-
   current_offset_ = offset;
   state_ = State::kWritingEntry;
   return kNoError;
 }
 
+int32_t ZipWriter::DiscardLastEntry() {
+  if (state_ != State::kWritingZip || files_.empty()) {
+    return kInvalidState;
+  }
+
+  FileEntry& last_entry = files_.back();
+  current_offset_ = last_entry.local_file_header_offset;
+  if (fseeko(file_, current_offset_, SEEK_SET) != 0) {
+    return HandleError(kIoError);
+  }
+  files_.pop_back();
+  return kNoError;
+}
+
+int32_t ZipWriter::GetLastEntry(FileEntry* out_entry) {
+  CHECK(out_entry != nullptr);
+
+  if (files_.empty()) {
+    return kInvalidState;
+  }
+  *out_entry = files_.back();
+  return kNoError;
+}
+
 int32_t ZipWriter::PrepareDeflate() {
-  assert(state_ == State::kWritingZip);
+  CHECK(state_ == State::kWritingZip);
 
   // Initialize the z_stream for compression.
   z_stream_ = std::unique_ptr<z_stream, void(*)(z_stream*)>(new z_stream(), DeleteZStream);
@@ -269,25 +294,25 @@
     return HandleError(kInvalidState);
   }
 
-  FileInfo& currentFile = files_.back();
   int32_t result = kNoError;
-  if (currentFile.compression_method & kCompressDeflated) {
-    result = CompressBytes(&currentFile, data, len);
+  if (current_file_entry_.compression_method & kCompressDeflated) {
+    result = CompressBytes(&current_file_entry_, data, len);
   } else {
-    result = StoreBytes(&currentFile, data, len);
+    result = StoreBytes(&current_file_entry_, data, len);
   }
 
   if (result != kNoError) {
     return result;
   }
 
-  currentFile.crc32 = crc32(currentFile.crc32, reinterpret_cast<const Bytef*>(data), len);
-  currentFile.uncompressed_size += len;
+  current_file_entry_.crc32 = crc32(current_file_entry_.crc32,
+                                    reinterpret_cast<const Bytef*>(data), len);
+  current_file_entry_.uncompressed_size += len;
   return kNoError;
 }
 
-int32_t ZipWriter::StoreBytes(FileInfo* file, const void* data, size_t len) {
-  assert(state_ == State::kWritingEntry);
+int32_t ZipWriter::StoreBytes(FileEntry* file, const void* data, size_t len) {
+  CHECK(state_ == State::kWritingEntry);
 
   if (fwrite(data, 1, len, file_) != len) {
     return HandleError(kIoError);
@@ -297,11 +322,11 @@
   return kNoError;
 }
 
-int32_t ZipWriter::CompressBytes(FileInfo* file, const void* data, size_t len) {
-  assert(state_ == State::kWritingEntry);
-  assert(z_stream_);
-  assert(z_stream_->next_out != nullptr);
-  assert(z_stream_->avail_out != 0);
+int32_t ZipWriter::CompressBytes(FileEntry* file, const void* data, size_t len) {
+  CHECK(state_ == State::kWritingEntry);
+  CHECK(z_stream_);
+  CHECK(z_stream_->next_out != nullptr);
+  CHECK(z_stream_->avail_out != 0);
 
   // Prepare the input.
   z_stream_->next_in = reinterpret_cast<const uint8_t*>(data);
@@ -331,17 +356,17 @@
   return kNoError;
 }
 
-int32_t ZipWriter::FlushCompressedBytes(FileInfo* file) {
-  assert(state_ == State::kWritingEntry);
-  assert(z_stream_);
-  assert(z_stream_->next_out != nullptr);
-  assert(z_stream_->avail_out != 0);
+int32_t ZipWriter::FlushCompressedBytes(FileEntry* file) {
+  CHECK(state_ == State::kWritingEntry);
+  CHECK(z_stream_);
+  CHECK(z_stream_->next_out != nullptr);
+  CHECK(z_stream_->avail_out != 0);
 
   // Keep deflating while there isn't enough space in the buffer to
   // to complete the compress.
   int zerr;
   while ((zerr = deflate(z_stream_.get(), Z_FINISH)) == Z_OK) {
-    assert(z_stream_->avail_out == 0);
+    CHECK(z_stream_->avail_out == 0);
     size_t write_bytes = z_stream_->next_out - buffer_.data();
     if (fwrite(buffer_.data(), 1, write_bytes, file_) != write_bytes) {
       return HandleError(kIoError);
@@ -373,9 +398,8 @@
     return kInvalidState;
   }
 
-  FileInfo& currentFile = files_.back();
-  if (currentFile.compression_method & kCompressDeflated) {
-    int32_t result = FlushCompressedBytes(&currentFile);
+  if (current_file_entry_.compression_method & kCompressDeflated) {
+    int32_t result = FlushCompressedBytes(&current_file_entry_);
     if (result != kNoError) {
       return result;
     }
@@ -388,13 +412,15 @@
   }
 
   DataDescriptor dd = {};
-  dd.crc32 = currentFile.crc32;
-  dd.compressed_size = currentFile.compressed_size;
-  dd.uncompressed_size = currentFile.uncompressed_size;
+  dd.crc32 = current_file_entry_.crc32;
+  dd.compressed_size = current_file_entry_.compressed_size;
+  dd.uncompressed_size = current_file_entry_.uncompressed_size;
   if (fwrite(&dd, sizeof(dd), 1, file_) != 1) {
     return HandleError(kIoError);
   }
 
+  files_.emplace_back(std::move(current_file_entry_));
+
   current_offset_ += sizeof(DataDescriptor::kOptSignature) + sizeof(dd);
   state_ = State::kWritingZip;
   return kNoError;
@@ -406,7 +432,7 @@
   }
 
   off64_t startOfCdr = current_offset_;
-  for (FileInfo& file : files_) {
+  for (FileEntry& file : files_) {
     CentralDirectoryRecord cdr = {};
     cdr.record_signature = CentralDirectoryRecord::kSignature;
     cdr.gpb_flags |= kGPBDDFlagMask;
@@ -442,11 +468,19 @@
     return HandleError(kIoError);
   }
 
+  current_offset_ += sizeof(er);
+
+  // Since we can BackUp() and potentially finish writing at an offset less than one we had
+  // already written at, we must truncate the file.
+
+  if (ftruncate64(fileno(file_), current_offset_) != 0) {
+    return HandleError(kIoError);
+  }
+
   if (fflush(file_) != 0) {
     return HandleError(kIoError);
   }
 
-  current_offset_ += sizeof(er);
   state_ = State::kDone;
   return kNoError;
 }
diff --git a/libziparchive/zip_writer_test.cc b/libziparchive/zip_writer_test.cc
index 16a574d..30f4950 100644
--- a/libziparchive/zip_writer_test.cc
+++ b/libziparchive/zip_writer_test.cc
@@ -23,6 +23,10 @@
 #include <memory>
 #include <vector>
 
+static ::testing::AssertionResult AssertFileEntryContentsEq(const std::string& expected,
+                                                            ZipArchiveHandle handle,
+                                                            ZipEntry* zip_entry);
+
 struct zipwriter : public ::testing::Test {
   TemporaryFile* temp_file_;
   int fd_;
@@ -59,16 +63,10 @@
 
   ZipEntry data;
   ASSERT_EQ(0, FindEntry(handle, ZipString("file.txt"), &data));
-  EXPECT_EQ(strlen(expected), data.compressed_length);
-  EXPECT_EQ(strlen(expected), data.uncompressed_length);
   EXPECT_EQ(kCompressStored, data.method);
-
-  char buffer[6];
-  EXPECT_EQ(0,
-            ExtractToMemory(handle, &data, reinterpret_cast<uint8_t*>(&buffer), sizeof(buffer)));
-  buffer[5] = 0;
-
-  EXPECT_STREQ(expected, buffer);
+  EXPECT_EQ(strlen(expected), data.compressed_length);
+  ASSERT_EQ(strlen(expected), data.uncompressed_length);
+  ASSERT_TRUE(AssertFileEntryContentsEq(expected, handle, &data));
 
   CloseArchive(handle);
 }
@@ -94,26 +92,19 @@
   ZipArchiveHandle handle;
   ASSERT_EQ(0, OpenArchiveFd(fd_, "temp", &handle, false));
 
-  char buffer[4];
   ZipEntry data;
 
   ASSERT_EQ(0, FindEntry(handle, ZipString("file.txt"), &data));
   EXPECT_EQ(kCompressStored, data.method);
   EXPECT_EQ(2u, data.compressed_length);
-  EXPECT_EQ(2u, data.uncompressed_length);
-  ASSERT_EQ(0,
-            ExtractToMemory(handle, &data, reinterpret_cast<uint8_t*>(buffer), arraysize(buffer)));
-  buffer[2] = 0;
-  EXPECT_STREQ("he", buffer);
+  ASSERT_EQ(2u, data.uncompressed_length);
+  ASSERT_TRUE(AssertFileEntryContentsEq("he", handle, &data));
 
   ASSERT_EQ(0, FindEntry(handle, ZipString("file/file.txt"), &data));
   EXPECT_EQ(kCompressStored, data.method);
   EXPECT_EQ(3u, data.compressed_length);
-  EXPECT_EQ(3u, data.uncompressed_length);
-  ASSERT_EQ(0,
-            ExtractToMemory(handle, &data, reinterpret_cast<uint8_t*>(buffer), arraysize(buffer)));
-  buffer[3] = 0;
-  EXPECT_STREQ("llo", buffer);
+  ASSERT_EQ(3u, data.uncompressed_length);
+  ASSERT_TRUE(AssertFileEntryContentsEq("llo", handle, &data));
 
   ASSERT_EQ(0, FindEntry(handle, ZipString("file/file2.txt"), &data));
   EXPECT_EQ(kCompressStored, data.method);
@@ -143,7 +134,7 @@
   CloseArchive(handle);
 }
 
-void ConvertZipTimeToTm(uint32_t& zip_time, struct tm* tm) {
+static void ConvertZipTimeToTm(uint32_t& zip_time, struct tm* tm) {
   memset(tm, 0, sizeof(struct tm));
   tm->tm_hour = (zip_time >> 11) & 0x1f;
   tm->tm_min = (zip_time >> 5) & 0x3f;
@@ -264,14 +255,8 @@
   ZipEntry data;
   ASSERT_EQ(0, FindEntry(handle, ZipString("file.txt"), &data));
   EXPECT_EQ(kCompressDeflated, data.method);
-  EXPECT_EQ(4u, data.uncompressed_length);
-
-  char buffer[5];
-  ASSERT_EQ(0,
-            ExtractToMemory(handle, &data, reinterpret_cast<uint8_t*>(buffer), arraysize(buffer)));
-  buffer[4] = 0;
-
-  EXPECT_STREQ("helo", buffer);
+  ASSERT_EQ(4u, data.uncompressed_length);
+  ASSERT_TRUE(AssertFileEntryContentsEq("helo", handle, &data));
 
   CloseArchive(handle);
 }
@@ -319,3 +304,111 @@
   ASSERT_EQ(-5, writer.StartAlignedEntry("align.txt", ZipWriter::kAlign32, 4096));
   ASSERT_EQ(-6, writer.StartAlignedEntry("align.txt", 0, 3));
 }
+
+TEST_F(zipwriter, BackupRemovesTheLastFile) {
+  ZipWriter writer(file_);
+
+  const char* kKeepThis = "keep this";
+  const char* kDropThis = "drop this";
+  const char* kReplaceWithThis = "replace with this";
+
+  ZipWriter::FileEntry entry;
+  EXPECT_LT(writer.GetLastEntry(&entry), 0);
+
+  ASSERT_EQ(0, writer.StartEntry("keep.txt", 0));
+  ASSERT_EQ(0, writer.WriteBytes(kKeepThis, strlen(kKeepThis)));
+  ASSERT_EQ(0, writer.FinishEntry());
+
+  ASSERT_EQ(0, writer.GetLastEntry(&entry));
+  EXPECT_EQ("keep.txt", entry.path);
+
+  ASSERT_EQ(0, writer.StartEntry("drop.txt", 0));
+  ASSERT_EQ(0, writer.WriteBytes(kDropThis, strlen(kDropThis)));
+  ASSERT_EQ(0, writer.FinishEntry());
+
+  ASSERT_EQ(0, writer.GetLastEntry(&entry));
+  EXPECT_EQ("drop.txt", entry.path);
+
+  ASSERT_EQ(0, writer.DiscardLastEntry());
+
+  ASSERT_EQ(0, writer.GetLastEntry(&entry));
+  EXPECT_EQ("keep.txt", entry.path);
+
+  ASSERT_EQ(0, writer.StartEntry("replace.txt", 0));
+  ASSERT_EQ(0, writer.WriteBytes(kReplaceWithThis, strlen(kReplaceWithThis)));
+  ASSERT_EQ(0, writer.FinishEntry());
+
+  ASSERT_EQ(0, writer.GetLastEntry(&entry));
+  EXPECT_EQ("replace.txt", entry.path);
+
+  ASSERT_EQ(0, writer.Finish());
+
+  // Verify that "drop.txt" does not exist.
+
+  ASSERT_GE(0, lseek(fd_, 0, SEEK_SET));
+
+  ZipArchiveHandle handle;
+  ASSERT_EQ(0, OpenArchiveFd(fd_, "temp", &handle, false));
+
+  ZipEntry data;
+  ASSERT_EQ(0, FindEntry(handle, ZipString("keep.txt"), &data));
+  ASSERT_TRUE(AssertFileEntryContentsEq(kKeepThis, handle, &data));
+
+  ASSERT_NE(0, FindEntry(handle, ZipString("drop.txt"), &data));
+
+  ASSERT_EQ(0, FindEntry(handle, ZipString("replace.txt"), &data));
+  ASSERT_TRUE(AssertFileEntryContentsEq(kReplaceWithThis, handle, &data));
+
+  CloseArchive(handle);
+}
+
+TEST_F(zipwriter, TruncateFileAfterBackup) {
+  ZipWriter writer(file_);
+
+  const char* kSmall = "small";
+
+  ASSERT_EQ(0, writer.StartEntry("small.txt", 0));
+  ASSERT_EQ(0, writer.WriteBytes(kSmall, strlen(kSmall)));
+  ASSERT_EQ(0, writer.FinishEntry());
+
+  ASSERT_EQ(0, writer.StartEntry("large.txt", 0));
+  std::vector<uint8_t> data;
+  data.resize(1024*1024, 0xef);
+  ASSERT_EQ(0, writer.WriteBytes(data.data(), data.size()));
+  ASSERT_EQ(0, writer.FinishEntry());
+
+  off_t before_len = ftello(file_);
+
+  ZipWriter::FileEntry entry;
+  ASSERT_EQ(0, writer.GetLastEntry(&entry));
+  ASSERT_EQ(0, writer.DiscardLastEntry());
+
+  ASSERT_EQ(0, writer.Finish());
+
+  off_t after_len = ftello(file_);
+
+  ASSERT_GT(before_len, after_len);
+}
+
+static ::testing::AssertionResult AssertFileEntryContentsEq(const std::string& expected,
+                                                            ZipArchiveHandle handle,
+                                                            ZipEntry* zip_entry) {
+  if (expected.size() != zip_entry->uncompressed_length) {
+    return ::testing::AssertionFailure() << "uncompressed entry size "
+        << zip_entry->uncompressed_length << " does not match expected size " << expected.size();
+  }
+
+  std::string actual;
+  actual.resize(expected.size());
+
+  uint8_t* buffer = reinterpret_cast<uint8_t*>(&*actual.begin());
+  if (ExtractToMemory(handle, zip_entry, buffer, actual.size()) != 0) {
+    return ::testing::AssertionFailure() << "failed to extract entry";
+  }
+
+  if (expected != actual) {
+    return ::testing::AssertionFailure() << "actual zip_entry data '" << actual
+        << "' does not match expected '" << expected << "'";
+  }
+  return ::testing::AssertionSuccess();
+}
diff --git a/logwrapper/Android.bp b/logwrapper/Android.bp
index 7ee0464..ccb1aa6 100644
--- a/logwrapper/Android.bp
+++ b/logwrapper/Android.bp
@@ -32,3 +32,22 @@
         "-Werror",
     ],
 }
+
+// ========================================================
+// Benchmark
+// ========================================================
+cc_benchmark {
+    name: "android_fork_execvp_ext_benchmark",
+    srcs: [
+        "android_fork_execvp_ext_benchmark.cpp",
+    ],
+    shared_libs: [
+        "libbase",
+        "libcutils",
+        "liblog",
+        "liblogwrap",
+    ],
+    cflags: [
+        "-Werror",
+    ]
+}
diff --git a/logwrapper/android_fork_execvp_ext_benchmark.cpp b/logwrapper/android_fork_execvp_ext_benchmark.cpp
new file mode 100644
index 0000000..1abd932
--- /dev/null
+++ b/logwrapper/android_fork_execvp_ext_benchmark.cpp
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "logwrap/logwrap.h"
+
+#include <android-base/logging.h>
+#include <benchmark/benchmark.h>
+
+static void BM_android_fork_execvp_ext(benchmark::State& state) {
+    const char* argv[] = {"/system/bin/echo", "hello", "world"};
+    const int argc = 3;
+    while (state.KeepRunning()) {
+        int rc = android_fork_execvp_ext(
+            argc, (char**)argv, NULL /* status */, false /* ignore_int_quit */, LOG_NONE,
+            false /* abbreviated */, NULL /* file_path */, NULL /* opts */, 0 /* opts_len */);
+        CHECK_EQ(0, rc);
+    }
+}
+BENCHMARK(BM_android_fork_execvp_ext);
+
+BENCHMARK_MAIN();
diff --git a/logwrapper/include/logwrap/logwrap.h b/logwrapper/include/logwrap/logwrap.h
index 89a8fdd..d3538b3 100644
--- a/logwrapper/include/logwrap/logwrap.h
+++ b/logwrapper/include/logwrap/logwrap.h
@@ -54,9 +54,8 @@
  *           the specified log until the child has exited.
  *   file_path: if log_target has the LOG_FILE bit set, then this parameter
  *           must be set to the pathname of the file to log to.
- *   opts: set to non-NULL if you want to use one or more of the
- *           FORK_EXECVP_OPTION_* features.
- *   opts_len: the length of the opts array. When opts is NULL, pass 0.
+ *   unused_opts: currently unused.
+ *   unused_opts_len: currently unused.
  *
  * Return value:
  *   0 when logwrap successfully run the child process and captured its status
@@ -72,30 +71,10 @@
 #define LOG_KLOG        2
 #define LOG_FILE        4
 
-/* Write data to child's stdin. */
-#define FORK_EXECVP_OPTION_INPUT             0
-/* Capture data from child's stdout and stderr. */
-#define FORK_EXECVP_OPTION_CAPTURE_OUTPUT    1
-
-struct AndroidForkExecvpOption {
-    int opt_type;
-    union {
-        struct {
-            const uint8_t* input;
-            size_t input_len;
-        } opt_input;
-        struct {
-            void (*on_output)(const uint8_t* /*output*/,
-                              size_t /*output_len*/,
-                              void* /* user_pointer */);
-            void* user_pointer;
-        } opt_capture_output;
-    };
-};
-
+// TODO: Remove unused_opts / unused_opts_len in a followup change.
 int android_fork_execvp_ext(int argc, char* argv[], int *status, bool ignore_int_quit,
-        int log_target, bool abbreviated, char *file_path,
-        const struct AndroidForkExecvpOption* opts, size_t opts_len);
+        int log_target, bool abbreviated, char *file_path, void* unused_opts,
+        int unused_opts_len);
 
 /* Similar to above, except abbreviated logging is not available, and if logwrap
  * is true, logging is to the Android system log, and if false, there is no
diff --git a/logwrapper/logwrap.c b/logwrapper/logwrap.c
index 3ad0983..7076078 100644
--- a/logwrapper/logwrap.c
+++ b/logwrapper/logwrap.c
@@ -291,8 +291,7 @@
 }
 
 static int parent(const char *tag, int parent_read, pid_t pid,
-        int *chld_sts, int log_target, bool abbreviated, char *file_path,
-        const struct AndroidForkExecvpOption* opts, size_t opts_len) {
+        int *chld_sts, int log_target, bool abbreviated, char *file_path) {
     int status = 0;
     char buffer[4096];
     struct pollfd poll_fds[] = {
@@ -359,13 +358,6 @@
             sz = TEMP_FAILURE_RETRY(
                 read(parent_read, &buffer[b], sizeof(buffer) - 1 - b));
 
-            for (size_t i = 0; sz > 0 && i < opts_len; ++i) {
-                if (opts[i].opt_type == FORK_EXECVP_OPTION_CAPTURE_OUTPUT) {
-                  opts[i].opt_capture_output.on_output(
-                      (uint8_t*)&buffer[b], sz, opts[i].opt_capture_output.user_pointer);
-                }
-            }
-
             sz += b;
             // Log one line at a time
             for (b = 0; b < sz; b++) {
@@ -483,7 +475,7 @@
 
 int android_fork_execvp_ext(int argc, char* argv[], int *status, bool ignore_int_quit,
         int log_target, bool abbreviated, char *file_path,
-        const struct AndroidForkExecvpOption* opts, size_t opts_len) {
+        void *unused_opts, int unused_opts_len) {
     pid_t pid;
     int parent_ptty;
     int child_ptty;
@@ -493,6 +485,9 @@
     sigset_t oldset;
     int rc = 0;
 
+    LOG_ALWAYS_FATAL_IF(unused_opts != NULL);
+    LOG_ALWAYS_FATAL_IF(unused_opts_len != 0);
+
     rc = pthread_mutex_lock(&fd_mutex);
     if (rc) {
         ERROR("failed to lock signal_fd mutex\n");
@@ -538,13 +533,6 @@
         pthread_sigmask(SIG_SETMASK, &oldset, NULL);
         close(parent_ptty);
 
-        // redirect stdin, stdout and stderr
-        for (size_t i = 0; i < opts_len; ++i) {
-            if (opts[i].opt_type == FORK_EXECVP_OPTION_INPUT) {
-                dup2(child_ptty, 0);
-                break;
-            }
-        }
         dup2(child_ptty, 1);
         dup2(child_ptty, 2);
         close(child_ptty);
@@ -561,24 +549,8 @@
             sigaction(SIGQUIT, &ignact, &quitact);
         }
 
-        for (size_t i = 0; i < opts_len; ++i) {
-            if (opts[i].opt_type == FORK_EXECVP_OPTION_INPUT) {
-                size_t left = opts[i].opt_input.input_len;
-                const uint8_t* input = opts[i].opt_input.input;
-                while (left > 0) {
-                    ssize_t res =
-                        TEMP_FAILURE_RETRY(write(parent_ptty, input, left));
-                    if (res < 0) {
-                        break;
-                    }
-                    left -= res;
-                    input += res;
-                }
-            }
-        }
-
         rc = parent(argv[0], parent_ptty, pid, status, log_target,
-                    abbreviated, file_path, opts, opts_len);
+                    abbreviated, file_path);
     }
 
     if (ignore_int_quit) {
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 25cea7f..0045fd6 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -150,15 +150,6 @@
     write /dev/cpuctl/cpu.rt_period_us 1000000
     write /dev/cpuctl/cpu.rt_runtime_us 950000
 
-    mkdir /dev/cpuctl/bg_non_interactive
-    chown system system /dev/cpuctl/bg_non_interactive/tasks
-    chmod 0666 /dev/cpuctl/bg_non_interactive/tasks
-    # 5.0 %
-    write /dev/cpuctl/bg_non_interactive/cpu.shares 52
-    write /dev/cpuctl/bg_non_interactive/cpu.rt_period_us 1000000
-    # active FIFO threads will never be in BG
-    write /dev/cpuctl/bg_non_interactive/cpu.rt_runtime_us 10000
-
     # sets up initial cpusets for ActivityManager
     mkdir /dev/cpuset
     mount cpuset none /dev/cpuset
@@ -417,6 +408,9 @@
     mkdir /data/misc/profman 0770 system shell
     mkdir /data/misc/gcov 0770 root root
 
+    mkdir /data/vendor 0771 root root
+    mkdir /data/vendor/hardware 0771 root root
+
     # For security reasons, /data/local/tmp should always be empty.
     # Do not place files or directories in /data/local/tmp
     mkdir /data/local/tmp 0771 shell shell
diff --git a/tzdatacheck/tzdatacheck.cpp b/tzdatacheck/tzdatacheck.cpp
index 769f0f5..381df5a 100644
--- a/tzdatacheck/tzdatacheck.cpp
+++ b/tzdatacheck/tzdatacheck.cpp
@@ -31,7 +31,7 @@
 #include "android-base/logging.h"
 
 // The name of the file containing the distro version information.
-// See also libcore.tzdata.update2.TimeZoneDistro / libcore.tzdata.update2.DistroVersion.
+// See also libcore.tzdata.shared2.TimeZoneDistro / libcore.tzdata.shared2.DistroVersion.
 static const char* DISTRO_VERSION_FILENAME = "/distro_version";
 
 // distro_version is an ASCII file consisting of 17 bytes in the form: AAA.BBB|CCCCC|DDD
@@ -42,14 +42,14 @@
 static const int DISTRO_VERSION_LENGTH = 13;
 
 // The major version of the distro format supported by this code as a null-terminated char[].
-// See also libcore.tzdata.update2.TimeZoneDistro / libcore.tzdata.update2.DistroVersion.
+// See also libcore.tzdata.shared2.TimeZoneDistro / libcore.tzdata.shared2.DistroVersion.
 static const char SUPPORTED_DISTRO_MAJOR_VERSION[] = "001";
 
 // The length of the distro format major version excluding the \0
 static const size_t SUPPORTED_DISTRO_MAJOR_VERSION_LEN = sizeof(SUPPORTED_DISTRO_MAJOR_VERSION) - 1;
 
 // The minor version of the distro format supported by this code as a null-terminated char[].
-// See also libcore.tzdata.update2.TimeZoneDistro / libcore.tzdata.update2.DistroVersion.
+// See also libcore.tzdata.shared2.TimeZoneDistro / libcore.tzdata.shared2.DistroVersion.
 static const char SUPPORTED_DISTRO_MINOR_VERSION[] = "001";
 
 // The length of the distro format minor version excluding the \0
@@ -65,7 +65,7 @@
 // Distro version bytes are: AAA.BBB|CCCCC - the rules version is CCCCC
 static const size_t DISTRO_VERSION_RULES_IDX = 8;
 
-// See also libcore.tzdata.update2.TimeZoneDistro.
+// See also libcore.tzdata.shared2.TimeZoneDistro.
 static const char* TZDATA_FILENAME = "/tzdata";
 
 // tzdata file header (as much as we need for the version):