Merge changes I8d0c60e5,Ib8ad0ad6

* changes:
  adb: boolify check_header and check_data.
  adb: redirect stdout/stderr before initializing usb.
diff --git a/adb/commandline.cpp b/adb/commandline.cpp
index f49c69d..68ae4af 100644
--- a/adb/commandline.cpp
+++ b/adb/commandline.cpp
@@ -126,8 +126,9 @@
         " reverse --remove-all     remove all reverse socket connections from device\n"
         "\n"
         "file transfer:\n"
-        " push LOCAL... REMOTE\n"
+        " push [--sync] LOCAL... REMOTE\n"
         "     copy local files/directories to device\n"
+        "     --sync: only push files that are newer on the host than the device\n"
         " pull [-a] REMOTE... LOCAL\n"
         "     copy files/dirs from device\n"
         "     -a: preserve file timestamp and mode\n"
@@ -1233,9 +1234,8 @@
     return 0;
 }
 
-static void parse_push_pull_args(const char** arg, int narg,
-                                 std::vector<const char*>* srcs,
-                                 const char** dst, bool* copy_attrs) {
+static void parse_push_pull_args(const char** arg, int narg, std::vector<const char*>* srcs,
+                                 const char** dst, bool* copy_attrs, bool* sync) {
     *copy_attrs = false;
 
     srcs->clear();
@@ -1248,6 +1248,10 @@
                 // Silently ignore for backwards compatibility.
             } else if (!strcmp(*arg, "-a")) {
                 *copy_attrs = true;
+            } else if (!strcmp(*arg, "--sync")) {
+                if (sync != nullptr) {
+                    *sync = true;
+                }
             } else if (!strcmp(*arg, "--")) {
                 ignore_flags = true;
             } else {
@@ -1654,19 +1658,20 @@
     }
     else if (!strcmp(argv[0], "push")) {
         bool copy_attrs = false;
+        bool sync = false;
         std::vector<const char*> srcs;
         const char* dst = nullptr;
 
-        parse_push_pull_args(&argv[1], argc - 1, &srcs, &dst, &copy_attrs);
+        parse_push_pull_args(&argv[1], argc - 1, &srcs, &dst, &copy_attrs, &sync);
         if (srcs.empty() || !dst) return syntax_error("push requires an argument");
-        return do_sync_push(srcs, dst) ? 0 : 1;
+        return do_sync_push(srcs, dst, sync) ? 0 : 1;
     }
     else if (!strcmp(argv[0], "pull")) {
         bool copy_attrs = false;
         std::vector<const char*> srcs;
         const char* dst = ".";
 
-        parse_push_pull_args(&argv[1], argc - 1, &srcs, &dst, &copy_attrs);
+        parse_push_pull_args(&argv[1], argc - 1, &srcs, &dst, &copy_attrs, nullptr);
         if (srcs.empty()) return syntax_error("pull requires an argument");
         return do_sync_pull(srcs, dst, copy_attrs) ? 0 : 1;
     }
@@ -2086,7 +2091,7 @@
     std::vector<const char*> apk_file = {argv[last_apk]};
     std::string apk_dest = android::base::StringPrintf(
         where, android::base::Basename(argv[last_apk]).c_str());
-    if (!do_sync_push(apk_file, apk_dest.c_str())) goto cleanup_apk;
+    if (!do_sync_push(apk_file, apk_dest.c_str(), false)) goto cleanup_apk;
     argv[last_apk] = apk_dest.c_str(); /* destination name, not source location */
     result = pm_command(transport, serial, argc, argv);
 
diff --git a/adb/file_sync_client.cpp b/adb/file_sync_client.cpp
index 22bd2f2..2576fb1 100644
--- a/adb/file_sync_client.cpp
+++ b/adb/file_sync_client.cpp
@@ -674,11 +674,22 @@
     return true;
 }
 
-static bool sync_send(SyncConnection& sc, const char* lpath, const char* rpath,
-                      unsigned mtime, mode_t mode)
-{
+static bool sync_send(SyncConnection& sc, const char* lpath, const char* rpath, unsigned mtime,
+                      mode_t mode, bool sync) {
     std::string path_and_mode = android::base::StringPrintf("%s,%d", rpath, mode);
 
+    if (sync) {
+        struct stat st;
+        if (sync_lstat(sc, rpath, &st)) {
+            // For links, we cannot update the atime/mtime.
+            if ((S_ISREG(mode & st.st_mode) && st.st_mtime == static_cast<time_t>(mtime)) ||
+                (S_ISLNK(mode & st.st_mode) && st.st_mtime >= static_cast<time_t>(mtime))) {
+                sc.RecordFilesSkipped(1);
+                return true;
+            }
+        }
+    }
+
     if (S_ISLNK(mode)) {
 #if !defined(_WIN32)
         char buf[PATH_MAX];
@@ -902,7 +913,7 @@
             if (list_only) {
                 sc.Println("would push: %s -> %s", ci.lpath.c_str(), ci.rpath.c_str());
             } else {
-                if (!sync_send(sc, ci.lpath.c_str(), ci.rpath.c_str(), ci.time, ci.mode)) {
+                if (!sync_send(sc, ci.lpath.c_str(), ci.rpath.c_str(), ci.time, ci.mode, false)) {
                     return false;
                 }
             }
@@ -916,7 +927,7 @@
     return true;
 }
 
-bool do_sync_push(const std::vector<const char*>& srcs, const char* dst) {
+bool do_sync_push(const std::vector<const char*>& srcs, const char* dst, bool sync) {
     SyncConnection sc;
     if (!sc.IsValid()) return false;
 
@@ -981,7 +992,7 @@
                 dst_dir.append(android::base::Basename(src_path));
             }
 
-            success &= copy_local_dir_remote(sc, src_path, dst_dir.c_str(), false, false);
+            success &= copy_local_dir_remote(sc, src_path, dst_dir.c_str(), sync, false);
             continue;
         } else if (!should_push_file(st.st_mode)) {
             sc.Warning("skipping special file '%s' (mode = 0o%o)", src_path, st.st_mode);
@@ -1002,7 +1013,7 @@
 
         sc.NewTransfer();
         sc.SetExpectedTotalBytes(st.st_size);
-        success &= sync_send(sc, src_path, dst_path, st.st_mtime, st.st_mode);
+        success &= sync_send(sc, src_path, dst_path, st.st_mtime, st.st_mode, sync);
         sc.ReportTransferRate(src_path, TransferDirection::push);
     }
 
diff --git a/adb/file_sync_service.h b/adb/file_sync_service.h
index 90f1965..6606efd 100644
--- a/adb/file_sync_service.h
+++ b/adb/file_sync_service.h
@@ -81,7 +81,7 @@
 
 void file_sync_service(int fd, void* cookie);
 bool do_sync_ls(const char* path);
-bool do_sync_push(const std::vector<const char*>& srcs, const char* dst);
+bool do_sync_push(const std::vector<const char*>& srcs, const char* dst, bool sync);
 bool do_sync_pull(const std::vector<const char*>& srcs, const char* dst,
                   bool copy_attrs, const char* name=nullptr);
 
diff --git a/adb/set_verity_enable_state_service.cpp b/adb/set_verity_enable_state_service.cpp
index b2b1c18..253d14a 100644
--- a/adb/set_verity_enable_state_service.cpp
+++ b/adb/set_verity_enable_state_service.cpp
@@ -139,25 +139,36 @@
     bool any_changed = false;
 
     bool enable = (cookie != NULL);
-    if (!kAllowDisableVerity) {
-        WriteFdFmt(fd, "%s-verity only works for userdebug builds\n",
-                   enable ? "enable" : "disable");
+
+    // Figure out if we're using VB1.0 or VB2.0 (aka AVB) - by
+    // contract, androidboot.vbmeta.digest is set by the bootloader
+    // when using AVB).
+    bool using_avb = !android::base::GetProperty("ro.boot.vbmeta.digest", "").empty();
+
+    // If using AVB, dm-verity is used on any build so we want it to
+    // be possible to disable/enable on any build (except USER). For
+    // VB1.0 dm-verity is only enabled on certain builds.
+    if (!using_avb) {
+        if (!kAllowDisableVerity) {
+            WriteFdFmt(fd, "%s-verity only works for userdebug builds\n",
+                       enable ? "enable" : "disable");
+        }
+
+        if (!android::base::GetBoolProperty("ro.secure", false)) {
+            WriteFdFmt(fd, "verity not enabled - ENG build\n");
+            return;
+        }
     }
 
-    if (!android::base::GetBoolProperty("ro.secure", false)) {
-        WriteFdFmt(fd, "verity not enabled - ENG build\n");
-        return;
-    }
+    // Should never be possible to disable dm-verity on a USER build
+    // regardless of using AVB or VB1.0.
     if (!__android_log_is_debuggable()) {
         WriteFdFmt(fd, "verity cannot be disabled/enabled - USER build\n");
         return;
     }
 
-    // Figure out if we're using VB1.0 or VB2.0 (aka AVB).
-    std::string vbmeta_hash = android::base::GetProperty("ro.boot.vbmeta.digest", "");
-    if (vbmeta_hash != "") {
-        // Yep, the system is using AVB (by contract, androidboot.vbmeta.hash is
-        // set by the bootloader when using AVB).
+    if (using_avb) {
+        // Yep, the system is using AVB.
         AvbOps* ops = avb_ops_user_new();
         if (ops == nullptr) {
             WriteFdFmt(fd, "Error getting AVB ops\n");
diff --git a/adb/test_device.py b/adb/test_device.py
index e44cc83..737d0c2 100644
--- a/adb/test_device.py
+++ b/adb/test_device.py
@@ -1130,8 +1130,18 @@
             if host_dir is not None:
                 shutil.rmtree(host_dir)
 
+    def verify_sync(self, device, temp_files, device_dir):
+        """Verifies that a list of temp files was synced to the device."""
+        # Confirm that every file on the device mirrors that on the host.
+        for temp_file in temp_files:
+            device_full_path = posixpath.join(
+                device_dir, temp_file.base_name)
+            dev_md5, _ = device.shell(
+                [get_md5_prog(self.device), device_full_path])[0].split()
+            self.assertEqual(temp_file.checksum, dev_md5)
+
     def test_sync(self):
-        """Sync a randomly generated directory of files to specified device."""
+        """Sync a host directory to the data partition."""
 
         try:
             base_dir = tempfile.mkdtemp()
@@ -1141,27 +1151,50 @@
             os.makedirs(full_dir_path)
 
             # Create 32 random files within the host mirror.
-            temp_files = make_random_host_files(in_dir=full_dir_path, num_files=32)
+            temp_files = make_random_host_files(
+                in_dir=full_dir_path, num_files=32)
 
-            # Clean up any trash on the device.
-            device = adb.get_device(product=base_dir)
+            # Clean up any stale files on the device.
+            device = adb.get_device()  # pylint: disable=no-member
             device.shell(['rm', '-rf', self.DEVICE_TEMP_DIR])
 
+            old_product_out = os.environ.get('ANDROID_PRODUCT_OUT')
+            os.environ['ANDROID_PRODUCT_OUT'] = base_dir
             device.sync('data')
+            if old_product_out is None:
+                del os.environ['ANDROID_PRODUCT_OUT']
+            else:
+                os.environ['ANDROID_PRODUCT_OUT'] = old_product_out
 
-            # Confirm that every file on the device mirrors that on the host.
-            for temp_file in temp_files:
-                device_full_path = posixpath.join(self.DEVICE_TEMP_DIR,
-                                                  temp_file.base_name)
-                dev_md5, _ = device.shell(
-                    [get_md5_prog(self.device), device_full_path])[0].split()
-                self.assertEqual(temp_file.checksum, dev_md5)
+            self.verify_sync(device, temp_files, self.DEVICE_TEMP_DIR)
 
-            self.device.shell(['rm', '-rf', self.DEVICE_TEMP_DIR])
+            #self.device.shell(['rm', '-rf', self.DEVICE_TEMP_DIR])
         finally:
             if base_dir is not None:
                 shutil.rmtree(base_dir)
 
+    def test_push_sync(self):
+        """Sync a host directory to a specific path."""
+
+        try:
+            temp_dir = tempfile.mkdtemp()
+            temp_files = make_random_host_files(in_dir=temp_dir, num_files=32)
+
+            device_dir = posixpath.join(self.DEVICE_TEMP_DIR, 'sync_src_dst')
+
+            # Clean up any stale files on the device.
+            device = adb.get_device()  # pylint: disable=no-member
+            device.shell(['rm', '-rf', device_dir])
+
+            device.push(temp_dir, device_dir, sync=True)
+
+            self.verify_sync(device, temp_files, device_dir)
+
+            self.device.shell(['rm', '-rf', self.DEVICE_TEMP_DIR])
+        finally:
+            if temp_dir is not None:
+                shutil.rmtree(temp_dir)
+
     def test_unicode_paths(self):
         """Ensure that we can support non-ASCII paths, even on Windows."""
         name = u'로보카 폴리'
diff --git a/base/Android.bp b/base/Android.bp
index 81b96db..b636dc3 100644
--- a/base/Android.bp
+++ b/base/Android.bp
@@ -53,7 +53,6 @@
 
     header_libs: [
         "libbase_headers",
-        "libutils_headers",
     ],
     export_header_lib_headers: ["libbase_headers"],
 
diff --git a/base/file.cpp b/base/file.cpp
index 7fbebc5..a2f2887 100644
--- a/base/file.cpp
+++ b/base/file.cpp
@@ -32,13 +32,14 @@
 #include "android-base/macros.h"  // For TEMP_FAILURE_RETRY on Darwin.
 #include "android-base/unique_fd.h"
 #include "android-base/utf8.h"
-#include "utils/Compat.h"
 
 #if defined(__APPLE__)
 #include <mach-o/dyld.h>
 #endif
 #if defined(_WIN32)
 #include <windows.h>
+#define O_CLOEXEC O_NOINHERIT
+#define O_NOFOLLOW 0
 #endif
 
 namespace android {
@@ -133,7 +134,7 @@
                        bool follow_symlinks) {
   int flags = O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_BINARY |
               (follow_symlinks ? 0 : O_NOFOLLOW);
-  android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(path.c_str(), flags, DEFFILEMODE)));
+  android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(path.c_str(), flags, 0666)));
   if (fd == -1) {
     return false;
   }
diff --git a/debuggerd/include/debuggerd/protocol.h b/debuggerd/include/debuggerd/protocol.h
index 0756876..144efc8 100644
--- a/debuggerd/include/debuggerd/protocol.h
+++ b/debuggerd/include/debuggerd/protocol.h
@@ -21,6 +21,7 @@
 // Sockets in the ANDROID_SOCKET_NAMESPACE_RESERVED namespace.
 // Both sockets are SOCK_SEQPACKET sockets, so no explicit length field is needed.
 constexpr char kTombstonedCrashSocketName[] = "tombstoned_crash";
+constexpr char kTombstonedJavaTraceSocketName[] = "tombstoned_java_trace";
 constexpr char kTombstonedInterceptSocketName[] = "tombstoned_intercept";
 
 enum class CrashPacketType : uint8_t {
diff --git a/debuggerd/include/debuggerd/tombstoned.h b/debuggerd/include/debuggerd/tombstoned.h
index d158d50..908517d 100644
--- a/debuggerd/include/debuggerd/tombstoned.h
+++ b/debuggerd/include/debuggerd/tombstoned.h
@@ -21,6 +21,6 @@
 #include <android-base/unique_fd.h>
 
 bool tombstoned_connect(pid_t pid, android::base::unique_fd* tombstoned_socket,
-                        android::base::unique_fd* output_fd);
+                        android::base::unique_fd* output_fd, bool is_native_crash = true);
 
 bool tombstoned_notify_completion(int tombstoned_socket);
diff --git a/debuggerd/tombstoned/tombstoned.cpp b/debuggerd/tombstoned/tombstoned.cpp
index 2248a21..80dbef5 100644
--- a/debuggerd/tombstoned/tombstoned.cpp
+++ b/debuggerd/tombstoned/tombstoned.cpp
@@ -50,86 +50,154 @@
   kCrashStatusQueued,
 };
 
+struct Crash;
+
+class CrashType {
+ public:
+  CrashType(const std::string& dir_path, const std::string& file_name_prefix, size_t max_artifacts,
+            size_t max_concurrent_dumps)
+      : file_name_prefix_(file_name_prefix),
+        dir_path_(dir_path),
+        dir_fd_(open(dir_path.c_str(), O_DIRECTORY | O_RDONLY | O_CLOEXEC)),
+        max_artifacts_(max_artifacts),
+        next_artifact_(0),
+        max_concurrent_dumps_(max_concurrent_dumps),
+        num_concurrent_dumps_(0) {
+    if (dir_fd_ == -1) {
+      PLOG(FATAL) << "failed to open directory: " << dir_path;
+    }
+
+    // NOTE: If max_artifacts_ <= max_concurrent_dumps_, then theoretically the
+    // same filename could be handed out to multiple processes.
+    CHECK(max_artifacts_ > max_concurrent_dumps_);
+
+    find_oldest_artifact();
+  }
+
+  unique_fd get_output_fd() {
+    unique_fd result;
+    char buf[PATH_MAX];
+    snprintf(buf, sizeof(buf), "%s%02d", file_name_prefix_.c_str(), next_artifact_);
+    // Unlink and create the file, instead of using O_TRUNC, to avoid two processes
+    // interleaving their output in case we ever get into that situation.
+    if (unlinkat(dir_fd_, buf, 0) != 0 && errno != ENOENT) {
+      PLOG(FATAL) << "failed to unlink tombstone at " << dir_path_ << buf;
+    }
+
+    result.reset(openat(dir_fd_, buf, O_CREAT | O_EXCL | O_WRONLY | O_APPEND | O_CLOEXEC, 0640));
+    if (result == -1) {
+      PLOG(FATAL) << "failed to create tombstone at " << dir_path_ << buf;
+    }
+
+    next_artifact_ = (next_artifact_ + 1) % max_artifacts_;
+    return result;
+  }
+
+  bool maybe_enqueue_crash(Crash* crash) {
+    if (num_concurrent_dumps_ == max_concurrent_dumps_) {
+      queued_requests_.push_back(crash);
+      return true;
+    }
+
+    return false;
+  }
+
+  void maybe_dequeue_crashes(void (*handler)(Crash* crash)) {
+    while (!queued_requests_.empty() && num_concurrent_dumps_ < max_concurrent_dumps_) {
+      Crash* next_crash = queued_requests_.front();
+      queued_requests_.pop_front();
+      handler(next_crash);
+    }
+  }
+
+  void on_crash_started() { ++num_concurrent_dumps_; }
+
+  void on_crash_completed() { --num_concurrent_dumps_; }
+
+  static CrashType* const tombstone;
+  static CrashType* const java_trace;
+
+ private:
+  void find_oldest_artifact() {
+    size_t oldest_tombstone = 0;
+    time_t oldest_time = std::numeric_limits<time_t>::max();
+
+    for (size_t i = 0; i < max_artifacts_; ++i) {
+      std::string path = android::base::StringPrintf("%s/%s%02zu", dir_path_.c_str(),
+                                                     file_name_prefix_.c_str(), i);
+      struct stat st;
+      if (stat(path.c_str(), &st) != 0) {
+        if (errno == ENOENT) {
+          oldest_tombstone = i;
+          break;
+        } else {
+          PLOG(ERROR) << "failed to stat " << path;
+          continue;
+        }
+      }
+
+      if (st.st_mtime < oldest_time) {
+        oldest_tombstone = i;
+        oldest_time = st.st_mtime;
+      }
+    }
+
+    next_artifact_ = oldest_tombstone;
+  }
+
+  const std::string file_name_prefix_;
+
+  const std::string dir_path_;
+  const int dir_fd_;
+
+  const size_t max_artifacts_;
+  int next_artifact_;
+
+  const size_t max_concurrent_dumps_;
+  size_t num_concurrent_dumps_;
+
+  std::deque<Crash*> queued_requests_;
+
+  DISALLOW_COPY_AND_ASSIGN(CrashType);
+};
+
+// Whether java trace dumps are produced via tombstoned.
+static constexpr bool kJavaTraceDumpsEnabled = false;
+
+/* static */ CrashType* const CrashType::tombstone =
+    new CrashType("/data/tombstones", "tombstone_" /* file_name_prefix */, 10 /* max_artifacts */,
+                  1 /* max_concurrent_dumps */);
+
+/* static */ CrashType* const CrashType::java_trace =
+    (kJavaTraceDumpsEnabled ? new CrashType("/data/anr", "anr_" /* file_name_prefix */,
+                                            64 /* max_artifacts */, 4 /* max_concurrent_dumps */)
+                            : nullptr);
+
 // Ownership of Crash is a bit messy.
 // It's either owned by an active event that must have a timeout, or owned by
 // queued_requests, in the case that multiple crashes come in at the same time.
 struct Crash {
-  ~Crash() {
-    event_free(crash_event);
-  }
+  ~Crash() { event_free(crash_event); }
 
   unique_fd crash_fd;
   pid_t crash_pid;
   event* crash_event = nullptr;
+
+  // Not owned by |Crash|.
+  CrashType* crash_type = nullptr;
 };
 
-static constexpr char kTombstoneDirectory[] = "/data/tombstones/";
-static constexpr size_t kTombstoneCount = 10;
-static int tombstone_directory_fd = -1;
-static int next_tombstone = 0;
-
-static constexpr size_t kMaxConcurrentDumps = 1;
-static size_t num_concurrent_dumps = 0;
-
-static std::deque<Crash*> queued_requests;
-
 // Forward declare the callbacks so they can be placed in a sensible order.
 static void crash_accept_cb(evconnlistener* listener, evutil_socket_t sockfd, sockaddr*, int, void*);
 static void crash_request_cb(evutil_socket_t sockfd, short ev, void* arg);
 static void crash_completed_cb(evutil_socket_t sockfd, short ev, void* arg);
 
-static void find_oldest_tombstone() {
-  size_t oldest_tombstone = 0;
-  time_t oldest_time = std::numeric_limits<time_t>::max();
-
-  for (size_t i = 0; i < kTombstoneCount; ++i) {
-    std::string path = android::base::StringPrintf("%stombstone_%02zu", kTombstoneDirectory, i);
-    struct stat st;
-    if (stat(path.c_str(), &st) != 0) {
-      if (errno == ENOENT) {
-        oldest_tombstone = i;
-        break;
-      } else {
-        PLOG(ERROR) << "failed to stat " << path;
-        continue;
-      }
-    }
-
-    if (st.st_mtime < oldest_time) {
-      oldest_tombstone = i;
-      oldest_time = st.st_mtime;
-    }
-  }
-
-  next_tombstone = oldest_tombstone;
-}
-
-static unique_fd get_tombstone_fd() {
-  // If kMaxConcurrentDumps is greater than 1, then theoretically the same
-  // filename could be handed out to multiple processes. Unlink and create the
-  // file, instead of using O_TRUNC, to avoid two processes interleaving their
-  // output.
-  unique_fd result;
-  char buf[PATH_MAX];
-  snprintf(buf, sizeof(buf), "tombstone_%02d", next_tombstone);
-  if (unlinkat(tombstone_directory_fd, buf, 0) != 0 && errno != ENOENT) {
-    PLOG(FATAL) << "failed to unlink tombstone at " << kTombstoneDirectory << buf;
-  }
-
-  result.reset(
-    openat(tombstone_directory_fd, buf, O_CREAT | O_EXCL | O_WRONLY | O_APPEND | O_CLOEXEC, 0640));
-  if (result == -1) {
-    PLOG(FATAL) << "failed to create tombstone at " << kTombstoneDirectory << buf;
-  }
-
-  next_tombstone = (next_tombstone + 1) % kTombstoneCount;
-  return result;
-}
-
 static void perform_request(Crash* crash) {
   unique_fd output_fd;
-  if (!intercept_manager->GetIntercept(crash->crash_pid, &output_fd)) {
-    output_fd = get_tombstone_fd();
+  // Note that java traces are not interceptible.
+  if ((crash->crash_type == CrashType::java_trace) ||
+      !intercept_manager->GetIntercept(crash->crash_pid, &output_fd)) {
+    output_fd = crash->crash_type->get_output_fd();
   }
 
   TombstonedCrashPacket response = {
@@ -152,23 +220,15 @@
     event_add(crash->crash_event, &timeout);
   }
 
-  ++num_concurrent_dumps;
+  crash->crash_type->on_crash_started();
   return;
 
 fail:
   delete crash;
 }
 
-static void dequeue_requests() {
-  while (!queued_requests.empty() && num_concurrent_dumps < kMaxConcurrentDumps) {
-    Crash* next_crash = queued_requests.front();
-    queued_requests.pop_front();
-    perform_request(next_crash);
-  }
-}
-
 static void crash_accept_cb(evconnlistener* listener, evutil_socket_t sockfd, sockaddr*, int,
-                            void*) {
+                            void* crash_type) {
   event_base* base = evconnlistener_get_base(listener);
   Crash* crash = new Crash();
 
@@ -176,12 +236,15 @@
   event* crash_event = event_new(base, sockfd, EV_TIMEOUT | EV_READ, crash_request_cb, crash);
   crash->crash_fd.reset(sockfd);
   crash->crash_event = crash_event;
+  crash->crash_type = static_cast<CrashType*>(crash_type);
   event_add(crash_event, &timeout);
 }
 
 static void crash_request_cb(evutil_socket_t sockfd, short ev, void* arg) {
   ssize_t rc;
   Crash* crash = static_cast<Crash*>(arg);
+  CrashType* type = crash->crash_type;
+
   TombstonedCrashPacket request = {};
 
   if ((ev & EV_TIMEOUT) != 0) {
@@ -208,12 +271,27 @@
     goto fail;
   }
 
-  crash->crash_pid = request.packet.dump_request.pid;
+  if (type == CrashType::tombstone) {
+    crash->crash_pid = request.packet.dump_request.pid;
+  } else {
+    // Requests for java traces are sent from untrusted processes, so we
+    // must not trust the PID sent down with the request. Instead, we ask the
+    // kernel.
+    ucred cr = {};
+    socklen_t len = sizeof(cr);
+    int ret = getsockopt(sockfd, SOL_SOCKET, SO_PEERCRED, &cr, &len);
+    if (ret != 0) {
+      PLOG(ERROR) << "Failed to getsockopt(..SO_PEERCRED)";
+      goto fail;
+    }
+
+    crash->crash_pid = cr.pid;
+  }
+
   LOG(INFO) << "received crash request for pid " << crash->crash_pid;
 
-  if (num_concurrent_dumps == kMaxConcurrentDumps) {
+  if (type->maybe_enqueue_crash(crash)) {
     LOG(INFO) << "enqueueing crash request for pid " << crash->crash_pid;
-    queued_requests.push_back(crash);
   } else {
     perform_request(crash);
   }
@@ -229,7 +307,7 @@
   Crash* crash = static_cast<Crash*>(arg);
   TombstonedCrashPacket request = {};
 
-  --num_concurrent_dumps;
+  crash->crash_type->on_crash_completed();
 
   if ((ev & EV_READ) == 0) {
     goto fail;
@@ -252,10 +330,11 @@
   }
 
 fail:
+  CrashType* type = crash->crash_type;
   delete crash;
 
   // If there's something queued up, let them proceed.
-  dequeue_requests();
+  type->maybe_dequeue_crashes(perform_request);
 }
 
 int main(int, char* []) {
@@ -269,13 +348,6 @@
   };
   debuggerd_register_handlers(&action);
 
-  tombstone_directory_fd = open(kTombstoneDirectory, O_DIRECTORY | O_RDONLY | O_CLOEXEC);
-  if (tombstone_directory_fd == -1) {
-    PLOG(FATAL) << "failed to open tombstone directory";
-  }
-
-  find_oldest_tombstone();
-
   int intercept_socket = android_get_control_socket(kTombstonedInterceptSocketName);
   int crash_socket = android_get_control_socket(kTombstonedCrashSocketName);
 
@@ -293,10 +365,24 @@
 
   intercept_manager = new InterceptManager(base, intercept_socket);
 
-  evconnlistener* listener =
-    evconnlistener_new(base, crash_accept_cb, nullptr, -1, LEV_OPT_CLOSE_ON_FREE, crash_socket);
-  if (!listener) {
-    LOG(FATAL) << "failed to create evconnlistener";
+  evconnlistener* tombstone_listener = evconnlistener_new(
+      base, crash_accept_cb, CrashType::tombstone, -1, LEV_OPT_CLOSE_ON_FREE, crash_socket);
+  if (!tombstone_listener) {
+    LOG(FATAL) << "failed to create evconnlistener for tombstones.";
+  }
+
+  if (kJavaTraceDumpsEnabled) {
+    const int java_trace_socket = android_get_control_socket(kTombstonedJavaTraceSocketName);
+    if (java_trace_socket == -1) {
+      PLOG(FATAL) << "failed to get socket from init";
+    }
+
+    evutil_make_socket_nonblocking(java_trace_socket);
+    evconnlistener* java_trace_listener = evconnlistener_new(
+        base, crash_accept_cb, CrashType::java_trace, -1, LEV_OPT_CLOSE_ON_FREE, java_trace_socket);
+    if (!java_trace_listener) {
+      LOG(FATAL) << "failed to create evconnlistener for java traces.";
+    }
   }
 
   LOG(INFO) << "tombstoned successfully initialized";
diff --git a/debuggerd/tombstoned/tombstoned.rc b/debuggerd/tombstoned/tombstoned.rc
index b8345ca..53ef01c 100644
--- a/debuggerd/tombstoned/tombstoned.rc
+++ b/debuggerd/tombstoned/tombstoned.rc
@@ -7,4 +7,5 @@
 
     socket tombstoned_crash seqpacket 0666 system system
     socket tombstoned_intercept seqpacket 0666 system system
+    socket tombstoned_java_trace seqpacket 0666 system system
     writepid /dev/cpuset/system-background/tasks
diff --git a/debuggerd/tombstoned_client.cpp b/debuggerd/tombstoned_client.cpp
index 4741fa6..e878b6a 100644
--- a/debuggerd/tombstoned_client.cpp
+++ b/debuggerd/tombstoned_client.cpp
@@ -30,9 +30,11 @@
 
 using android::base::unique_fd;
 
-bool tombstoned_connect(pid_t pid, unique_fd* tombstoned_socket, unique_fd* output_fd) {
-  unique_fd sockfd(socket_local_client(kTombstonedCrashSocketName,
-                                       ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_SEQPACKET));
+bool tombstoned_connect(pid_t pid, unique_fd* tombstoned_socket, unique_fd* output_fd,
+                        bool is_native_crash) {
+  unique_fd sockfd(socket_local_client(
+      (is_native_crash ? kTombstonedCrashSocketName : kTombstonedJavaTraceSocketName),
+      ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_SEQPACKET));
   if (sockfd == -1) {
     async_safe_format_log(ANDROID_LOG_ERROR, "libc", "failed to connect to tombstoned: %s",
                           strerror(errno));
diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp
index e1f289a..3e890c7 100644
--- a/fastboot/fastboot.cpp
+++ b/fastboot/fastboot.cpp
@@ -1260,10 +1260,10 @@
     fb_queue_command("flashing unlock_bootloader", "unlocking bootloader");
 }
 
-static void do_oem_command(std::vector<std::string>* args) {
+static void do_oem_command(const std::string& cmd, std::vector<std::string>* args) {
     if (args->empty()) syntax_error("empty oem command");
 
-    std::string command("oem");
+    std::string command(cmd);
     while (!args->empty()) {
         command += " " + next_arg(args);
     }
@@ -1766,7 +1766,7 @@
             std::string filename = next_arg(&args);
             fb_queue_upload(filename.c_str());
         } else if (command == "oem") {
-            do_oem_command(&args);
+            do_oem_command("oem", &args);
         } else if (command == "flashing") {
             if (args.empty()) {
                 syntax_error("missing 'flashing' command");
@@ -1776,7 +1776,7 @@
                                             args[0] == "get_unlock_ability" ||
                                             args[0] == "get_unlock_bootloader_nonce" ||
                                             args[0] == "lock_bootloader")) {
-                do_oem_command(&args);
+                do_oem_command("flashing", &args);
             } else if (args.size() == 2 && args[0] == "unlock_bootloader") {
                 do_bypass_unlock_command(&args);
             } else {
diff --git a/fs_mgr/Android.bp b/fs_mgr/Android.bp
new file mode 100644
index 0000000..0af6159
--- /dev/null
+++ b/fs_mgr/Android.bp
@@ -0,0 +1,62 @@
+//
+// 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.
+//
+
+cc_defaults {
+    name: "fs_mgr_defaults",
+    sanitize: {
+        misc_undefined: ["integer"],
+    },
+    local_include_dirs: ["include/"],
+    cppflags: ["-Werror"],
+    static_libs: [
+        "liblogwrap",
+        "libfec",
+        "libfec_rs",
+        "libbase",
+        "libcrypto_utils",
+        "libcrypto",
+        "libext4_utils",
+        "libsquashfs_utils",
+        "libselinux",
+        "libavb",
+    ],
+}
+
+cc_library_static {
+    name: "libfs_mgr",
+    defaults: ["fs_mgr_defaults"],
+    export_include_dirs: ["include"],
+    include_dirs: ["system/vold"],
+    srcs: [
+        "fs_mgr.cpp",
+        "fs_mgr_dm_ioctl.cpp",
+        "fs_mgr_format.cpp",
+        "fs_mgr_fstab.cpp",
+        "fs_mgr_slotselect.cpp",
+        "fs_mgr_verity.cpp",
+        "fs_mgr_avb.cpp",
+        "fs_mgr_avb_ops.cpp",
+        "fs_mgr_boot_config.cpp",
+    ],
+    product_variables: {
+        debuggable: {
+            cppflags: ["-DALLOW_ADBD_DISABLE_VERITY=1"],
+        },
+        eng: {
+            cppflags: ["-DALLOW_SKIP_SECURE_CHECK=1"],
+        },
+    },
+}
diff --git a/fs_mgr/Android.mk b/fs_mgr/Android.mk
index 2863a26..f3ca724 100644
--- a/fs_mgr/Android.mk
+++ b/fs_mgr/Android.mk
@@ -17,35 +17,6 @@
 include $(CLEAR_VARS)
 LOCAL_CLANG := true
 LOCAL_SANITIZE := integer
-LOCAL_SRC_FILES:= \
-    fs_mgr.cpp \
-    fs_mgr_dm_ioctl.cpp \
-    fs_mgr_format.cpp \
-    fs_mgr_fstab.cpp \
-    fs_mgr_slotselect.cpp \
-    fs_mgr_verity.cpp \
-    fs_mgr_avb.cpp \
-    fs_mgr_avb_ops.cpp \
-    fs_mgr_boot_config.cpp
-LOCAL_C_INCLUDES := \
-    $(LOCAL_PATH)/include \
-    system/vold \
-    system/extras/ext4_utils
-LOCAL_MODULE:= libfs_mgr
-LOCAL_STATIC_LIBRARIES := $(common_static_libraries)
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
-LOCAL_CFLAGS := -Werror
-ifneq (,$(filter userdebug,$(TARGET_BUILD_VARIANT)))
-LOCAL_CFLAGS += -DALLOW_ADBD_DISABLE_VERITY=1
-endif
-ifneq (,$(filter eng,$(TARGET_BUILD_VARIANT)))
-LOCAL_CFLAGS += -DALLOW_SKIP_SECURE_CHECK=1
-endif
-include $(BUILD_STATIC_LIBRARY)
-
-include $(CLEAR_VARS)
-LOCAL_CLANG := true
-LOCAL_SANITIZE := integer
 LOCAL_SRC_FILES:= fs_mgr_main.cpp
 LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
 LOCAL_MODULE:= fs_mgr
diff --git a/fs_mgr/fs_mgr_avb.cpp b/fs_mgr/fs_mgr_avb.cpp
index 2b32201..6618003 100644
--- a/fs_mgr/fs_mgr_avb.cpp
+++ b/fs_mgr/fs_mgr_avb.cpp
@@ -16,15 +16,14 @@
 
 #include "fs_mgr_avb.h"
 
-#include <errno.h>
 #include <fcntl.h>
-#include <inttypes.h>
 #include <libgen.h>
-#include <stdio.h>
 #include <string.h>
-#include <sys/stat.h>
+#include <sys/ioctl.h>
 #include <sys/types.h>
-#include <unistd.h>
+
+#include <sstream>
+#include <string>
 #include <vector>
 
 #include <android-base/file.h>
@@ -33,11 +32,7 @@
 #include <android-base/stringprintf.h>
 #include <android-base/strings.h>
 #include <android-base/unique_fd.h>
-#include <cutils/properties.h>
 #include <libavb/libavb.h>
-#include <openssl/sha.h>
-#include <sys/ioctl.h>
-#include <utils/Compat.h>
 
 #include "fs_mgr.h"
 #include "fs_mgr_priv.h"
@@ -45,48 +40,6 @@
 #include "fs_mgr_priv_dm_ioctl.h"
 #include "fs_mgr_priv_sha.h"
 
-/* The format of dm-verity construction parameters:
- *     <version> <dev> <hash_dev> <data_block_size> <hash_block_size>
- *     <num_data_blocks> <hash_start_block> <algorithm> <digest> <salt>
- */
-#define VERITY_TABLE_FORMAT \
-    "%u %s %s %u %u "       \
-    "%" PRIu64 " %" PRIu64 " %s %s %s "
-
-#define VERITY_TABLE_PARAMS(hashtree_desc, blk_device, digest, salt)                        \
-    hashtree_desc.dm_verity_version, blk_device, blk_device, hashtree_desc.data_block_size, \
-        hashtree_desc.hash_block_size,                                                      \
-        hashtree_desc.image_size / hashtree_desc.data_block_size,  /* num_data_blocks. */   \
-        hashtree_desc.tree_offset / hashtree_desc.hash_block_size, /* hash_start_block. */  \
-        (char*)hashtree_desc.hash_algorithm, digest, salt
-
-#define VERITY_TABLE_OPT_RESTART "restart_on_corruption"
-#define VERITY_TABLE_OPT_IGNZERO "ignore_zero_blocks"
-
-/* The default format of dm-verity optional parameters:
- *     <#opt_params> ignore_zero_blocks restart_on_corruption
- */
-#define VERITY_TABLE_OPT_DEFAULT_FORMAT "2 %s %s"
-#define VERITY_TABLE_OPT_DEFAULT_PARAMS VERITY_TABLE_OPT_IGNZERO, VERITY_TABLE_OPT_RESTART
-
-/* The FEC (forward error correction) format of dm-verity optional parameters:
- *     <#opt_params> use_fec_from_device <fec_dev>
- *     fec_roots <num> fec_blocks <num> fec_start <offset>
- *     ignore_zero_blocks restart_on_corruption
- */
-#define VERITY_TABLE_OPT_FEC_FORMAT \
-    "10 use_fec_from_device %s fec_roots %u fec_blocks %" PRIu64 " fec_start %" PRIu64 " %s %s"
-
-/* Note that fec_blocks is the size that FEC covers, *not* the
- * size of the FEC data. Since we use FEC for everything up until
- * the FEC data, it's the same as the offset (fec_start).
- */
-#define VERITY_TABLE_OPT_FEC_PARAMS(hashtree_desc, blk_device)                     \
-    blk_device, hashtree_desc.fec_num_roots,                                       \
-        hashtree_desc.fec_offset / hashtree_desc.data_block_size, /* fec_blocks */ \
-        hashtree_desc.fec_offset / hashtree_desc.data_block_size, /* fec_start */  \
-        VERITY_TABLE_OPT_IGNZERO, VERITY_TABLE_OPT_RESTART
-
 static inline bool nibble_value(const char& c, uint8_t* value) {
     FS_MGR_CHECK(value != nullptr);
 
@@ -280,10 +233,81 @@
     return true;
 }
 
-static bool hashtree_load_verity_table(struct dm_ioctl* io, const std::string& dm_device_name,
-                                       int fd, const std::string& blk_device,
-                                       const AvbHashtreeDescriptor& hashtree_desc,
-                                       const std::string& salt, const std::string& root_digest) {
+// Constructs dm-verity arguments for sending DM_TABLE_LOAD ioctl to kernel.
+// See the following link for more details:
+// https://gitlab.com/cryptsetup/cryptsetup/wikis/DMVerity
+static std::string construct_verity_table(const AvbHashtreeDescriptor& hashtree_desc,
+                                          const std::string& salt, const std::string& root_digest,
+                                          const std::string& blk_device) {
+    // Loads androidboot.veritymode from kernel cmdline.
+    std::string verity_mode;
+    if (!fs_mgr_get_boot_config("veritymode", &verity_mode)) {
+        verity_mode = "enforcing";  // Defaults to enforcing when it's absent.
+    }
+
+    // Converts veritymode to the format used in kernel.
+    std::string dm_verity_mode;
+    if (verity_mode == "enforcing") {
+        dm_verity_mode = "restart_on_corruption";
+    } else if (verity_mode == "logging") {
+        dm_verity_mode = "ignore_corruption";
+    } else if (verity_mode != "eio") {  // Default dm_verity_mode is eio.
+        LERROR << "Unknown androidboot.veritymode: " << verity_mode;
+        return "";
+    }
+
+    // dm-verity construction parameters:
+    //   <version> <dev> <hash_dev>
+    //   <data_block_size> <hash_block_size>
+    //   <num_data_blocks> <hash_start_block>
+    //   <algorithm> <digest> <salt>
+    //   [<#opt_params> <opt_params>]
+    std::ostringstream verity_table;
+    verity_table << hashtree_desc.dm_verity_version << " " << blk_device << " " << blk_device << " "
+                 << hashtree_desc.data_block_size << " " << hashtree_desc.hash_block_size << " "
+                 << hashtree_desc.image_size / hashtree_desc.data_block_size << " "
+                 << hashtree_desc.tree_offset / hashtree_desc.hash_block_size << " "
+                 << hashtree_desc.hash_algorithm << " " << root_digest << " " << salt;
+
+    // Continued from the above optional parameters:
+    //   [<#opt_params> <opt_params>]
+    int optional_argc = 0;
+    std::ostringstream optional_args;
+
+    // dm-verity optional parameters for FEC (forward error correction):
+    //   use_fec_from_device <fec_dev>
+    //   fec_roots <num>
+    //   fec_blocks <num>
+    //   fec_start <offset>
+    if (hashtree_desc.fec_size > 0) {
+        // Note that fec_blocks is the size that FEC covers, *NOT* the
+        // size of the FEC data. Since we use FEC for everything up until
+        // the FEC data, it's the same as the offset (fec_start).
+        optional_argc += 8;
+        // clang-format off
+        optional_args << "use_fec_from_device " << blk_device
+                      << " fec_roots " << hashtree_desc.fec_num_roots
+                      << " fec_blocks " << hashtree_desc.fec_offset / hashtree_desc.data_block_size
+                      << " fec_start " << hashtree_desc.fec_offset / hashtree_desc.data_block_size
+                      << " ";
+        // clang-format on
+    }
+
+    if (!dm_verity_mode.empty()) {
+        optional_argc += 1;
+        optional_args << dm_verity_mode << " ";
+    }
+
+    // Always use ignore_zero_blocks.
+    optional_argc += 1;
+    optional_args << "ignore_zero_blocks";
+
+    verity_table << " " << optional_argc << " " << optional_args.str();
+    return verity_table.str();
+}
+
+static bool load_verity_table(struct dm_ioctl* io, const std::string& dm_device_name, int fd,
+                              uint64_t image_size, const std::string& verity_table) {
     fs_mgr_verity_ioctl_init(io, dm_device_name, DM_STATUS_TABLE_FLAG);
 
     // The buffer consists of [dm_ioctl][dm_target_spec][verity_params].
@@ -294,35 +318,25 @@
     io->target_count = 1;
     dm_target->status = 0;
     dm_target->sector_start = 0;
-    dm_target->length = hashtree_desc.image_size / 512;
+    dm_target->length = image_size / 512;
     strcpy(dm_target->target_type, "verity");
 
     // Builds the verity params.
     char* verity_params = buffer + sizeof(struct dm_ioctl) + sizeof(struct dm_target_spec);
     size_t bufsize = DM_BUF_SIZE - (verity_params - buffer);
 
-    int res = 0;
-    if (hashtree_desc.fec_size > 0) {
-        res = snprintf(verity_params, bufsize, VERITY_TABLE_FORMAT VERITY_TABLE_OPT_FEC_FORMAT,
-                       VERITY_TABLE_PARAMS(hashtree_desc, blk_device.c_str(), root_digest.c_str(),
-                                           salt.c_str()),
-                       VERITY_TABLE_OPT_FEC_PARAMS(hashtree_desc, blk_device.c_str()));
-    } else {
-        res = snprintf(verity_params, bufsize, VERITY_TABLE_FORMAT VERITY_TABLE_OPT_DEFAULT_FORMAT,
-                       VERITY_TABLE_PARAMS(hashtree_desc, blk_device.c_str(), root_digest.c_str(),
-                                           salt.c_str()),
-                       VERITY_TABLE_OPT_DEFAULT_PARAMS);
-    }
+    LINFO << "Loading verity table: '" << verity_table << "'";
 
-    if (res < 0 || (size_t)res >= bufsize) {
-        LERROR << "Error building verity table; insufficient buffer size?";
+    // Copies verity_table to verity_params (including the terminating null byte).
+    if (verity_table.size() > bufsize - 1) {
+        LERROR << "Verity table size too large: " << verity_table.size()
+               << " (max allowable size: " << bufsize - 1 << ")";
         return false;
     }
-
-    LINFO << "Loading verity table: '" << verity_params << "'";
+    memcpy(verity_params, verity_table.c_str(), verity_table.size() + 1);
 
     // Sets ext target boundary.
-    verity_params += strlen(verity_params) + 1;
+    verity_params += verity_table.size() + 1;
     verity_params = (char*)(((unsigned long)verity_params + 7) & ~7);
     dm_target->next = verity_params - buffer;
 
@@ -362,9 +376,15 @@
         return false;
     }
 
+    std::string verity_table =
+        construct_verity_table(hashtree_desc, salt, root_digest, fstab_entry->blk_device);
+    if (verity_table.empty()) {
+        LERROR << "Failed to construct verity table.";
+        return false;
+    }
+
     // Loads the verity mapping table.
-    if (!hashtree_load_verity_table(io, mount_point, fd, std::string(fstab_entry->blk_device),
-                                    hashtree_desc, salt, root_digest)) {
+    if (!load_verity_table(io, mount_point, fd, hashtree_desc.image_size, verity_table)) {
         LERROR << "Couldn't load verity table!";
         return false;
     }
diff --git a/init/Android.bp b/init/Android.bp
new file mode 100644
index 0000000..80d5c42
--- /dev/null
+++ b/init/Android.bp
@@ -0,0 +1,164 @@
+//
+// 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.
+//
+
+cc_defaults {
+    name: "init_defaults",
+    cpp_std: "experimental",
+    sanitize: {
+        misc_undefined: ["integer"],
+    },
+    tidy_checks: ["-misc-forwarding-reference-overload"],
+    cppflags: [
+        "-DLOG_UEVENTS=0",
+        "-Wall",
+        "-Wextra",
+        "-Wno-unused-parameter",
+        "-Werror",
+        "-DALLOW_LOCAL_PROP_OVERRIDE=0",
+        "-DALLOW_PERMISSIVE_SELINUX=0",
+        "-DREBOOT_BOOTLOADER_ON_PANIC=0",
+        "-DWORLD_WRITABLE_KMSG=0",
+        "-DDUMP_ON_UMOUNT_FAILURE=0",
+        "-DSHUTDOWN_ZERO_TIMEOUT=0",
+    ],
+    product_variables: {
+        debuggable: {
+            cppflags: [
+                "-UALLOW_LOCAL_PROP_OVERRIDE",
+                "-DALLOW_LOCAL_PROP_OVERRIDE=1",
+                "-UALLOW_PERMISSIVE_SELINUX",
+                "-DALLOW_PERMISSIVE_SELINUX=1",
+                "-UREBOOT_BOOTLOADER_ON_PANIC",
+                "-DREBOOT_BOOTLOADER_ON_PANIC=1",
+                "-UWORLD_WRITABLE_KMSG",
+                "-DWORLD_WRITABLE_KMSG=1",
+                "-UDUMP_ON_UMOUNT_FAILURE",
+                "-DDUMP_ON_UMOUNT_FAILURE=1",
+            ],
+        },
+        eng: {
+            cppflags: [
+                "-USHUTDOWN_ZERO_TIMEOUT",
+                "-DSHUTDOWN_ZERO_TIMEOUT=1",
+            ],
+        },
+    },
+}
+
+cc_library_static {
+    name: "libinit",
+    defaults: ["init_defaults"],
+    srcs: [
+        "action.cpp",
+        "capabilities.cpp",
+        "descriptors.cpp",
+        "devices.cpp",
+        "import_parser.cpp",
+        "init_parser.cpp",
+        "log.cpp",
+        "parser.cpp",
+        "service.cpp",
+        "util.cpp",
+    ],
+    whole_static_libs: ["libcap"],
+    static_libs: [
+        "libbase",
+        "libselinux",
+        "liblog",
+        "libprocessgroup",
+    ],
+}
+
+/*
+This is not yet ready, see the below TODOs for what is missing
+
+cc_binary {
+    // TODO: Missing,
+    //LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT)
+    //LOCAL_UNSTRIPPED_PATH := $(TARGET_ROOT_OUT_UNSTRIPPED)
+
+    name: "init",
+    defaults: ["init_defaults"],
+    static_executable: true,
+    srcs: [
+        "bootchart.cpp",
+        "builtins.cpp",
+        "init.cpp",
+        "init_first_stage.cpp",
+        "keychords.cpp",
+        "property_service.cpp",
+        "reboot.cpp",
+        "signal_handler.cpp",
+        "ueventd.cpp",
+        "watchdogd.cpp",
+    ],
+    include_dirs: [
+        "system/core/mkbootimg"
+    ],
+    static_libs: [
+        "libinit",
+        "libbootloader_message",
+        "libfs_mgr",
+        "libfec",
+        "libfec_rs",
+        "libsquashfs_utils",
+        "liblogwrap",
+        "libext4_utils",
+        "libcutils",
+        "libbase",
+        "libc",
+        "libselinux",
+        "liblog",
+        "libcrypto_utils",
+        "libcrypto",
+        "libc++_static",
+        "libdl",
+        "libsparse",
+        "libz",
+        "libprocessgroup",
+        "libavb",
+        "libkeyutils",
+    ],
+    symlinks: [
+        "sbin/ueventd",
+        "sbin/watchdogd",
+    ],
+}
+*/
+
+// Tests
+// ------------------------------------------------------------------------------
+
+cc_test {
+    name: "init_tests",
+    defaults: ["init_defaults"],
+    srcs: [
+        "devices_test.cpp",
+        "init_parser_test.cpp",
+        "init_test.cpp",
+        "property_service_test.cpp",
+        "service_test.cpp",
+        "util_test.cpp",
+    ],
+    shared_libs: [
+        "libbase",
+        "libcutils",
+        "libselinux",
+    ],
+    static_libs: ["libinit"],
+}
+
+subdirs = ["*"]
diff --git a/init/Android.mk b/init/Android.mk
index 0db65cb..489d076 100644
--- a/init/Android.mk
+++ b/init/Android.mk
@@ -39,50 +39,6 @@
 
 # --
 
-# If building on Linux, then build unit test for the host.
-ifeq ($(HOST_OS),linux)
-include $(CLEAR_VARS)
-LOCAL_CPPFLAGS := $(init_cflags)
-LOCAL_SRC_FILES:= \
-    parser/tokenizer.cpp \
-
-LOCAL_MODULE := libinit_parser
-LOCAL_CLANG := true
-include $(BUILD_HOST_STATIC_LIBRARY)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := init_parser_tests
-LOCAL_SRC_FILES := \
-    parser/tokenizer_test.cpp \
-
-LOCAL_STATIC_LIBRARIES := libinit_parser
-LOCAL_CLANG := true
-include $(BUILD_HOST_NATIVE_TEST)
-endif
-
-include $(CLEAR_VARS)
-# b/38002385, work around clang-tidy segmentation fault.
-LOCAL_TIDY_CHECKS := -misc-forwarding-reference-overload
-LOCAL_CPPFLAGS := $(init_cflags)
-LOCAL_SRC_FILES:= \
-    action.cpp \
-    capabilities.cpp \
-    descriptors.cpp \
-    devices.cpp \
-    import_parser.cpp \
-    init_parser.cpp \
-    log.cpp \
-    parser.cpp \
-    service.cpp \
-    util.cpp \
-
-LOCAL_STATIC_LIBRARIES := libbase libselinux liblog libprocessgroup
-LOCAL_WHOLE_STATIC_LIBRARIES := libcap
-LOCAL_MODULE := libinit
-LOCAL_SANITIZE := integer
-LOCAL_CLANG := true
-include $(BUILD_STATIC_LIBRARY)
-
 include $(CLEAR_VARS)
 # b/38002385, work around clang-tidy segmentation fault.
 LOCAL_TIDY_CHECKS := -misc-forwarding-reference-overload
@@ -139,34 +95,3 @@
 LOCAL_SANITIZE := integer
 LOCAL_CLANG := true
 include $(BUILD_EXECUTABLE)
-
-
-# Unit tests.
-# =========================================================
-include $(CLEAR_VARS)
-# b/38002385, work around clang-tidy segmentation fault.
-LOCAL_TIDY_CHECKS := -misc-forwarding-reference-overload
-LOCAL_MODULE := init_tests
-LOCAL_SRC_FILES := \
-    devices_test.cpp \
-    init_parser_test.cpp \
-    init_test.cpp \
-    property_service_test.cpp \
-    service_test.cpp \
-    util_test.cpp \
-
-LOCAL_SHARED_LIBRARIES += \
-    libbase \
-    libcutils \
-    libselinux \
-
-LOCAL_STATIC_LIBRARIES := libinit
-LOCAL_SANITIZE := integer
-LOCAL_CLANG := true
-LOCAL_CPPFLAGS := -Wall -Wextra -Werror -std=gnu++1z
-include $(BUILD_NATIVE_TEST)
-
-
-# Include targets in subdirs.
-# =========================================================
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/init/devices.cpp b/init/devices.cpp
index d8258cf..e0351a3 100644
--- a/init/devices.cpp
+++ b/init/devices.cpp
@@ -30,6 +30,7 @@
 #include <string.h>
 #include <sys/sendfile.h>
 #include <sys/socket.h>
+#include <sys/sysmacros.h>
 #include <sys/time.h>
 #include <sys/un.h>
 #include <sys/wait.h>
diff --git a/init/reboot.cpp b/init/reboot.cpp
index 838406d..cdfc698 100644
--- a/init/reboot.cpp
+++ b/init/reboot.cpp
@@ -331,7 +331,7 @@
     // keep debugging tools until non critical ones are all gone.
     const std::set<std::string> kill_after_apps{"tombstoned", "logd", "adbd"};
     // watchdogd is a vendor specific component but should be alive to complete shutdown safely.
-    const std::set<std::string> to_starts{"watchdogd", "vold"};
+    const std::set<std::string> to_starts{"watchdogd", "vold", "ueventd"};
     ServiceManager::GetInstance().ForEachService([&kill_after_apps, &to_starts](Service* s) {
         if (kill_after_apps.count(s->name())) {
             s->SetShutdownCritical();
diff --git a/init/test_service/Android.bp b/init/test_service/Android.bp
new file mode 100644
index 0000000..9bd6f27
--- /dev/null
+++ b/init/test_service/Android.bp
@@ -0,0 +1,22 @@
+//
+// 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.
+//
+
+cc_binary {
+    name: "test_service",
+    srcs: ["test_service.cpp"],
+    shared_libs: ["libbase"],
+    init_rc: ["test_service.rc"],
+}
diff --git a/init/test_service/Android.mk b/init/test_service/Android.mk
deleted file mode 100644
index 30c9e9d..0000000
--- a/init/test_service/Android.mk
+++ /dev/null
@@ -1,27 +0,0 @@
-# Copyright (C) 2016 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http:#www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH := $(call my-dir)
-
-# Sample service for testing.
-# =========================================================
-include $(CLEAR_VARS)
-LOCAL_MODULE := test_service
-LOCAL_SRC_FILES := test_service.cpp
-
-LOCAL_SHARED_LIBRARIES += libbase
-
-LOCAL_INIT_RC := test_service.rc
-
-include $(BUILD_EXECUTABLE)
diff --git a/libcutils/ashmem-dev.c b/libcutils/ashmem-dev.c
index 92717c0..b4abb79 100644
--- a/libcutils/ashmem-dev.c
+++ b/libcutils/ashmem-dev.c
@@ -28,6 +28,7 @@
 #include <string.h>
 #include <sys/ioctl.h>
 #include <sys/stat.h>
+#include <sys/sysmacros.h>
 #include <sys/types.h>
 #include <unistd.h>
 
diff --git a/libcutils/fs_config.cpp b/libcutils/fs_config.cpp
index 2b3443f..919b65b 100644
--- a/libcutils/fs_config.cpp
+++ b/libcutils/fs_config.cpp
@@ -139,14 +139,8 @@
     { 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 },
-    { 00600, AID_ROOT,      AID_ROOT,      0, "system/odm/build.prop" },
-    { 00600, AID_ROOT,      AID_ROOT,      0, "system/odm/default.prop" },
-    { 00444, AID_ROOT,      AID_ROOT,      0, "system/odm/etc/fs_config_dirs" },
-    { 00444, AID_ROOT,      AID_ROOT,      0, "system/odm/etc/fs_config_files" },
     { 00444, AID_ROOT,      AID_ROOT,      0, oem_conf_dir + 1 },
     { 00444, AID_ROOT,      AID_ROOT,      0, oem_conf_file + 1 },
-    { 00444, AID_ROOT,      AID_ROOT,      0, "system/oem/etc/fs_config_dirs" },
-    { 00444, AID_ROOT,      AID_ROOT,      0, "system/oem/etc/fs_config_files" },
     { 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" },
@@ -163,10 +157,6 @@
     { 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" },
-    { 00600, AID_ROOT,      AID_ROOT,      0, "system/vendor/build.prop" },
-    { 00600, AID_ROOT,      AID_ROOT,      0, "system/vendor/default.prop" },
-    { 00444, AID_ROOT,      AID_ROOT,      0, "system/vendor/etc/fs_config_dirs" },
-    { 00444, AID_ROOT,      AID_ROOT,      0, "system/vendor/etc/fs_config_files" },
     { 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 },
@@ -202,17 +192,11 @@
     // Support RT scheduling in Bluetooth
     { 00700, AID_BLUETOOTH, AID_BLUETOOTH, CAP_MASK_LONG(CAP_NET_ADMIN) |
                                            CAP_MASK_LONG(CAP_SYS_NICE),
-                                              "system/vendor/bin/hw/android.hardware.bluetooth@1.0-service" },
-    { 00700, AID_BLUETOOTH, AID_BLUETOOTH, CAP_MASK_LONG(CAP_NET_ADMIN) |
-                                           CAP_MASK_LONG(CAP_SYS_NICE),
                                               "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),
-                                              "system/vendor/bin/hw/android.hardware.wifi@1.0-service" },
-    { 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" },
 
     // A non-privileged zygote that spawns isolated processes for web rendering.
@@ -233,8 +217,6 @@
     { 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/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/*" },
@@ -273,6 +255,36 @@
     return fd;
 }
 
+// if path is "vendor/<stuff>", "oem/<stuff>" or "odm/<stuff>"
+static bool is_partition(const char* path, size_t len) {
+    static const char* partitions[] = {"vendor/", "oem/", "odm/"};
+    for (size_t i = 0; i < (sizeof(partitions) / sizeof(partitions[0])); ++i) {
+        size_t plen = strlen(partitions[i]);
+        if (len <= plen) continue;
+        if (!strncmp(path, partitions[i], plen)) return true;
+    }
+    return false;
+}
+
+// alias prefixes of "<partition>/<stuff>" to "system/<partition>/<stuff>" or
+// "system/<partition>/<stuff>" to "<partition>/<stuff>"
+static bool prefix_cmp(const char* prefix, const char* path, size_t len) {
+    if (!strncmp(prefix, path, len)) return true;
+
+    static const char system[] = "system/";
+    if (!strncmp(path, system, strlen(system))) {
+        path += strlen(system);
+    } else if (len <= strlen(system)) {
+        return false;
+    } else if (strncmp(prefix, system, strlen(system))) {
+        return false;
+    } else {
+        prefix += strlen(system);
+        len -= strlen(system);
+    }
+    return is_partition(prefix, len) && !strncmp(prefix, path, len);
+}
+
 static bool fs_config_cmp(bool dir, const char* prefix, size_t len, const char* path, size_t plen) {
     if (dir) {
         if (plen < len) {
@@ -281,13 +293,13 @@
     } else {
         // If name ends in * then allow partial matches.
         if (prefix[len - 1] == '*') {
-            return !strncmp(prefix, path, len - 1);
+            return prefix_cmp(prefix, path, len - 1);
         }
         if (plen != len) {
             return false;
         }
     }
-    return !strncmp(prefix, path, len);
+    return prefix_cmp(prefix, path, len);
 }
 
 void fs_config(const char* path, int dir, const char* target_out_path, unsigned* uid, unsigned* gid,
diff --git a/libcutils/tests/fs_config.cpp b/libcutils/tests/fs_config.cpp
index 3917a0b..a62cd51 100644
--- a/libcutils/tests/fs_config.cpp
+++ b/libcutils/tests/fs_config.cpp
@@ -14,63 +14,188 @@
  * limitations under the License.
  */
 
+#include <inttypes.h>
+
 #include <string>
 
 #include <gtest/gtest.h>
 
+#include <android-base/file.h>
+#include <android-base/stringprintf.h>
 #include <android-base/strings.h>
 
 #include <private/android_filesystem_config.h>
+#include <private/fs_config.h>
 
-extern const struct fs_path_config* __for_testing_only__android_dirs;
-extern const struct fs_path_config* __for_testing_only__android_files;
+extern const fs_path_config* __for_testing_only__android_dirs;
+extern const fs_path_config* __for_testing_only__android_files;
 
-static void check_one(const struct fs_path_config* paths, const std::string& prefix,
-                      const std::string& alternate) {
-    for (size_t idx = 0; paths[idx].prefix; ++idx) {
-        std::string path(paths[idx].prefix);
-        if (android::base::StartsWith(path, prefix.c_str())) {
-            path = alternate + path.substr(prefix.length());
-            size_t second;
-            for (second = 0; paths[second].prefix; ++second) {
-                if (path == paths[second].prefix) break;
+// Maximum entries in system/core/libcutils/fs_config.cpp:android_* before we
+// hit a nullptr termination, before we declare the list is just too big or
+// could be missing the nullptr.
+static constexpr size_t max_idx = 4096;
+
+static bool check_unique(std::vector<const char*>& paths, const std::string& config_name,
+                         const std::string& prefix) {
+    bool retval = false;
+
+    std::string alternate = "system/" + prefix;
+
+    for (size_t idx = 0; idx < paths.size(); ++idx) {
+        size_t second;
+        std::string path(paths[idx]);
+        // check if there are multiple identical paths
+        for (second = idx + 1; second < paths.size(); ++second) {
+            if (path == paths[second]) {
+                GTEST_LOG_(ERROR) << "duplicate paths in " << config_name << ": " << paths[idx];
+                retval = true;
+                break;
             }
-            if (!paths[second].prefix) {
-                // guaranteed to fail expectations, trigger test failure with
-                // a message that reports the violation as an inequality.
-                EXPECT_STREQ((prefix + path.substr(alternate.length())).c_str(), path.c_str());
+        }
+
+        // check if path is <partition>/
+        if (android::base::StartsWith(path, prefix.c_str())) {
+            // rebuild path to be system/<partition>/... to check for alias
+            path = alternate + path.substr(prefix.size());
+            for (second = 0; second < paths.size(); ++second) {
+                if (path == paths[second]) {
+                    GTEST_LOG_(ERROR) << "duplicate alias paths in " << config_name << ": "
+                                      << paths[idx] << " and " << paths[second]
+                                      << " (remove latter)";
+                    retval = true;
+                    break;
+                }
+            }
+            continue;
+        }
+
+        // check if path is system/<partition>/
+        if (android::base::StartsWith(path, alternate.c_str())) {
+            // rebuild path to be <partition>/... to check for alias
+            path = prefix + path.substr(alternate.size());
+            for (second = 0; second < paths.size(); ++second) {
+                if (path == paths[second]) break;
+            }
+            if (second >= paths.size()) {
+                GTEST_LOG_(ERROR) << "replace path in " << config_name << ": " << paths[idx]
+                                  << " with " << path;
+                retval = true;
             }
         }
     }
+    return retval;
 }
 
-static void check_two(const struct fs_path_config* paths, const std::string& prefix) {
+static bool check_unique(const fs_path_config* paths, const char* type_name,
+                         const std::string& prefix) {
+    std::string config("system/core/libcutils/fs_config.cpp:android_");
+    config += type_name;
+    config += "[]";
+
+    bool retval = false;
+    std::vector<const char*> paths_tmp;
+    for (size_t idx = 0; paths[idx].prefix; ++idx) {
+        if (idx > max_idx) {
+            GTEST_LOG_(WARNING) << config << ": has no end (missing null prefix)";
+            retval = true;
+            break;
+        }
+        paths_tmp.push_back(paths[idx].prefix);
+    }
+
+    return check_unique(paths_tmp, config, prefix) || retval;
+}
+
+#define endof(pointer, field) (offsetof(typeof(*(pointer)), field) + sizeof((pointer)->field))
+
+static bool check_unique(const std::string& config, const std::string& prefix) {
+    int retval = false;
+
+    std::string data;
+    if (!android::base::ReadFileToString(config, &data)) return retval;
+
+    const fs_path_config_from_file* pc =
+        reinterpret_cast<const fs_path_config_from_file*>(data.c_str());
+    size_t len = data.size();
+
+    std::vector<const char*> paths_tmp;
+    size_t entry_number = 0;
+    while (len > 0) {
+        uint16_t host_len = (len >= endof(pc, len)) ? pc->len : INT16_MAX;
+        if (host_len > len) {
+            GTEST_LOG_(WARNING) << config << ": truncated at entry " << entry_number << " ("
+                                << host_len << " > " << len << ")";
+            const std::string unknown("?");
+            GTEST_LOG_(WARNING)
+                << config << ": entry[" << entry_number << "]={ "
+                << "len=" << ((len >= endof(pc, len))
+                                  ? android::base::StringPrintf("%" PRIu16, pc->len)
+                                  : unknown)
+                << ", mode=" << ((len >= endof(pc, mode))
+                                     ? android::base::StringPrintf("0%" PRIo16, pc->mode)
+                                     : unknown)
+                << ", uid=" << ((len >= endof(pc, uid))
+                                    ? android::base::StringPrintf("%" PRIu16, pc->uid)
+                                    : unknown)
+                << ", gid=" << ((len >= endof(pc, gid))
+                                    ? android::base::StringPrintf("%" PRIu16, pc->gid)
+                                    : unknown)
+                << ", capabilities="
+                << ((len >= endof(pc, capabilities))
+                        ? android::base::StringPrintf("0x%" PRIx64, pc->capabilities)
+                        : unknown)
+                << ", prefix="
+                << ((len >= offsetof(fs_path_config_from_file, prefix))
+                        ? android::base::StringPrintf(
+                              "\"%.*s...", (int)(len - offsetof(fs_path_config_from_file, prefix)),
+                              pc->prefix)
+                        : unknown)
+                << " }";
+            retval = true;
+            break;
+        }
+        paths_tmp.push_back(pc->prefix);
+
+        pc = reinterpret_cast<const fs_path_config_from_file*>(reinterpret_cast<const char*>(pc) +
+                                                               host_len);
+        len -= host_len;
+        ++entry_number;
+    }
+
+    return check_unique(paths_tmp, config, prefix) || retval;
+}
+
+void check_two(const fs_path_config* paths, const char* type_name, const char* prefix) {
     ASSERT_FALSE(paths == nullptr);
-    std::string alternate = "system/" + prefix;
-    check_one(paths, prefix, alternate);
-    check_one(paths, alternate, prefix);
+    ASSERT_FALSE(type_name == nullptr);
+    ASSERT_FALSE(prefix == nullptr);
+    bool check_internal = check_unique(paths, type_name, prefix);
+    EXPECT_FALSE(check_internal);
+    bool check_overrides =
+        check_unique(std::string("/") + prefix + "etc/fs_config_" + type_name, prefix);
+    EXPECT_FALSE(check_overrides);
 }
 
 TEST(fs_config, vendor_dirs_alias) {
-    check_two(__for_testing_only__android_dirs, "vendor/");
+    check_two(__for_testing_only__android_dirs, "dirs", "vendor/");
 }
 
 TEST(fs_config, vendor_files_alias) {
-    check_two(__for_testing_only__android_files, "vendor/");
+    check_two(__for_testing_only__android_files, "files", "vendor/");
 }
 
 TEST(fs_config, oem_dirs_alias) {
-    check_two(__for_testing_only__android_dirs, "oem/");
+    check_two(__for_testing_only__android_dirs, "dirs", "oem/");
 }
 
 TEST(fs_config, oem_files_alias) {
-    check_two(__for_testing_only__android_files, "oem/");
+    check_two(__for_testing_only__android_files, "files", "oem/");
 }
 
 TEST(fs_config, odm_dirs_alias) {
-    check_two(__for_testing_only__android_dirs, "odm/");
+    check_two(__for_testing_only__android_dirs, "dirs", "odm/");
 }
 
 TEST(fs_config, odm_files_alias) {
-    check_two(__for_testing_only__android_files, "odm/");
+    check_two(__for_testing_only__android_files, "files", "odm/");
 }
diff --git a/libmetricslogger/Android.bp b/libmetricslogger/Android.bp
index 75eab66..26a041a 100644
--- a/libmetricslogger/Android.bp
+++ b/libmetricslogger/Android.bp
@@ -22,7 +22,8 @@
 
         // 524291 corresponds to sysui_histogram, from
         // frameworks/base/core/java/com/android/internal/logging/EventLogTags.logtags
-        "-DHISTOGRAM_LOG_TAG=524291",
+        "-DHISTOGRAM_LOG_TAG=524292",
+        "-DCOUNT_LOG_TAG=524290",
     ],
 }
 
diff --git a/libmetricslogger/include/metricslogger/metrics_logger.h b/libmetricslogger/include/metricslogger/metrics_logger.h
index d30e56c..36e124d 100644
--- a/libmetricslogger/include/metricslogger/metrics_logger.h
+++ b/libmetricslogger/include/metricslogger/metrics_logger.h
@@ -24,5 +24,19 @@
 // buffer.
 void LogHistogram(const std::string& event, int32_t data);
 
+// Logs a Tron counter metric named |name| containing |val| count to the Tron
+// log buffer.
+void LogCounter(const std::string& name, int32_t val);
+
+// TODO: replace these with the metric_logger.proto definitions
+enum {
+    LOGBUILDER_CATEGORY = 757,
+    LOGBUILDER_NAME = 799,
+    LOGBUILDER_BUCKET = 801,
+    LOGBUILDER_VALUE = 802,
+    LOGBUILDER_COUNTER = 803,
+    LOGBUILDER_HISTOGRAM = 804,
+};
+
 }  // namespace metricslogger
 }  // namespace android
diff --git a/libmetricslogger/metrics_logger.cpp b/libmetricslogger/metrics_logger.cpp
index f8e0174..6f65e10 100644
--- a/libmetricslogger/metrics_logger.cpp
+++ b/libmetricslogger/metrics_logger.cpp
@@ -23,9 +23,18 @@
 namespace android {
 namespace metricslogger {
 
+// Mirror com.android.internal.logging.MetricsLogger#histogram().
 void LogHistogram(const std::string& event, int32_t data) {
-  android_log_event_list log(HISTOGRAM_LOG_TAG);
-  log << event << data << LOG_ID_EVENTS;
+    android_log_event_list log(HISTOGRAM_LOG_TAG);
+    log << LOGBUILDER_CATEGORY << LOGBUILDER_HISTOGRAM << LOGBUILDER_NAME << event
+        << LOGBUILDER_BUCKET << data << LOGBUILDER_VALUE << 1 << LOG_ID_EVENTS;
+}
+
+// Mirror com.android.internal.logging.MetricsLogger#count().
+void LogCounter(const std::string& name, int32_t val) {
+    android_log_event_list log(COUNT_LOG_TAG);
+    log << LOGBUILDER_CATEGORY << LOGBUILDER_COUNTER << LOGBUILDER_NAME << name << LOGBUILDER_VALUE
+        << val << LOG_ID_EVENTS;
 }
 
 }  // namespace metricslogger
diff --git a/libmetricslogger/metrics_logger_test.cpp b/libmetricslogger/metrics_logger_test.cpp
index 5a30ad7..440645c 100644
--- a/libmetricslogger/metrics_logger_test.cpp
+++ b/libmetricslogger/metrics_logger_test.cpp
@@ -19,6 +19,10 @@
 #include <gtest/gtest.h>
 
 TEST(MetricsLoggerTest, AddSingleBootEvent) {
-  android::metricslogger::LogHistogram("test_event", 42);
-  // TODO(jhawkins): Verify the EventLog is updated.
+    android::metricslogger::LogHistogram("test_event", 42);
+    // TODO(jhawkins): Verify the EventLog is updated.
+}
+
+TEST(MetricsLoggerTest, AddCounterVal) {
+    android::metricslogger::LogCounter("test_count", 10);
 }
diff --git a/libnetutils/Android.bp b/libnetutils/Android.bp
index f710ba2..0caf145 100644
--- a/libnetutils/Android.bp
+++ b/libnetutils/Android.bp
@@ -17,3 +17,17 @@
 
     export_include_dirs: ["include"],
 }
+
+cc_binary {
+    name: "dhcpdbg",
+
+    srcs: [
+        "dhcptool.c",
+    ],
+
+    shared_libs: [
+        "libnetutils",
+    ],
+
+    cflags: ["-Werror"],
+}
diff --git a/libnetutils/dhcptool.c b/libnetutils/dhcptool.c
new file mode 100644
index 0000000..280b977
--- /dev/null
+++ b/libnetutils/dhcptool.c
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2015, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <err.h>
+#include <errno.h>
+#include <error.h>
+#include <stdbool.h>
+#include <stdlib.h>
+
+#include <netutils/ifc.h>
+
+extern int do_dhcp(char*);
+
+int main(int argc, char* argv[]) {
+    if (argc != 2) {
+        error(EXIT_FAILURE, 0, "usage: %s INTERFACE", argv[0]);
+    }
+
+    char* interface = argv[1];
+    if (ifc_init()) {
+        err(errno, "dhcptool %s: ifc_init failed", interface);
+        ifc_close();
+        return EXIT_FAILURE;
+    }
+
+    int rc = do_dhcp(interface);
+    if (rc) {
+        err(errno, "dhcptool %s: do_dhcp failed", interface);
+    }
+    warn("IP assignment is for debug purposes ONLY");
+    ifc_close();
+
+    return rc ? EXIT_FAILURE : EXIT_SUCCESS;
+}
diff --git a/logd/LogBuffer.cpp b/logd/LogBuffer.cpp
index ded6c8c..76a4aff 100644
--- a/logd/LogBuffer.cpp
+++ b/logd/LogBuffer.cpp
@@ -79,10 +79,16 @@
             if (monotonic) {
                 if (!android::isMonotonic(e->mRealTime)) {
                     LogKlog::convertRealToMonotonic(e->mRealTime);
+                    if ((e->mRealTime.tv_nsec % 1000) == 0) {
+                        e->mRealTime.tv_nsec++;
+                    }
                 }
             } else {
                 if (android::isMonotonic(e->mRealTime)) {
                     LogKlog::convertMonotonicToReal(e->mRealTime);
+                    if ((e->mRealTime.tv_nsec % 1000) == 0) {
+                        e->mRealTime.tv_nsec++;
+                    }
                 }
             }
             ++it;
@@ -194,6 +200,11 @@
         return -EINVAL;
     }
 
+    // Slip the time by 1 nsec if the incoming lands on xxxxxx000 ns.
+    // This prevents any chance that an outside source can request an
+    // exact entry with time specified in ms or us precision.
+    if ((realtime.tv_nsec % 1000) == 0) ++realtime.tv_nsec;
+
     LogBufferElement* elem =
         new LogBufferElement(log_id, realtime, uid, pid, tid, msg, len);
     if (log_id != LOG_ID_SECURITY) {
@@ -1109,6 +1120,9 @@
             LogBufferElement* element = *it;
             if (element->getRealTime() > start) {
                 last = it;
+            } else if (element->getRealTime() == start) {
+                last = ++it;
+                break;
             } else if (!--count || (element->getRealTime() < min)) {
                 break;
             }
@@ -1116,7 +1130,7 @@
         it = last;
     }
 
-    log_time max = start;
+    log_time curr = start;
 
     LogBufferElement* lastElement = nullptr;  // iterator corruption paranoia
     static const size_t maxSkip = 4194304;    // maximum entries to skip
@@ -1142,10 +1156,6 @@
             continue;
         }
 
-        if (element->getRealTime() <= start) {
-            continue;
-        }
-
         // NB: calling out to another object with wrlock() held (safe)
         if (filter) {
             int ret = (*filter)(element, arg);
@@ -1172,10 +1182,10 @@
         unlock();
 
         // range locking in LastLogTimes looks after us
-        max = element->flushTo(reader, this, privileged, sameTid);
+        curr = element->flushTo(reader, this, privileged, sameTid);
 
-        if (max == element->FLUSH_ERROR) {
-            return max;
+        if (curr == element->FLUSH_ERROR) {
+            return curr;
         }
 
         skip = maxSkip;
@@ -1183,7 +1193,7 @@
     }
     unlock();
 
-    return max;
+    return curr;
 }
 
 std::string LogBuffer::formatStatistics(uid_t uid, pid_t pid,
diff --git a/shell_and_utilities/Android.bp b/shell_and_utilities/Android.bp
index 81cf315..4f4fc5d 100644
--- a/shell_and_utilities/Android.bp
+++ b/shell_and_utilities/Android.bp
@@ -5,9 +5,12 @@
         "grep",
         "gzip",
         "mkshrc",
+        "mkshrc_vendor",
         "reboot",
         "sh",
+        "sh_vendor",
         "toolbox",
         "toybox",
+        "toybox_vendor",
     ],
 }
diff --git a/toolbox/Android.bp b/toolbox/Android.bp
new file mode 100644
index 0000000..1c9fb20
--- /dev/null
+++ b/toolbox/Android.bp
@@ -0,0 +1,44 @@
+common_cflags = [
+    "-Werror",
+    "-Wno-unused-parameter",
+    "-Wno-unused-const-variable",
+    "-include bsd-compatibility.h"
+]
+
+cc_library_static {
+    srcs: [
+        "upstream-netbsd/bin/dd/args.c",
+        "upstream-netbsd/bin/dd/conv.c",
+        "upstream-netbsd/bin/dd/dd.c",
+        "upstream-netbsd/bin/dd/dd_hostops.c",
+        "upstream-netbsd/bin/dd/misc.c",
+        "upstream-netbsd/bin/dd/position.c",
+        "upstream-netbsd/lib/libc/gen/getbsize.c",
+        "upstream-netbsd/lib/libc/gen/humanize_number.c",
+        "upstream-netbsd/lib/libc/stdlib/strsuftoll.c",
+        "upstream-netbsd/lib/libc/string/swab.c",
+        "upstream-netbsd/lib/libutil/raise_default_signal.c",
+    ],
+    cflags: common_cflags + [
+        "-Dmain=dd_main",
+        "-DNO_CONV",
+    ],
+    local_include_dirs: ["upstream-netbsd/include/"],
+    name: "libtoolbox_dd",
+}
+
+// We build BSD grep separately, so it can provide egrep and fgrep too.
+cc_binary {
+    name: "grep",
+    srcs: [
+        "upstream-netbsd/usr.bin/grep/fastgrep.c",
+        "upstream-netbsd/usr.bin/grep/file.c",
+        "upstream-netbsd/usr.bin/grep/grep.c",
+        "upstream-netbsd/usr.bin/grep/queue.c",
+        "upstream-netbsd/usr.bin/grep/util.c",
+    ],
+    cflags: common_cflags,
+    local_include_dirs: ["upstream-netbsd/include/"],
+    symlinks: ["egrep", "fgrep"],
+
+}
diff --git a/toolbox/Android.mk b/toolbox/Android.mk
index d6ead1a..94029d8 100644
--- a/toolbox/Android.mk
+++ b/toolbox/Android.mk
@@ -1,30 +1,9 @@
 LOCAL_PATH:= $(call my-dir)
 
-
 common_cflags := \
     -Werror -Wno-unused-parameter -Wno-unused-const-variable \
     -include bsd-compatibility.h \
 
-
-include $(CLEAR_VARS)
-LOCAL_SRC_FILES := \
-    upstream-netbsd/bin/dd/args.c \
-    upstream-netbsd/bin/dd/conv.c \
-    upstream-netbsd/bin/dd/dd.c \
-    upstream-netbsd/bin/dd/dd_hostops.c \
-    upstream-netbsd/bin/dd/misc.c \
-    upstream-netbsd/bin/dd/position.c \
-    upstream-netbsd/lib/libc/gen/getbsize.c \
-    upstream-netbsd/lib/libc/gen/humanize_number.c \
-    upstream-netbsd/lib/libc/stdlib/strsuftoll.c \
-    upstream-netbsd/lib/libc/string/swab.c \
-    upstream-netbsd/lib/libutil/raise_default_signal.c
-LOCAL_CFLAGS += $(common_cflags) -Dmain=dd_main -DNO_CONV
-LOCAL_C_INCLUDES += $(LOCAL_PATH)/upstream-netbsd/include/
-LOCAL_MODULE := libtoolbox_dd
-include $(BUILD_STATIC_LIBRARY)
-
-
 include $(CLEAR_VARS)
 
 BSD_TOOLS := \
@@ -80,18 +59,3 @@
 $(INPUT_H_LABELS_H): $(LOCAL_PATH)/Android.mk $(LOCAL_PATH)/generate-input.h-labels.py $(UAPI_INPUT_EVENT_CODES_H)
 $(INPUT_H_LABELS_H):
 	$(transform-generated-source)
-
-
-# We build BSD grep separately, so it can provide egrep and fgrep too.
-include $(CLEAR_VARS)
-LOCAL_SRC_FILES := \
-    upstream-netbsd/usr.bin/grep/fastgrep.c \
-    upstream-netbsd/usr.bin/grep/file.c \
-    upstream-netbsd/usr.bin/grep/grep.c \
-    upstream-netbsd/usr.bin/grep/queue.c \
-    upstream-netbsd/usr.bin/grep/util.c
-LOCAL_CFLAGS += $(common_cflags)
-LOCAL_C_INCLUDES += $(LOCAL_PATH)/upstream-netbsd/include/
-LOCAL_MODULE := grep
-LOCAL_POST_INSTALL_CMD := $(hide) $(foreach t,egrep fgrep,ln -sf grep $(TARGET_OUT)/bin/$(t);)
-include $(BUILD_EXECUTABLE)