Merge "Make inlines static"
diff --git a/TEST_MAPPING b/TEST_MAPPING
index bc5685b..cc85408 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -19,6 +19,9 @@
       "name": "libprocinfo_test"
     },
     {
+      "name": "libutils_test"
+    },
+    {
       "name": "memunreachable_test"
     },
     {
diff --git a/adb/sysdeps_win32.cpp b/adb/sysdeps_win32.cpp
index d587589..4c5d8cb 100644
--- a/adb/sysdeps_win32.cpp
+++ b/adb/sysdeps_win32.cpp
@@ -356,6 +356,9 @@
     DWORD desiredAccess = 0;
     DWORD shareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
 
+    // CreateFileW is inherently O_CLOEXEC by default.
+    options &= ~O_CLOEXEC;
+
     switch (options) {
         case O_RDONLY:
             desiredAccess = GENERIC_READ;
diff --git a/adb/test_adb.py b/adb/test_adb.py
index 430fc3d..14e5071 100755
--- a/adb/test_adb.py
+++ b/adb/test_adb.py
@@ -422,6 +422,9 @@
         with fake_adbd() as (port, _):
             serial = "localhost:{}".format(port)
             with adb_connect(self, serial):
+                # Wait a bit to give adb some time to connect.
+                time.sleep(0.25)
+
                 output = subprocess.check_output(["adb", "-s", serial,
                                                   "get-state"])
                 self.assertEqual(output.strip(), b"device")
diff --git a/base/mapped_file.cpp b/base/mapped_file.cpp
index f7901af..faa845d 100644
--- a/base/mapped_file.cpp
+++ b/base/mapped_file.cpp
@@ -16,6 +16,8 @@
 
 #include "android-base/mapped_file.h"
 
+#include <errno.h>
+
 namespace android {
 namespace base {
 
@@ -50,7 +52,14 @@
       new MappedFile{static_cast<char*>(base), length, slop, handle});
 #else
   void* base = mmap(nullptr, file_length, prot, MAP_SHARED, fd, file_offset);
-  if (base == MAP_FAILED) return nullptr;
+  if (base == MAP_FAILED) {
+    // http://b/119818070 "app crashes when reading asset of zero length".
+    // mmap fails with EINVAL for a zero length region.
+    if (errno == EINVAL && length == 0) {
+      return std::unique_ptr<MappedFile>(new MappedFile{nullptr, 0, 0});
+    }
+    return nullptr;
+  }
   return std::unique_ptr<MappedFile>(new MappedFile{static_cast<char*>(base), length, slop});
 #endif
 }
diff --git a/base/mapped_file_test.cpp b/base/mapped_file_test.cpp
index 7e89723..cfde73c 100644
--- a/base/mapped_file_test.cpp
+++ b/base/mapped_file_test.cpp
@@ -25,7 +25,6 @@
 #include <string>
 
 #include "android-base/file.h"
-#include "android-base/unique_fd.h"
 
 TEST(mapped_file, smoke) {
   TemporaryFile tf;
@@ -37,3 +36,13 @@
   ASSERT_EQ('l', m->data()[0]);
   ASSERT_EQ('o', m->data()[1]);
 }
+
+TEST(mapped_file, zero_length_mapping) {
+  // http://b/119818070 "app crashes when reading asset of zero length".
+  // mmap fails with EINVAL for a zero length region.
+  TemporaryFile tf;
+  ASSERT_TRUE(tf.fd != -1);
+
+  auto m = android::base::MappedFile::FromFd(tf.fd, 4096, 0, PROT_READ);
+  ASSERT_EQ(0u, m->size());
+}
diff --git a/bootstat/bootstat.cpp b/bootstat/bootstat.cpp
index 6700b6c..ed955ea 100644
--- a/bootstat/bootstat.cpp
+++ b/bootstat/bootstat.cpp
@@ -114,25 +114,6 @@
   return cmd;
 }
 
-// Convenience wrapper over the property API that returns an
-// std::string.
-std::string GetProperty(const char* key) {
-  std::vector<char> temp(PROPERTY_VALUE_MAX);
-  const int len = property_get(key, &temp[0], nullptr);
-  if (len < 0) {
-    return "";
-  }
-  return std::string(&temp[0], len);
-}
-
-bool SetProperty(const char* key, const std::string& val) {
-  return property_set(key, val.c_str()) == 0;
-}
-
-bool SetProperty(const char* key, const char* val) {
-  return property_set(key, val) == 0;
-}
-
 constexpr int32_t kEmptyBootReason = 0;
 constexpr int32_t kUnknownBootReason = 1;
 
@@ -746,11 +727,13 @@
 void BootReasonAddToHistory(const std::string& system_boot_reason) {
   if (system_boot_reason.empty()) return;
   LOG(INFO) << "Canonical boot reason: " << system_boot_reason;
-  auto old_system_boot_reason = GetProperty(system_reboot_reason_property);
-  if (!SetProperty(system_reboot_reason_property, system_boot_reason)) {
-    SetProperty(system_reboot_reason_property, system_boot_reason.substr(0, PROPERTY_VALUE_MAX - 1));
+  auto old_system_boot_reason = android::base::GetProperty(system_reboot_reason_property, "");
+  if (!android::base::SetProperty(system_reboot_reason_property, system_boot_reason)) {
+    android::base::SetProperty(system_reboot_reason_property,
+                               system_boot_reason.substr(0, PROPERTY_VALUE_MAX - 1));
   }
-  auto reason_history = android::base::Split(GetProperty(history_reboot_reason_property), "\n");
+  auto reason_history =
+      android::base::Split(android::base::GetProperty(history_reboot_reason_property, ""), "\n");
   static auto mark = time(nullptr);
   auto mark_str = std::string(",") + std::to_string(mark);
   auto marked_system_boot_reason = system_boot_reason + mark_str;
@@ -773,7 +756,8 @@
   reason_history.insert(reason_history.begin(), marked_system_boot_reason);
   // If the property string is too long ( > PROPERTY_VALUE_MAX)
   // we get an error, so trim out last entry and try again.
-  while (!(SetProperty(history_reboot_reason_property, android::base::Join(reason_history, '\n')))) {
+  while (!android::base::SetProperty(history_reboot_reason_property,
+                                     android::base::Join(reason_history, '\n'))) {
     auto it = std::prev(reason_history.end());
     if (it == reason_history.end()) break;
     reason_history.erase(it);
@@ -782,7 +766,7 @@
 
 // Scrub, Sanitize, Standardize and Enhance the boot reason string supplied.
 std::string BootReasonStrToReason(const std::string& boot_reason) {
-  std::string ret(GetProperty(system_reboot_reason_property));
+  auto ret = android::base::GetProperty(system_reboot_reason_property, "");
   std::string reason(boot_reason);
   // If sys.boot.reason == ro.boot.bootreason, let's re-evaluate
   if (reason == ret) ret = "";
@@ -922,7 +906,7 @@
     if (isBluntRebootReason(ret)) {
       // Content buffer no longer will have console data. Beware if more
       // checks added below, that depend on parsing console content.
-      content = GetProperty(last_reboot_reason_property);
+      content = android::base::GetProperty(last_reboot_reason_property, "");
       transformReason(content);
 
       // Anything in last is better than 'super-blunt' reboot or shutdown.
@@ -966,7 +950,7 @@
   static const std::string kBuildDateKey = "build_date";
   std::string boot_complete_prefix = "boot_complete";
 
-  std::string build_date_str = GetProperty("ro.build.date.utc");
+  auto build_date_str = android::base::GetProperty("ro.build.date.utc", "");
   int32_t build_date;
   if (!android::base::ParseInt(build_date_str, &build_date)) {
     return std::string();
@@ -989,7 +973,7 @@
 
 // Records the value of a given ro.boottime.init property in milliseconds.
 void RecordInitBootTimeProp(BootEventRecordStore* boot_event_store, const char* property) {
-  std::string value = GetProperty(property);
+  auto value = android::base::GetProperty(property, "");
 
   int32_t time_in_ms;
   if (android::base::ParseInt(value, &time_in_ms)) {
@@ -1007,7 +991,7 @@
 
   // |ro.boot.boottime| is of the form 'stage1:time1,...,stageN:timeN',
   // where timeN is in milliseconds.
-  std::string value = GetProperty("ro.boot.boottime");
+  auto value = android::base::GetProperty("ro.boot.boottime", "");
   if (value.empty()) {
     // ro.boot.boottime is not reported on all devices.
     return BootloaderTimingMap();
@@ -1019,6 +1003,7 @@
     auto stageTimingValues = android::base::Split(stageTiming, ":");
     DCHECK_EQ(2U, stageTimingValues.size());
 
+    if (stageTimingValues.size() < 2) continue;
     std::string stageName = stageTimingValues[0];
     int32_t time_ms;
     if (android::base::ParseInt(stageTimingValues[1], &time_ms)) {
@@ -1080,7 +1065,7 @@
 void LogBootInfoToStatsd(std::chrono::milliseconds end_time,
                          std::chrono::milliseconds total_duration, int32_t bootloader_duration_ms,
                          double time_since_last_boot_sec) {
-  const std::string reason(GetProperty(bootloader_reboot_reason_property));
+  const auto reason = android::base::GetProperty(bootloader_reboot_reason_property, "");
 
   if (reason.empty()) {
     android::util::stats_write(android::util::BOOT_SEQUENCE_REPORTED, "<EMPTY>", "<EMPTY>",
@@ -1090,7 +1075,7 @@
     return;
   }
 
-  const std::string system_reason(GetProperty(system_reboot_reason_property));
+  const auto system_reason = android::base::GetProperty(system_reboot_reason_property, "");
   android::util::stats_write(android::util::BOOT_SEQUENCE_REPORTED, reason.c_str(),
                              system_reason.c_str(), end_time.count(), total_duration.count(),
                              (int64_t)bootloader_duration_ms,
@@ -1098,19 +1083,20 @@
 }
 
 void SetSystemBootReason() {
-  const std::string bootloader_boot_reason(GetProperty(bootloader_reboot_reason_property));
+  const auto bootloader_boot_reason =
+      android::base::GetProperty(bootloader_reboot_reason_property, "");
   const std::string system_boot_reason(BootReasonStrToReason(bootloader_boot_reason));
   // Record the scrubbed system_boot_reason to the property
   BootReasonAddToHistory(system_boot_reason);
   // Shift last_reboot_reason_property to last_last_reboot_reason_property
-  std::string last_boot_reason(GetProperty(last_reboot_reason_property));
+  auto last_boot_reason = android::base::GetProperty(last_reboot_reason_property, "");
   if (last_boot_reason.empty() || isKernelRebootReason(system_boot_reason)) {
     last_boot_reason = system_boot_reason;
   } else {
     transformReason(last_boot_reason);
   }
-  SetProperty(last_last_reboot_reason_property, last_boot_reason);
-  SetProperty(last_reboot_reason_property, "");
+  android::base::SetProperty(last_last_reboot_reason_property, last_boot_reason);
+  android::base::SetProperty(last_reboot_reason_property, "");
 }
 
 // Gets the boot time offset. This is useful when Android is running in a
@@ -1197,7 +1183,7 @@
 // Records the boot_reason metric by querying the ro.boot.bootreason system
 // property.
 void RecordBootReason() {
-  const std::string reason(GetProperty(bootloader_reboot_reason_property));
+  const auto reason = android::base::GetProperty(bootloader_reboot_reason_property, "");
 
   if (reason.empty()) {
     // Log an empty boot reason value as '<EMPTY>' to ensure the value is intentional
@@ -1215,12 +1201,12 @@
   boot_event_store.AddBootEventWithValue("boot_reason", boot_reason);
 
   // Log the scrubbed system_boot_reason.
-  const std::string system_reason(GetProperty(system_reboot_reason_property));
+  const auto system_reason = android::base::GetProperty(system_reboot_reason_property, "");
   int32_t system_boot_reason = BootReasonStrToEnum(system_reason);
   boot_event_store.AddBootEventWithValue("system_boot_reason", system_boot_reason);
 
   if (reason == "") {
-    SetProperty(bootloader_reboot_reason_property, system_reason);
+    android::base::SetProperty(bootloader_reboot_reason_property, system_reason);
   }
 }
 
diff --git a/bootstat/bootstat.rc b/bootstat/bootstat.rc
index 1300a27..85caf25 100644
--- a/bootstat/bootstat.rc
+++ b/bootstat/bootstat.rc
@@ -1,7 +1,9 @@
 # This file is the LOCAL_INIT_RC file for the bootstat command.
 
-# mirror bootloader boot reason to system boot reason
-on property:ro.boot.bootreason=*
+# Mirror bootloader boot reason to system boot reason
+# ro.boot.bootreason should be set by init already
+# before post-fs trigger
+on post-fs && property:ro.boot.bootreason=*
     setprop sys.boot.reason ${ro.boot.bootreason}
 
 on post-fs-data
@@ -66,11 +68,16 @@
 on property:init.svc.zygote=stopping
     setprop sys.logbootcomplete 0
 
+# Set boot reason
+on zygote-start
+    # Converts bootloader boot reason and persist.sys.boot.reason to system boot reason
+    # Need go after persist peroperties are loaded which is right before zygote-start trigger
+    exec_background - system log -- /system/bin/bootstat --set_system_boot_reason
+
 # Record boot complete metrics.
 on property:sys.boot_completed=1 && property:sys.logbootcomplete=1
-    # Converts bootloader boot reason to system boot reason
     # Record boot_complete and related stats (decryption, etc).
     # Record the boot reason.
     # Record time since factory reset.
     # Log all boot events.
-    exec_background - system log -- /system/bin/bootstat --set_system_boot_reason --record_boot_complete --record_boot_reason --record_time_since_factory_reset -l
+    exec_background - system log -- /system/bin/bootstat --record_boot_complete --record_boot_reason --record_time_since_factory_reset -l
diff --git a/fs_mgr/README.overlayfs.md b/fs_mgr/README.overlayfs.md
index 8784c94..2aac260 100644
--- a/fs_mgr/README.overlayfs.md
+++ b/fs_mgr/README.overlayfs.md
@@ -74,7 +74,7 @@
 When *overlayfs* logic is feasible, it will use either the
 **/cache/overlay/** directory for non-A/B devices, or the
 **/mnt/scratch/overlay** directory for A/B devices that have
-access to *Logical Resizeable Android Partitions*.
+access to *Logical Resizable Android Partitions*.
 The backing store is used as soon as possible in the boot
 process and can occur at first stage init, or at the
 mount_all init rc commands.
@@ -94,12 +94,17 @@
   and thus free dynamic partition space.
 - Kernel must have CONFIG_OVERLAY_FS=y and will need to be patched
   with "*overlayfs: override_creds=off option bypass creator_cred*"
-  if higher than 4.6.
+  if kernel is higher than 4.6.
+  The patch is available on the upstream mailing list and the latest as of
+  Feb 8 2019 is https://lore.kernel.org/patchwork/patch/1009299/.
+  This patch adds an override_creds _mount_ option to overlayfs that
+  permits legacy behavior for systems that do not have overlapping
+  sepolicy rules, principals of least privilege, which is how Android behaves.
 - *adb enable-verity* will free up overlayfs and as a bonus the
   device will be reverted pristine to before any content was updated.
   Update engine does not take advantage of this, will perform a full OTA.
 - Update engine may not run if *fs_mgr_overlayfs_is_setup*() reports
-  true as adb remount overrides are incompatable with an OTA resources.
+  true as adb remount overrides are incompatible with an OTA resources.
 - For implementation simplicity on retrofit dynamic partition devices,
   take the whole alternate super (eg: if "*a*" slot, then the whole of
   "*system_b*").
diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp
index e684293..b69e773 100644
--- a/fs_mgr/fs_mgr.cpp
+++ b/fs_mgr/fs_mgr.cpp
@@ -85,6 +85,7 @@
 
 #define ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a)))
 
+using android::base::Basename;
 using android::base::Realpath;
 using android::base::StartsWith;
 using android::base::unique_fd;
@@ -1576,65 +1577,41 @@
     return true;
 }
 
-bool fs_mgr_update_verity_state(
-        std::function<void(const std::string& mount_point, int mode)> callback) {
-    if (!callback) {
-        return false;
-    }
-
-    int mode;
-    if (!fs_mgr_load_verity_state(&mode)) {
-        return false;
-    }
-
-    Fstab fstab;
-    if (!ReadDefaultFstab(&fstab)) {
-        LERROR << "Failed to read default fstab";
+bool fs_mgr_is_verity_enabled(const FstabEntry& entry) {
+    if (!entry.fs_mgr_flags.verify && !entry.fs_mgr_flags.avb) {
         return false;
     }
 
     DeviceMapper& dm = DeviceMapper::Instance();
 
-    for (const auto& entry : fstab) {
-        if (!entry.fs_mgr_flags.verify && !entry.fs_mgr_flags.avb) {
-            continue;
-        }
-
-        std::string mount_point;
-        if (entry.mount_point == "/") {
-            // In AVB, the dm device name is vroot instead of system.
-            mount_point = entry.fs_mgr_flags.avb ? "vroot" : "system";
-        } else {
-            mount_point = basename(entry.mount_point.c_str());
-        }
-
-        if (dm.GetState(mount_point) == DmDeviceState::INVALID) {
-            PERROR << "Could not find verity device for mount point: " << mount_point;
-            continue;
-        }
-
-        const char* status;
-        std::vector<DeviceMapper::TargetInfo> table;
-        if (!dm.GetTableStatus(mount_point, &table) || table.empty() || table[0].data.empty()) {
-            if (!entry.fs_mgr_flags.verify_at_boot) {
-                PERROR << "Failed to query DM_TABLE_STATUS for " << mount_point;
-                continue;
-            }
-            status = "V";
-        } else {
-            status = table[0].data.c_str();
-        }
-
-        // To be consistent in vboot 1.0 and vboot 2.0 (AVB), change the mount_point
-        // back to 'system' for the callback. So it has property [partition.system.verified]
-        // instead of [partition.vroot.verified].
-        if (mount_point == "vroot") mount_point = "system";
-        if (*status == 'C' || *status == 'V') {
-            callback(mount_point, mode);
-        }
+    std::string mount_point;
+    if (entry.mount_point == "/") {
+        // In AVB, the dm device name is vroot instead of system.
+        mount_point = entry.fs_mgr_flags.avb ? "vroot" : "system";
+    } else {
+        mount_point = Basename(entry.mount_point);
     }
 
-    return true;
+    if (dm.GetState(mount_point) == DmDeviceState::INVALID) {
+        return false;
+    }
+
+    const char* status;
+    std::vector<DeviceMapper::TargetInfo> table;
+    if (!dm.GetTableStatus(mount_point, &table) || table.empty() || table[0].data.empty()) {
+        if (!entry.fs_mgr_flags.verify_at_boot) {
+            return false;
+        }
+        status = "V";
+    } else {
+        status = table[0].data.c_str();
+    }
+
+    if (*status == 'C' || *status == 'V') {
+        return true;
+    }
+
+    return false;
 }
 
 std::string fs_mgr_get_super_partition_name(int slot) {
diff --git a/fs_mgr/fs_mgr_fstab.cpp b/fs_mgr/fs_mgr_fstab.cpp
index 9a8ad56..4d44fcf 100644
--- a/fs_mgr/fs_mgr_fstab.cpp
+++ b/fs_mgr/fs_mgr_fstab.cpp
@@ -176,6 +176,7 @@
 
 void ParseFsMgrFlags(const std::string& flags, FstabEntry* entry) {
     for (const auto& flag : Split(flags, ",")) {
+        if (flag.empty() || flag == "defaults") continue;
         std::string arg;
         if (auto equal_sign = flag.find('='); equal_sign != std::string::npos) {
             arg = flag.substr(equal_sign + 1);
diff --git a/fs_mgr/fs_mgr_overlayfs.cpp b/fs_mgr/fs_mgr_overlayfs.cpp
index c7d2cb9..87729cd 100644
--- a/fs_mgr/fs_mgr_overlayfs.cpp
+++ b/fs_mgr/fs_mgr_overlayfs.cpp
@@ -67,6 +67,13 @@
     return ret;
 }
 
+// determine if a filesystem is available
+bool fs_mgr_overlayfs_filesystem_available(const std::string& filesystem) {
+    std::string filesystems;
+    if (!android::base::ReadFileToString("/proc/filesystems", &filesystems)) return false;
+    return filesystems.find("\t" + filesystem + "\n") != std::string::npos;
+}
+
 }  // namespace
 
 #if ALLOW_ADBD_DISABLE_VERITY == 0  // If we are a user build, provide stubs
@@ -265,15 +272,6 @@
     return false;
 }
 
-std::vector<std::string> fs_mgr_overlayfs_verity_enabled_list() {
-    std::vector<std::string> ret;
-    auto save_errno = errno;
-    fs_mgr_update_verity_state(
-            [&ret](const std::string& mount_point, int) { ret.emplace_back(mount_point); });
-    if ((errno == ENOENT) || (errno == ENXIO)) errno = save_errno;
-    return ret;
-}
-
 bool fs_mgr_wants_overlayfs(FstabEntry* entry) {
     // Don't check entries that are managed by vold.
     if (entry->fs_mgr_flags.vold_managed || entry->fs_mgr_flags.recovery_only) return false;
@@ -321,6 +319,7 @@
 bool fs_mgr_overlayfs_setup_one(const std::string& overlay, const std::string& mount_point,
                                 bool* change) {
     auto ret = true;
+    if (fs_mgr_overlayfs_already_mounted(mount_point)) return ret;
     auto fsrec_mount_point = overlay + "/" + android::base::Basename(mount_point) + "/";
 
     if (setfscreatecon(kOverlayfsFileContext)) {
@@ -529,15 +528,19 @@
 
 std::vector<std::string> fs_mgr_candidate_list(Fstab* fstab, const char* mount_point = nullptr) {
     std::vector<std::string> mounts;
-    auto verity = fs_mgr_overlayfs_verity_enabled_list();
     for (auto& entry : *fstab) {
-        if (!fs_mgr_wants_overlayfs(&entry)) continue;
-        std::string new_mount_point(fs_mgr_mount_point(entry.mount_point.c_str()));
-        if (mount_point && (new_mount_point != mount_point)) continue;
-        if (std::find(verity.begin(), verity.end(), android::base::Basename(new_mount_point)) !=
-            verity.end()) {
+        if (!fs_mgr_overlayfs_already_mounted(entry.mount_point) &&
+            !fs_mgr_wants_overlayfs(&entry)) {
             continue;
         }
+        std::string new_mount_point(fs_mgr_mount_point(entry.mount_point.c_str()));
+        if (mount_point && (new_mount_point != mount_point)) continue;
+
+        auto saved_errno = errno;
+        auto verity_enabled = fs_mgr_is_verity_enabled(entry);
+        if (errno == ENOENT || errno == ENXIO) errno = saved_errno;
+        if (verity_enabled) continue;
+
         auto duplicate_or_more_specific = false;
         for (auto it = mounts.begin(); it != mounts.end();) {
             if ((*it == new_mount_point) ||
@@ -554,26 +557,6 @@
         if (!duplicate_or_more_specific) mounts.emplace_back(new_mount_point);
     }
 
-    // if not itemized /system or /, system as root, fake one up?
-
-    // do we want or need to?
-    if (mount_point && ("/system"s != mount_point)) return mounts;
-    if (std::find(mounts.begin(), mounts.end(), "/system") != mounts.end()) return mounts;
-
-    // fs_mgr_overlayfs_verity_enabled_list says not to?
-    if (std::find(verity.begin(), verity.end(), "system") != verity.end()) return mounts;
-
-    // confirm that fstab is missing system
-    if (GetEntryForMountPoint(fstab, "/") != nullptr ||
-        GetEntryForMountPoint(fstab, "/system") != nullptr) {
-        return mounts;
-    }
-
-    // We have a stunted fstab (w/o system or / ) passed in by the caller,
-    // verity claims are assumed accurate because they are collected internally
-    // from fs_mgr_fstab_default() from within fs_mgr_update_verity_state(),
-    // Can (re)evaluate /system with impunity since we know it is ever-present.
-    mounts.emplace_back("/system");
     return mounts;
 }
 
@@ -625,8 +608,12 @@
 
 // Only a suggestion for _first_ try during mounting
 std::string fs_mgr_overlayfs_scratch_mount_type() {
-    if (!access(kMkF2fs.c_str(), X_OK) && fs_mgr_access("/sys/fs/f2fs")) return "f2fs";
-    if (!access(kMkExt4.c_str(), X_OK) && fs_mgr_access("/sys/fs/ext4")) return "ext4";
+    if (!access(kMkF2fs.c_str(), X_OK) && fs_mgr_overlayfs_filesystem_available("f2fs")) {
+        return "f2fs";
+    }
+    if (!access(kMkExt4.c_str(), X_OK) && fs_mgr_overlayfs_filesystem_available("ext4")) {
+        return "ext4";
+    }
     return "auto";
 }
 
@@ -657,7 +644,7 @@
     if (mnt_type == "f2fs") {
         command = kMkF2fs + " -w 4096 -f -d1 -l" + android::base::Basename(kScratchMountPoint);
     } else if (mnt_type == "ext4") {
-        command = kMkExt4 + " -b 4096 -t ext4 -m 0 -O has_journal -M " + kScratchMountPoint;
+        command = kMkExt4 + " -F -b 4096 -t ext4 -m 0 -O has_journal -M " + kScratchMountPoint;
     } else {
         errno = ESRCH;
         LERROR << mnt_type << " has no mkfs cookbook";
@@ -821,7 +808,10 @@
 
     auto scratch_can_be_mounted = true;
     for (const auto& mount_point : fs_mgr_candidate_list(fstab)) {
-        if (fs_mgr_overlayfs_already_mounted(mount_point)) continue;
+        if (fs_mgr_overlayfs_already_mounted(mount_point)) {
+            ret = true;
+            continue;
+        }
         if (scratch_can_be_mounted) {
             scratch_can_be_mounted = false;
             auto scratch_device = fs_mgr_overlayfs_scratch_device();
@@ -1002,7 +992,7 @@
     if (fs_mgr_access("/sys/module/overlay/parameters/override_creds")) {
         return OverlayfsValidResult::kOverrideCredsRequired;
     }
-    if (!fs_mgr_access("/sys/module/overlay")) {
+    if (!fs_mgr_overlayfs_filesystem_available("overlay")) {
         return OverlayfsValidResult::kNotSupported;
     }
     struct utsname uts;
diff --git a/fs_mgr/fs_mgr_priv.h b/fs_mgr/fs_mgr_priv.h
index 83e5d7b..166c32b 100644
--- a/fs_mgr/fs_mgr_priv.h
+++ b/fs_mgr/fs_mgr_priv.h
@@ -14,8 +14,7 @@
  * limitations under the License.
  */
 
-#ifndef __CORE_FS_MGR_PRIV_H
-#define __CORE_FS_MGR_PRIV_H
+#pragma once
 
 #include <chrono>
 #include <string>
@@ -85,53 +84,6 @@
  *
  */
 
-// clang-format off
-#define MF_WAIT                  0x1
-#define MF_CHECK                 0x2
-#define MF_CRYPT                 0x4
-#define MF_NONREMOVABLE          0x8
-#define MF_VOLDMANAGED          0x10
-#define MF_LENGTH               0x20
-#define MF_RECOVERYONLY         0x40
-#define MF_SWAPPRIO             0x80
-#define MF_ZRAMSIZE            0x100
-#define MF_VERIFY              0x200
-#define MF_FORCECRYPT          0x400
-#define MF_NOEMULATEDSD        0x800 /* no emulated sdcard daemon, sd card is the only
-                                        external storage */
-#define MF_NOTRIM             0x1000
-#define MF_FILEENCRYPTION     0x2000
-#define MF_FORMATTABLE        0x4000
-#define MF_SLOTSELECT         0x8000
-#define MF_FORCEFDEORFBE     0x10000
-#define MF_LATEMOUNT         0x20000
-#define MF_NOFAIL            0x40000
-#define MF_VERIFYATBOOT      0x80000
-#define MF_MAX_COMP_STREAMS 0x100000
-#define MF_RESERVEDSIZE     0x200000
-#define MF_QUOTA            0x400000
-#define MF_ERASEBLKSIZE     0x800000
-#define MF_LOGICALBLKSIZE  0X1000000
-#define MF_AVB             0X2000000
-#define MF_KEYDIRECTORY    0X4000000
-#define MF_SYSFS           0X8000000
-#define MF_LOGICAL        0x10000000
-#define MF_CHECKPOINT_BLK 0x20000000
-#define MF_CHECKPOINT_FS  0x40000000
-#define MF_FIRST_STAGE_MOUNT \
-                          0x80000000
-#define MF_SLOTSELECT_OTHER  \
-                         0x100000000
-#define MF_ZRAM_LOOPBACK_PATH    \
-                         0x200000000
-#define MF_ZRAM_LOOPBACK_SIZE    \
-                         0x400000000
-#define MF_ZRAM_BACKING_DEV_PATH \
-                         0x800000000
-#define MF_FS_VERITY  \
-                         0x1000000000
-// clang-format on
-
 #define DM_BUF_SIZE 4096
 
 using namespace std::chrono_literals;
@@ -148,5 +100,3 @@
 const std::string& get_android_dt_dir();
 bool is_dt_compatible();
 int load_verity_state(const android::fs_mgr::FstabEntry& entry, int* mode);
-
-#endif /* __CORE_FS_MGR_PRIV_H */
diff --git a/fs_mgr/include/fs_mgr.h b/fs_mgr/include/fs_mgr.h
index 8af80a7..a3bb852 100644
--- a/fs_mgr/include/fs_mgr.h
+++ b/fs_mgr/include/fs_mgr.h
@@ -14,8 +14,7 @@
  * limitations under the License.
  */
 
-#ifndef __CORE_FS_MGR_H
-#define __CORE_FS_MGR_H
+#pragma once
 
 #include <stdio.h>
 #include <stdint.h>
@@ -73,8 +72,8 @@
                         const std::string& mount_point = "");
 int fs_mgr_do_tmpfs_mount(const char *n_name);
 bool fs_mgr_load_verity_state(int* mode);
-bool fs_mgr_update_verity_state(
-        std::function<void(const std::string& mount_point, int mode)> callback);
+// Returns true if verity is enabled on this particular FstabEntry.
+bool fs_mgr_is_verity_enabled(const android::fs_mgr::FstabEntry& entry);
 bool fs_mgr_swapon_all(const android::fs_mgr::Fstab& fstab);
 bool fs_mgr_update_logical_partition(android::fs_mgr::FstabEntry* entry);
 
@@ -90,5 +89,3 @@
 // specified, the super partition for the corresponding metadata slot will be
 // returned. Otherwise, it will use the current slot.
 std::string fs_mgr_get_super_partition_name(int slot = -1);
-
-#endif /* __CORE_FS_MGR_H */
diff --git a/fs_mgr/libfs_avb/Android.bp b/fs_mgr/libfs_avb/Android.bp
index 3e93265..a3c76ab 100644
--- a/fs_mgr/libfs_avb/Android.bp
+++ b/fs_mgr/libfs_avb/Android.bp
@@ -24,6 +24,8 @@
         "avb_ops.cpp",
         "avb_util.cpp",
         "fs_avb.cpp",
+        "fs_avb_util.cpp",
+        "types.cpp",
         "util.cpp",
     ],
     static_libs: [
@@ -98,6 +100,7 @@
     srcs: [
         "tests/basic_test.cpp",
         "tests/fs_avb_test.cpp",
+        "tests/fs_avb_util_test.cpp",
     ],
 }
 
@@ -115,3 +118,26 @@
         "tests/util_test.cpp",
     ],
 }
+
+cc_test {
+    name: "libfs_avb_device_test",
+    test_suites: ["device-tests"],
+    static_libs: [
+        "libavb",
+        "libdm",
+        "libfs_avb",
+        "libfstab",
+    ],
+    shared_libs: [
+        "libbase",
+        "libcrypto",
+    ],
+    srcs: [
+        "tests/fs_avb_device_test.cpp",
+    ],
+    cflags: [
+        "-Wall",
+        "-Wextra",
+        "-Werror",
+    ],
+}
diff --git a/fs_mgr/libfs_avb/avb_ops.h b/fs_mgr/libfs_avb/avb_ops.h
index c0f12aa..a849d94 100644
--- a/fs_mgr/libfs_avb/avb_ops.h
+++ b/fs_mgr/libfs_avb/avb_ops.h
@@ -27,7 +27,7 @@
 #include <string>
 #include <vector>
 
-#include <fs_avb/fs_avb.h>
+#include <fs_avb/types.h>
 #include <libavb/libavb.h>
 
 namespace android {
diff --git a/fs_mgr/libfs_avb/avb_util.cpp b/fs_mgr/libfs_avb/avb_util.cpp
index 08f87b4..fa9080e 100644
--- a/fs_mgr/libfs_avb/avb_util.cpp
+++ b/fs_mgr/libfs_avb/avb_util.cpp
@@ -34,56 +34,11 @@
 namespace android {
 namespace fs_mgr {
 
-// Helper functions to print enum class VBMetaVerifyResult.
-const char* VBMetaVerifyResultToString(VBMetaVerifyResult result) {
-    // clang-format off
-    static const char* const name[] = {
-        "ResultSuccess",
-        "ResultError",
-        "ResultErrorVerification",
-        "ResultUnknown",
-    };
-    // clang-format on
-
-    uint32_t index = static_cast<uint32_t>(result);
-    uint32_t unknown_index = sizeof(name) / sizeof(char*) - 1;
-    if (index >= unknown_index) {
-        index = unknown_index;
-    }
-
-    return name[index];
-}
-
-std::ostream& operator<<(std::ostream& os, VBMetaVerifyResult result) {
-    os << VBMetaVerifyResultToString(result);
-    return os;
-}
-
-// class VBMetaData
-// ----------------
-std::unique_ptr<AvbVBMetaImageHeader> VBMetaData::GetVBMetaHeader(bool update_vbmeta_size) {
-    auto vbmeta_header = std::make_unique<AvbVBMetaImageHeader>();
-
-    if (!vbmeta_header) return nullptr;
-
-    /* Byteswap the header. */
-    avb_vbmeta_image_header_to_host_byte_order((AvbVBMetaImageHeader*)vbmeta_ptr_.get(),
-                                               vbmeta_header.get());
-    if (update_vbmeta_size) {
-        vbmeta_size_ = sizeof(AvbVBMetaImageHeader) +
-                       vbmeta_header->authentication_data_block_size +
-                       vbmeta_header->auxiliary_data_block_size;
-    }
-
-    return vbmeta_header;
-}
-
 // 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
-bool ConstructVerityTable(const AvbHashtreeDescriptor& hashtree_desc, const std::string& salt,
-                          const std::string& root_digest, const std::string& blk_device,
-                          android::dm::DmTable* table) {
+bool ConstructVerityTable(const FsAvbHashtreeDescriptor& hashtree_desc,
+                          const std::string& blk_device, android::dm::DmTable* table) {
     // Loads androidboot.veritymode from kernel cmdline.
     std::string verity_mode;
     if (!fs_mgr_get_boot_config("veritymode", &verity_mode)) {
@@ -104,12 +59,12 @@
     std::ostringstream hash_algorithm;
     hash_algorithm << hashtree_desc.hash_algorithm;
 
-    android::dm::DmTargetVerity target(0, hashtree_desc.image_size / 512,
-                                       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,
-                                       hash_algorithm.str(), root_digest, salt);
+    android::dm::DmTargetVerity target(
+            0, hashtree_desc.image_size / 512, 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, hash_algorithm.str(),
+            hashtree_desc.root_digest, hashtree_desc.salt);
     if (hashtree_desc.fec_size > 0) {
         target.UseFec(blk_device, hashtree_desc.fec_num_roots,
                       hashtree_desc.fec_offset / hashtree_desc.data_block_size,
@@ -126,12 +81,10 @@
     return table->AddTarget(std::make_unique<android::dm::DmTargetVerity>(target));
 }
 
-bool HashtreeDmVeritySetup(FstabEntry* fstab_entry, const AvbHashtreeDescriptor& hashtree_desc,
-                           const std::string& salt, const std::string& root_digest,
+bool HashtreeDmVeritySetup(FstabEntry* fstab_entry, const FsAvbHashtreeDescriptor& hashtree_desc,
                            bool wait_for_verity_dev) {
     android::dm::DmTable table;
-    if (!ConstructVerityTable(hashtree_desc, salt, root_digest, fstab_entry->blk_device, &table) ||
-        !table.valid()) {
+    if (!ConstructVerityTable(hashtree_desc, fstab_entry->blk_device, &table) || !table.valid()) {
         LERROR << "Failed to construct verity table.";
         return false;
     }
@@ -164,12 +117,11 @@
     return true;
 }
 
-std::unique_ptr<AvbHashtreeDescriptor> GetHashtreeDescriptor(
-    const std::string& partition_name, const std::vector<VBMetaData>& vbmeta_images,
-    std::string* out_salt, std::string* out_digest) {
+std::unique_ptr<FsAvbHashtreeDescriptor> GetHashtreeDescriptor(
+        const std::string& partition_name, const std::vector<VBMetaData>& vbmeta_images) {
     bool found = false;
     const uint8_t* desc_partition_name;
-    auto hashtree_desc = std::make_unique<AvbHashtreeDescriptor>();
+    auto hashtree_desc = std::make_unique<FsAvbHashtreeDescriptor>();
 
     for (const auto& vbmeta : vbmeta_images) {
         size_t num_descriptors;
@@ -209,15 +161,17 @@
     }
 
     if (!found) {
-        LERROR << "Partition descriptor not found: " << partition_name.c_str();
+        LERROR << "Hashtree descriptor not found: " << partition_name;
         return nullptr;
     }
 
+    hashtree_desc->partition_name = partition_name;
+
     const uint8_t* desc_salt = desc_partition_name + hashtree_desc->partition_name_len;
-    *out_salt = BytesToHex(desc_salt, hashtree_desc->salt_len);
+    hashtree_desc->salt = BytesToHex(desc_salt, hashtree_desc->salt_len);
 
     const uint8_t* desc_digest = desc_salt + hashtree_desc->salt_len;
-    *out_digest = BytesToHex(desc_digest, hashtree_desc->root_digest_len);
+    hashtree_desc->root_digest = BytesToHex(desc_digest, hashtree_desc->root_digest_len);
 
     return hashtree_desc;
 }
@@ -235,18 +189,15 @@
         return false;
     }
 
-    std::string salt;
-    std::string root_digest;
-    std::unique_ptr<AvbHashtreeDescriptor> hashtree_descriptor =
-        GetHashtreeDescriptor(partition_name, vbmeta_images, &salt, &root_digest);
+    std::unique_ptr<FsAvbHashtreeDescriptor> hashtree_descriptor =
+            GetHashtreeDescriptor(partition_name, vbmeta_images);
     if (!hashtree_descriptor) {
         return false;
     }
 
     // Converts HASHTREE descriptor to verity table to load into kernel.
     // When success, the new device path will be returned, e.g., /dev/block/dm-2.
-    return HashtreeDmVeritySetup(fstab_entry, *hashtree_descriptor, salt, root_digest,
-                                 wait_for_verity_dev);
+    return HashtreeDmVeritySetup(fstab_entry, *hashtree_descriptor, wait_for_verity_dev);
 }
 
 // Converts a AVB partition_name (without A/B suffix) to a device partition name.
@@ -420,6 +371,10 @@
     uint64_t vbmeta_size = VBMetaData::kMaxVBMetaSize;
     bool is_vbmeta_partition = StartsWith(partition_name, "vbmeta");
 
+    if (out_verify_result) {
+        *out_verify_result = VBMetaVerifyResult::kError;
+    }
+
     if (!is_vbmeta_partition) {
         std::unique_ptr<AvbFooter> footer = GetAvbFooter(fd);
         if (!footer) {
@@ -445,7 +400,10 @@
 
     auto verify_result =
             VerifyVBMetaSignature(*vbmeta, expected_public_key_blob, out_public_key_data);
-    if (out_verify_result != nullptr) *out_verify_result = verify_result;
+
+    if (out_verify_result != nullptr) {
+        *out_verify_result = verify_result;
+    }
 
     if (verify_result == VBMetaVerifyResult::kSuccess ||
         verify_result == VBMetaVerifyResult::kErrorVerification) {
@@ -508,6 +466,10 @@
         const std::string& expected_public_key_blob, bool allow_verification_error,
         bool rollback_protection, bool is_chained_vbmeta, std::string* out_public_key_data,
         bool* out_verification_disabled, VBMetaVerifyResult* out_verify_result) {
+    if (out_verify_result) {
+        *out_verify_result = VBMetaVerifyResult::kError;
+    }
+
     // Ensures the device path (might be a symlink created by init) is ready to access.
     if (!WaitForFile(image_path, 1s)) {
         PERROR << "No such path: " << image_path;
diff --git a/fs_mgr/libfs_avb/avb_util.h b/fs_mgr/libfs_avb/avb_util.h
index 4b54e27..9babd88 100644
--- a/fs_mgr/libfs_avb/avb_util.h
+++ b/fs_mgr/libfs_avb/avb_util.h
@@ -24,19 +24,11 @@
 #include <libavb/libavb.h>
 #include <libdm/dm.h>
 
-#include "fs_avb/fs_avb.h"
+#include "fs_avb/types.h"
 
 namespace android {
 namespace fs_mgr {
 
-enum class VBMetaVerifyResult {
-    kSuccess = 0,
-    kError = 1,
-    kErrorVerification = 2,
-};
-
-std::ostream& operator<<(std::ostream& os, VBMetaVerifyResult);
-
 struct ChainInfo {
     std::string partition_name;
     std::string public_key_blob;
@@ -46,16 +38,13 @@
 };
 
 // AvbHashtreeDescriptor to dm-verity table setup.
-std::unique_ptr<AvbHashtreeDescriptor> GetHashtreeDescriptor(
-    const std::string& partition_name, const std::vector<VBMetaData>& vbmeta_images,
-    std::string* out_salt, std::string* out_digest);
+std::unique_ptr<FsAvbHashtreeDescriptor> GetHashtreeDescriptor(
+        const std::string& partition_name, const std::vector<VBMetaData>& vbmeta_images);
 
-bool ConstructVerityTable(const AvbHashtreeDescriptor& hashtree_desc, const std::string& salt,
-                          const std::string& root_digest, const std::string& blk_device,
-                          android::dm::DmTable* table);
+bool ConstructVerityTable(const FsAvbHashtreeDescriptor& hashtree_desc,
+                          const std::string& blk_device, android::dm::DmTable* table);
 
-bool HashtreeDmVeritySetup(FstabEntry* fstab_entry, const AvbHashtreeDescriptor& hashtree_desc,
-                           const std::string& salt, const std::string& root_digest,
+bool HashtreeDmVeritySetup(FstabEntry* fstab_entry, const FsAvbHashtreeDescriptor& hashtree_desc,
                            bool wait_for_verity_dev);
 
 // Searches a Avb hashtree descriptor in vbmeta_images for fstab_entry, to enable dm-verity.
diff --git a/fs_mgr/libfs_avb/fs_avb.cpp b/fs_mgr/libfs_avb/fs_avb.cpp
index 1af3b33..938e149 100644
--- a/fs_mgr/libfs_avb/fs_avb.cpp
+++ b/fs_mgr/libfs_avb/fs_avb.cpp
@@ -76,33 +76,6 @@
     return std::make_pair(digest, total_size);
 }
 
-// Helper functions to dump enum class AvbHandleStatus.
-const char* AvbHandleStatusToString(AvbHandleStatus status) {
-    // clang-format off
-    static const char* const name[] = {
-        "Success",
-        "Uninitialized",
-        "HashtreeDisabled",
-        "VerificationDisabled",
-        "VerificationError",
-        "Unknown",
-    };
-    // clang-format on
-
-    uint32_t index = static_cast<uint32_t>(status);
-    uint32_t unknown_index = sizeof(name) / sizeof(char*) - 1;
-    if (index >= unknown_index) {
-        index = unknown_index;
-    }
-
-    return name[index];
-}
-
-std::ostream& operator<<(std::ostream& os, AvbHandleStatus status) {
-    os << AvbHandleStatusToString(status);
-    return os;
-}
-
 // class AvbVerifier
 // -----------------
 // Reads the following values from kernel cmdline and provides the
diff --git a/fs_mgr/libfs_avb/fs_avb_util.cpp b/fs_mgr/libfs_avb/fs_avb_util.cpp
new file mode 100644
index 0000000..f82f83d
--- /dev/null
+++ b/fs_mgr/libfs_avb/fs_avb_util.cpp
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2019 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 "fs_avb/fs_avb_util.h"
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include <android-base/strings.h>
+#include <fstab/fstab.h>
+#include <libavb/libavb.h>
+#include <libdm/dm.h>
+
+#include "avb_util.h"
+#include "util.h"
+
+namespace android {
+namespace fs_mgr {
+
+// Given a FstabEntry, loads and verifies the vbmeta, to extract the Avb Hashtree descriptor.
+std::unique_ptr<VBMetaData> LoadAndVerifyVbmeta(const FstabEntry& fstab_entry,
+                                                const std::string& expected_public_key_blob,
+                                                std::string* out_public_key_data,
+                                                std::string* out_avb_partition_name,
+                                                VBMetaVerifyResult* out_verify_result) {
+    // Derives partition_name from blk_device to query the corresponding AVB HASHTREE descriptor
+    // to setup dm-verity. The partition_names in AVB descriptors are without A/B suffix.
+    std::string avb_partition_name = DeriveAvbPartitionName(fstab_entry, fs_mgr_get_slot_suffix(),
+                                                            fs_mgr_get_other_slot_suffix());
+    if (out_avb_partition_name) {
+        *out_avb_partition_name = avb_partition_name;
+    }
+
+    // Updates fstab_entry->blk_device from <partition> to /dev/block/dm-<N> if
+    // it's a logical partition.
+    std::string device_path = fstab_entry.blk_device;
+    if (fstab_entry.fs_mgr_flags.logical &&
+        !android::base::StartsWith(fstab_entry.blk_device, "/")) {
+        dm::DeviceMapper& dm = dm::DeviceMapper::Instance();
+        if (!dm.GetDmDevicePathByName(fstab_entry.blk_device, &device_path)) {
+            LERROR << "Failed to resolve logical device path for: " << fstab_entry.blk_device;
+            return nullptr;
+        }
+    }
+
+    return LoadAndVerifyVbmetaByPath(device_path, avb_partition_name, expected_public_key_blob,
+                                     true /* allow_verification_error */,
+                                     false /* rollback_protection */, false /* is_chained_vbmeta */,
+                                     out_public_key_data, nullptr /* out_verification_disabled */,
+                                     out_verify_result);
+}
+
+// Given a path, loads and verifies the vbmeta, to extract the Avb Hashtree descriptor.
+std::unique_ptr<FsAvbHashtreeDescriptor> GetHashtreeDescriptor(
+        const std::string& avb_partition_name, VBMetaData&& vbmeta) {
+    if (!vbmeta.size()) return nullptr;
+
+    std::vector<VBMetaData> vbmeta_images;
+    vbmeta_images.emplace_back(std::move(vbmeta));
+    return GetHashtreeDescriptor(avb_partition_name, vbmeta_images);
+}
+
+}  // namespace fs_mgr
+}  // namespace android
diff --git a/fs_mgr/libfs_avb/include/fs_avb/fs_avb.h b/fs_mgr/libfs_avb/include/fs_avb/fs_avb.h
index d4e3a6e..d026722 100644
--- a/fs_mgr/libfs_avb/include/fs_avb/fs_avb.h
+++ b/fs_mgr/libfs_avb/include/fs_avb/fs_avb.h
@@ -21,32 +21,13 @@
 #include <string>
 #include <vector>
 
+#include <fs_avb/types.h>
 #include <fstab/fstab.h>
 #include <libavb/libavb.h>
 
 namespace android {
 namespace fs_mgr {
 
-enum class AvbHashtreeResult {
-    kSuccess = 0,
-    kFail,
-    kDisabled,
-};
-
-enum class HashAlgorithm {
-    kInvalid = 0,
-    kSHA256 = 1,
-    kSHA512 = 2,
-};
-
-enum class AvbHandleStatus {
-    kSuccess = 0,
-    kUninitialized = 1,
-    kHashtreeDisabled = 2,
-    kVerificationDisabled = 3,
-    kVerificationError = 4,
-};
-
 struct VBMetaInfo {
     std::string digest;
     HashAlgorithm hash_algorithm;
@@ -58,51 +39,6 @@
         : digest(std::move(digest_value)), hash_algorithm(algorithm), total_size(size) {}
 };
 
-class VBMetaData {
-  public:
-    // Constructors
-    VBMetaData() : vbmeta_ptr_(nullptr), vbmeta_size_(0){};
-
-    VBMetaData(const uint8_t* data, size_t size, const std::string& partition_name)
-        : vbmeta_ptr_(new (std::nothrow) uint8_t[size]),
-          vbmeta_size_(size),
-          partition_name_(partition_name) {
-        // The ownership of data is NOT transferred, i.e., the caller still
-        // needs to release the memory as we make a copy here.
-        memcpy(vbmeta_ptr_.get(), data, size * sizeof(uint8_t));
-    }
-
-    explicit VBMetaData(size_t size, const std::string& partition_name)
-        : vbmeta_ptr_(new (std::nothrow) uint8_t[size]),
-          vbmeta_size_(size),
-          partition_name_(partition_name) {}
-
-    // Extracts vbmeta header from the vbmeta buffer, set update_vbmeta_size to
-    // true to update vbmeta_size_ to the actual size with valid content.
-    std::unique_ptr<AvbVBMetaImageHeader> GetVBMetaHeader(bool update_vbmeta_size = false);
-
-    // Sets the vbmeta_path where we load the vbmeta data. Could be a partition or a file.
-    // e.g.,
-    // - /dev/block/by-name/system_a
-    // - /path/to/system_other.img.
-    void set_vbmeta_path(std::string vbmeta_path) { vbmeta_path_ = std::move(vbmeta_path); }
-
-    // Get methods for each data member.
-    const std::string& partition() const { return partition_name_; }
-    const std::string& vbmeta_path() const { return vbmeta_path_; }
-    uint8_t* data() const { return vbmeta_ptr_.get(); }
-    const size_t& size() const { return vbmeta_size_; }
-
-    // Maximum size of a vbmeta data - 64 KiB.
-    static const size_t kMaxVBMetaSize = 64 * 1024;
-
-  private:
-    std::unique_ptr<uint8_t[]> vbmeta_ptr_;
-    size_t vbmeta_size_;
-    std::string partition_name_;
-    std::string vbmeta_path_;
-};
-
 class FsManagerAvbOps;
 
 class AvbHandle;
diff --git a/fs_mgr/libfs_avb/include/fs_avb/fs_avb_util.h b/fs_mgr/libfs_avb/include/fs_avb/fs_avb_util.h
new file mode 100644
index 0000000..ec8badb
--- /dev/null
+++ b/fs_mgr/libfs_avb/include/fs_avb/fs_avb_util.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <string>
+
+#include <fs_avb/types.h>
+#include <fstab/fstab.h>
+#include <libavb/libavb.h>
+
+namespace android {
+namespace fs_mgr {
+
+// Given a FstabEntry, loads and verifies the vbmeta.
+std::unique_ptr<VBMetaData> LoadAndVerifyVbmeta(const FstabEntry& fstab_entry,
+                                                const std::string& expected_public_key_blob,
+                                                std::string* out_public_key_data,
+                                                std::string* out_avb_partition_name,
+                                                VBMetaVerifyResult* out_verify_result);
+
+// Gets the hashtree descriptor for avb_partition_name from the vbmeta.
+std::unique_ptr<FsAvbHashtreeDescriptor> GetHashtreeDescriptor(
+        const std::string& avb_partition_name, VBMetaData&& vbmeta);
+
+}  // namespace fs_mgr
+}  // namespace android
diff --git a/fs_mgr/libfs_avb/include/fs_avb/types.h b/fs_mgr/libfs_avb/include/fs_avb/types.h
new file mode 100644
index 0000000..bd638e6
--- /dev/null
+++ b/fs_mgr/libfs_avb/include/fs_avb/types.h
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <cstring>
+#include <memory>
+#include <ostream>
+
+#include <libavb/libavb.h>
+
+namespace android {
+namespace fs_mgr {
+
+enum class VBMetaVerifyResult {
+    kSuccess = 0,
+    kError = 1,
+    kErrorVerification = 2,
+};
+
+std::ostream& operator<<(std::ostream& os, VBMetaVerifyResult);
+
+enum class AvbHashtreeResult {
+    kSuccess = 0,
+    kFail,
+    kDisabled,
+};
+
+enum class HashAlgorithm {
+    kInvalid = 0,
+    kSHA256 = 1,
+    kSHA512 = 2,
+};
+
+enum class AvbHandleStatus {
+    kSuccess = 0,
+    kUninitialized = 1,
+    kHashtreeDisabled = 2,
+    kVerificationDisabled = 3,
+    kVerificationError = 4,
+};
+
+std::ostream& operator<<(std::ostream& os, AvbHandleStatus status);
+
+struct FsAvbHashtreeDescriptor : AvbHashtreeDescriptor {
+    std::string partition_name;
+    std::string salt;
+    std::string root_digest;
+};
+
+class VBMetaData {
+  public:
+    // Constructors
+    VBMetaData() : vbmeta_ptr_(nullptr), vbmeta_size_(0){};
+
+    VBMetaData(const uint8_t* data, size_t size, const std::string& partition_name)
+        : vbmeta_ptr_(new (std::nothrow) uint8_t[size]),
+          vbmeta_size_(size),
+          partition_name_(partition_name) {
+        // The ownership of data is NOT transferred, i.e., the caller still
+        // needs to release the memory as we make a copy here.
+        std::memcpy(vbmeta_ptr_.get(), data, size * sizeof(uint8_t));
+    }
+
+    explicit VBMetaData(size_t size, const std::string& partition_name)
+        : vbmeta_ptr_(new (std::nothrow) uint8_t[size]),
+          vbmeta_size_(size),
+          partition_name_(partition_name) {}
+
+    // Extracts vbmeta header from the vbmeta buffer, set update_vbmeta_size to
+    // true to update vbmeta_size_ to the actual size with valid content.
+    std::unique_ptr<AvbVBMetaImageHeader> GetVBMetaHeader(bool update_vbmeta_size = false);
+
+    // Sets the vbmeta_path where we load the vbmeta data. Could be a partition or a file.
+    // e.g.,
+    // - /dev/block/by-name/system_a
+    // - /path/to/system_other.img.
+    void set_vbmeta_path(std::string vbmeta_path) { vbmeta_path_ = std::move(vbmeta_path); }
+
+    // Get methods for each data member.
+    const std::string& partition() const { return partition_name_; }
+    const std::string& vbmeta_path() const { return vbmeta_path_; }
+    uint8_t* data() const { return vbmeta_ptr_.get(); }
+    const size_t& size() const { return vbmeta_size_; }
+
+    // Maximum size of a vbmeta data - 64 KiB.
+    static const size_t kMaxVBMetaSize = 64 * 1024;
+
+  private:
+    std::unique_ptr<uint8_t[]> vbmeta_ptr_;
+    size_t vbmeta_size_;
+    std::string partition_name_;
+    std::string vbmeta_path_;
+};
+
+}  // namespace fs_mgr
+}  // namespace android
diff --git a/fs_mgr/libfs_avb/run_tests.sh b/fs_mgr/libfs_avb/run_tests.sh
new file mode 100755
index 0000000..5d2ce3d
--- /dev/null
+++ b/fs_mgr/libfs_avb/run_tests.sh
@@ -0,0 +1,8 @@
+#!/bin/sh
+#
+# Run host tests
+atest libfs_avb_test                 # Tests public libfs_avb APIs.
+atest libfs_avb_internal_test        # Tests libfs_avb private APIs.
+
+# Run device tests
+atest libfs_avb_device_test          # Test public libfs_avb APIs on a device.
diff --git a/fs_mgr/libfs_avb/tests/fs_avb_device_test.cpp b/fs_mgr/libfs_avb/tests/fs_avb_device_test.cpp
new file mode 100644
index 0000000..fc4eb5f
--- /dev/null
+++ b/fs_mgr/libfs_avb/tests/fs_avb_device_test.cpp
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2019 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 <android-base/properties.h>
+#include <fs_avb/fs_avb_util.h>
+#include <fstab/fstab.h>
+#include <gtest/gtest.h>
+
+#include <sys/types.h>
+#include <unistd.h>
+
+using android::fs_mgr::Fstab;
+using android::fs_mgr::FstabEntry;
+using android::fs_mgr::VBMetaData;
+using android::fs_mgr::VBMetaVerifyResult;
+
+namespace fs_avb_device_test {
+
+// system vbmeta might not be at the end of /system when dynamic partition is
+// enabled. Therefore, disable it by default.
+TEST(PublicFsAvbDeviceTest, DISABLED_LoadAndVerifyVbmeta_SystemVbmeta) {
+    Fstab fstab;
+    EXPECT_TRUE(ReadDefaultFstab(&fstab));
+
+    FstabEntry* system_entry = GetEntryForMountPoint(&fstab, "/system");
+    EXPECT_NE(nullptr, system_entry);
+
+    std::string out_public_key_data;
+    std::string out_avb_partition_name;
+    VBMetaVerifyResult out_verify_result;
+    std::unique_ptr<VBMetaData> vbmeta =
+            LoadAndVerifyVbmeta(*system_entry, "" /* expected_public_key_blob */,
+                                &out_public_key_data, &out_avb_partition_name, &out_verify_result);
+
+    EXPECT_NE(nullptr, vbmeta);
+    EXPECT_EQ(VBMetaVerifyResult::kSuccess, out_verify_result);
+    EXPECT_EQ("system", out_avb_partition_name);
+    EXPECT_NE("", out_public_key_data);
+}
+
+TEST(PublicFsAvbDeviceTest, GetHashtreeDescriptor_SystemOther) {
+    // Non-A/B device doesn't have system_other partition.
+    if (fs_mgr_get_slot_suffix() == "") return;
+
+    // Skip running this test if system_other is a logical partition.
+    // Note that system_other is still a physical partition on "retrofit" devices.
+    if (android::base::GetBoolProperty("ro.boot.dynamic_partitions", false) &&
+        !android::base::GetBoolProperty("ro.boot.dynamic_partitions_retrofit", false)) {
+        return;
+    }
+
+    Fstab fstab;
+    EXPECT_TRUE(ReadFstabFromFile("/system/etc/fstab.postinstall", &fstab));
+
+    // It should have two lines in the fstab, the first for logical system_other,
+    // the other for physical system_other.
+    EXPECT_EQ(2UL, fstab.size());
+
+    // Use the 2nd fstab entry, which is for physical system_other partition.
+    FstabEntry* system_other = &fstab[1];
+    EXPECT_NE(nullptr, system_other);
+
+    std::string out_public_key_data;
+    std::string out_avb_partition_name;
+    VBMetaVerifyResult out_verify_result;
+    std::unique_ptr<VBMetaData> system_other_vbmeta =
+            LoadAndVerifyVbmeta(*system_other, "" /* expected_public_key_blob */,
+                                &out_public_key_data, &out_avb_partition_name, &out_verify_result);
+
+    EXPECT_NE(nullptr, system_other_vbmeta);
+    EXPECT_EQ(VBMetaVerifyResult::kSuccess, out_verify_result);
+    EXPECT_EQ("system_other", out_avb_partition_name);
+    EXPECT_NE("", out_public_key_data);
+
+    auto hashtree_desc =
+            GetHashtreeDescriptor(out_avb_partition_name, std::move(*system_other_vbmeta));
+    EXPECT_NE(nullptr, hashtree_desc);
+}
+
+}  // namespace fs_avb_device_test
diff --git a/fs_mgr/libfs_avb/tests/fs_avb_test_util.h b/fs_mgr/libfs_avb/tests/fs_avb_test_util.h
index 2e46644..ab1980b 100644
--- a/fs_mgr/libfs_avb/tests/fs_avb_test_util.h
+++ b/fs_mgr/libfs_avb/tests/fs_avb_test_util.h
@@ -29,7 +29,7 @@
 #include <android-base/unique_fd.h>
 #include <base/files/file_path.h>
 #include <base/strings/stringprintf.h>
-#include <fs_avb/fs_avb.h>
+#include <fs_avb/types.h>
 #include <gtest/gtest.h>
 
 // Utility macro to run the command expressed by the printf()-style string
diff --git a/fs_mgr/libfs_avb/tests/fs_avb_util_test.cpp b/fs_mgr/libfs_avb/tests/fs_avb_util_test.cpp
new file mode 100644
index 0000000..7c34009
--- /dev/null
+++ b/fs_mgr/libfs_avb/tests/fs_avb_util_test.cpp
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2019 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 <fs_avb/fs_avb_util.h>
+
+#include "fs_avb_test_util.h"
+
+namespace fs_avb_host_test {
+
+class PublicFsAvbUtilTest : public BaseFsAvbTest {
+  public:
+    PublicFsAvbUtilTest(){};
+
+  protected:
+    ~PublicFsAvbUtilTest(){};
+};
+
+TEST_F(PublicFsAvbUtilTest, GetHashtreeDescriptor) {
+    // Generates a raw system_other.img, use a smaller size to speed-up unit test.
+    const size_t system_image_size = 10 * 1024 * 1024;
+    const size_t system_partition_size = 15 * 1024 * 1024;
+    base::FilePath system_path = GenerateImage("system.img", system_image_size);
+
+    // Adds AVB Hashtree Footer.
+    AddAvbFooter(system_path, "hashtree", "system", system_partition_size, "SHA512_RSA4096", 20,
+                 data_dir_.Append("testkey_rsa4096.pem"), "d00df00d",
+                 "--internal_release_string \"unit test\"");
+
+    auto system_vbmeta = ExtractAndLoadVBMetaData(system_path, "system-vbmeta.img");
+
+    auto hashtree_desc =
+            GetHashtreeDescriptor("system" /* avb_partition_name */, std::move(system_vbmeta));
+    EXPECT_NE(nullptr, hashtree_desc);
+
+    // Checks the returned hashtree_desc matches the following info returned by avbtool.
+    EXPECT_EQ(
+            "Footer version:           1.0\n"
+            "Image size:               15728640 bytes\n"
+            "Original image size:      10485760 bytes\n"
+            "VBMeta offset:            10661888\n"
+            "VBMeta size:              2112 bytes\n"
+            "--\n"
+            "Minimum libavb version:   1.0\n"
+            "Header Block:             256 bytes\n"
+            "Authentication Block:     576 bytes\n"
+            "Auxiliary Block:          1280 bytes\n"
+            "Algorithm:                SHA512_RSA4096\n"
+            "Rollback Index:           20\n"
+            "Flags:                    0\n"
+            "Release String:           'unit test'\n"
+            "Descriptors:\n"
+            "    Hashtree descriptor:\n"
+            "      Version of dm-verity:  1\n"
+            "      Image Size:            10485760 bytes\n"
+            "      Tree Offset:           10485760\n"
+            "      Tree Size:             86016 bytes\n"
+            "      Data Block Size:       4096 bytes\n"
+            "      Hash Block Size:       4096 bytes\n"
+            "      FEC num roots:         2\n"
+            "      FEC offset:            10571776\n"
+            "      FEC size:              90112 bytes\n"
+            "      Hash Algorithm:        sha1\n"
+            "      Partition Name:        system\n"
+            "      Salt:                  d00df00d\n"
+            "      Root Digest:           a3d5dd307341393d85de356c384ff543ec1ed81b\n"
+            "      Flags:                 0\n",
+            InfoImage(system_path));
+
+    EXPECT_EQ(1UL, hashtree_desc->dm_verity_version);
+    EXPECT_EQ(10485760UL, hashtree_desc->image_size);
+    EXPECT_EQ(10485760UL, hashtree_desc->tree_offset);
+    EXPECT_EQ(86016UL, hashtree_desc->tree_size);
+    EXPECT_EQ(4096UL, hashtree_desc->data_block_size);
+    EXPECT_EQ(4096UL, hashtree_desc->hash_block_size);
+    EXPECT_EQ(2UL, hashtree_desc->fec_num_roots);
+    EXPECT_EQ(10571776UL, hashtree_desc->fec_offset);
+    EXPECT_EQ(90112UL, hashtree_desc->fec_size);
+    EXPECT_EQ(std::string("sha1"),
+              std::string(reinterpret_cast<const char*>(hashtree_desc->hash_algorithm)));
+    EXPECT_EQ(std::string("system").length(), hashtree_desc->partition_name_len);
+    EXPECT_EQ(hashtree_desc->partition_name, "system");
+    EXPECT_EQ(hashtree_desc->salt, "d00df00d");
+    EXPECT_EQ(hashtree_desc->root_digest, "a3d5dd307341393d85de356c384ff543ec1ed81b");
+
+    // Checks it's null if partition name doesn't match.
+    EXPECT_EQ(nullptr, GetHashtreeDescriptor("system_not_exist" /* avb_partition_name */,
+                                             std::move(system_vbmeta)));
+}
+
+TEST_F(PublicFsAvbUtilTest, GetHashtreeDescriptor_NotFound) {
+    // Generates a raw boot.img
+    const size_t image_size = 5 * 1024 * 1024;
+    const size_t partition_size = 10 * 1024 * 1024;
+    base::FilePath boot_path = GenerateImage("boot.img", image_size);
+    // Appends AVB Hash Footer.
+    AddAvbFooter(boot_path, "hash", "boot", partition_size, "SHA256_RSA4096", 10,
+                 data_dir_.Append("testkey_rsa4096.pem"), "d00df00d",
+                 "--internal_release_string \"unit test\"");
+    // Extracts boot vbmeta from boot.img into boot-vbmeta.img.
+    auto boot_vbmeta = ExtractAndLoadVBMetaData(boot_path, "boot-vbmeta.img");
+
+    auto hashtree_desc =
+            GetHashtreeDescriptor("boot" /* avb_partition_name */, std::move(boot_vbmeta));
+    EXPECT_EQ(nullptr, hashtree_desc);
+}
+
+}  // namespace fs_avb_host_test
diff --git a/fs_mgr/libfs_avb/types.cpp b/fs_mgr/libfs_avb/types.cpp
new file mode 100644
index 0000000..3c277f3
--- /dev/null
+++ b/fs_mgr/libfs_avb/types.cpp
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2019 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 "fs_avb/types.h"
+
+namespace android {
+namespace fs_mgr {
+
+// Helper functions to print enum class VBMetaVerifyResult.
+const char* VBMetaVerifyResultToString(VBMetaVerifyResult result) {
+    // clang-format off
+    static const char* const name[] = {
+        "ResultSuccess",
+        "ResultError",
+        "ResultErrorVerification",
+        "ResultUnknown",
+    };
+    // clang-format on
+
+    uint32_t index = static_cast<uint32_t>(result);
+    uint32_t unknown_index = sizeof(name) / sizeof(char*) - 1;
+    if (index >= unknown_index) {
+        index = unknown_index;
+    }
+
+    return name[index];
+}
+
+std::ostream& operator<<(std::ostream& os, VBMetaVerifyResult result) {
+    os << VBMetaVerifyResultToString(result);
+    return os;
+}
+
+// Helper functions to dump enum class AvbHandleStatus.
+const char* AvbHandleStatusToString(AvbHandleStatus status) {
+    // clang-format off
+    static const char* const name[] = {
+        "Success",
+        "Uninitialized",
+        "HashtreeDisabled",
+        "VerificationDisabled",
+        "VerificationError",
+        "Unknown",
+    };
+    // clang-format on
+
+    uint32_t index = static_cast<uint32_t>(status);
+    uint32_t unknown_index = sizeof(name) / sizeof(char*) - 1;
+    if (index >= unknown_index) {
+        index = unknown_index;
+    }
+
+    return name[index];
+}
+
+std::ostream& operator<<(std::ostream& os, AvbHandleStatus status) {
+    os << AvbHandleStatusToString(status);
+    return os;
+}
+
+// class VBMetaData
+// ----------------
+std::unique_ptr<AvbVBMetaImageHeader> VBMetaData::GetVBMetaHeader(bool update_vbmeta_size) {
+    auto vbmeta_header = std::make_unique<AvbVBMetaImageHeader>();
+
+    if (!vbmeta_header) return nullptr;
+
+    /* Byteswap the header. */
+    avb_vbmeta_image_header_to_host_byte_order((AvbVBMetaImageHeader*)vbmeta_ptr_.get(),
+                                               vbmeta_header.get());
+    if (update_vbmeta_size) {
+        vbmeta_size_ = sizeof(AvbVBMetaImageHeader) +
+                       vbmeta_header->authentication_data_block_size +
+                       vbmeta_header->auxiliary_data_block_size;
+    }
+
+    return vbmeta_header;
+}
+
+}  // namespace fs_mgr
+}  // namespace android
diff --git a/fs_mgr/tests/adb-remount-test.sh b/fs_mgr/tests/adb-remount-test.sh
index 4d9bc61..8298bf2 100755
--- a/fs_mgr/tests/adb-remount-test.sh
+++ b/fs_mgr/tests/adb-remount-test.sh
@@ -1,4 +1,15 @@
 #! /bin/bash
+#
+# Divided into four section:
+#
+##  USAGE
+##  Helper Variables
+##  Helper Functions
+##  MAINLINE
+
+##
+##  USAGE
+##
 
 USAGE="USAGE: `basename ${0}` [-s <SerialNumber>]
 
@@ -17,20 +28,26 @@
   exit 0
 fi
 
-# Helper Variables
+##
+##  Helper Variables
+##
 
 SPACE=" "
 # A _real_ embedded tab character
 TAB="`echo | tr '\n' '\t'`"
 # A _real_ embedded escape character
 ESCAPE="`echo | tr '\n' '\033'`"
+# A _real_ embedded carriage return character
+CR="`echo | tr '\n' '\r'`"
 GREEN="${ESCAPE}[38;5;40m"
 RED="${ESCAPE}[38;5;196m"
 ORANGE="${ESCAPE}[38;5;255:165:0m"
 BLUE="${ESCAPE}[35m"
 NORMAL="${ESCAPE}[0m"
 
-# Helper functions
+##
+##  Helper Functions
+##
 
 [ "USAGE: inFastboot
 
@@ -68,6 +85,8 @@
       args="${args}${i}"
     elif [ X"${i}" != X"${i#* }" ]; then
       args="${args}'${i}'"
+    elif [ X"${i}" != X"${i#*${TAB}}" ]; then
+      args="${args}'${i}'"
     else
       args="${args}${i}"
     fi
@@ -130,16 +149,62 @@
 
 Returns: true if the reboot command succeeded" ]
 adb_reboot() {
-  adb reboot remount-test &&
+  adb reboot remount-test || true
   sleep 2
 }
 
+[ "USAGE: format_duration [<seconds>|<seconds>s|<minutes>m|<hours>h|<days>d]
+
+human readable output whole seconds, whole minutes or mm:ss" ]
+format_duration() {
+  if [ -z "${1}" ]; then
+    echo unknown
+    return
+  fi
+  duration="${1}"
+  if [ X"${duration}" != X"${duration%s}" ]; then
+    duration=${duration%s}
+  elif [ X"${duration}" != X"${duration%m}" ]; then
+    duration=`expr ${duration%m} \* 60`
+  elif [ X"${duration}" != X"${duration%h}" ]; then
+    duration=`expr ${duration%h} \* 3600`
+  elif [ X"${duration}" != X"${duration%d}" ]; then
+    duration=`expr ${duration%d} \* 86400`
+  fi
+  seconds=`expr ${duration} % 60`
+  minutes=`expr \( ${duration} / 60 \) % 60`
+  hours=`expr ${duration} / 3600`
+  if [ 0 -eq ${minutes} -a 0 -eq ${hours} ]; then
+    if [ 1 -eq ${duration} ]; then
+      echo 1 second
+      return
+    fi
+    echo ${duration} seconds
+    return
+  elif [ 60 -eq ${duration} ]; then
+    echo 1 minute
+    return
+  elif [ 0 -eq ${seconds} -a 0 -eq ${hours} ]; then
+    echo ${minutes} minutes
+    return
+  fi
+  if [ 0 -eq ${hours} ]; then
+    echo ${minutes}:`expr ${seconds} / 10``expr ${seconds} % 10`
+    return
+  fi
+  echo ${hours}:`expr ${minutes} / 10``expr ${minutes} % 10`:`expr ${seconds} / 10``expr ${seconds} % 10`
+}
+
 [ "USAGE: adb_wait [timeout]
 
 Returns: waits until the device has returned for adb or optional timeout" ]
 adb_wait() {
   if [ -n "${1}" ]; then
+    echo -n ". . . waiting `format_duration ${1}`" ${ANDROID_SERIAL} ${USB_ADDRESS} "${CR}"
     timeout --preserve-status --signal=KILL ${1} adb wait-for-device
+    retval=${?}
+    echo -n "                                                                             ${CR}"
+    return ${retval}
   else
     adb wait-for-device
   fi
@@ -152,10 +217,14 @@
   # fastboot has no wait-for-device, but it does an automatic
   # wait and requires (even a nonsensical) command to do so.
   if [ -n "${1}" ]; then
-    timeout --preserve-status --signal=KILL ${1} fastboot wait-for-device
+    echo -n ". . . waiting `format_duration ${1}`" ${ANDROID_SERIAL} ${USB_ADDRESS} "${CR}"
+    timeout --preserve-status --signal=KILL ${1} fastboot wait-for-device >/dev/null 2>/dev/null
+    retval=${?}
+    echo -n "                                                                             ${CR}"
+    ( exit ${retval} )
   else
-    fastboot wait-for-device >/dev/null
-  fi >/dev/null 2>/dev/null ||
+    fastboot wait-for-device >/dev/null 2>/dev/null
+  fi ||
     inFastboot
 }
 
@@ -310,9 +379,14 @@
     -e "^\(overlay\|tmpfs\|none\|sysfs\|proc\|selinuxfs\|debugfs\) " \
     -e "^\(bpf\|cg2_bpf\|pstore\|tracefs\|adb\|mtp\|ptp\|devpts\) " \
     -e "^\(/data/media\|/dev/block/loop[0-9]*\) " \
+    -e "^rootfs / rootfs rw," \
     -e " /\(cache\|mnt/scratch\|mnt/vendor/persist\|persist\|metadata\) "
 }
 
+##
+##  MAINLINE
+##
+
 if [ X"-s" = X"${1}" -a -n "${2}" ]; then
   export ANDROID_SERIAL="${2}"
   shift 2
@@ -320,7 +394,7 @@
 
 inFastboot && die "device in fastboot mode"
 if ! inAdb; then
-  echo "${ORANGE}[  WARNING ]${NORMAL} device not in adb mode ... waiting 2 minutes"
+  echo "${ORANGE}[  WARNING ]${NORMAL} device not in adb mode"
   adb_wait 2m
 fi
 inAdb || die "specified device not in adb mode"
@@ -331,19 +405,38 @@
   enforcing=false
 fi
 
-# Do something
+# Do something.
 
 D=`get_property ro.serialno`
 [ -n "${D}" ] || D=`get_property ro.boot.serialno`
 [ -z "${D}" ] || ANDROID_SERIAL=${D}
+USB_SERIAL=
+[ -z "${ANDROID_SERIAL}" ] || USB_SERIAL=`find /sys/devices -name serial |
+                                          grep usb |
+                                          xargs grep -l ${ANDROID_SERIAL}`
+USB_ADDRESS=
+if [ -n "${USB_SERIAL}" ]; then
+  USB_ADDRESS=${USB_SERIAL%/serial}
+  USB_ADDRESS=usb${USB_ADDRESS##*/}
+fi
+[ -z "${ANDROID_SERIAL}${USB_ADDRESS}" ] ||
+  echo "${BLUE}[     INFO ]${NORMAL}" ${ANDROID_SERIAL} ${USB_ADDRESS} >&2
 BUILD_DESCRIPTION=`get_property ro.build.description`
-echo "${BLUE}[     INFO ]${NORMAL} ${ANDROID_SERIAL} ${BUILD_DESCRIPTION}" >&2
+[ -z "${BUILD_DESCRIPTION}" ] ||
+  echo "${BLUE}[     INFO ]${NORMAL} ${BUILD_DESCRIPTION}" >&2
+
+VERITY_WAS_ENABLED=false
+if [ "orange" = "`get_property ro.boot.verifiedbootstate`" -a \
+     "2" = "`get_property partition.system.verified`" ]; then
+  VERITY_WAS_ENABLED=true
+fi
 
 echo "${GREEN}[ RUN      ]${NORMAL} Testing kernel support for overlayfs" >&2
 
 overlayfs_supported=true;
 adb_wait || die "wait for device failed"
-adb_sh ls -d /sys/module/overlay </dev/null >/dev/null &&
+adb_sh ls -d /sys/module/overlay </dev/null >/dev/null 2>/dev/null ||
+  adb_sh grep "nodev${TAB}overlay" /proc/filesystems </dev/null >/dev/null 2>/dev/null &&
   echo "${GREEN}[       OK ]${NORMAL} overlay module present" >&2 ||
   (
     echo "${ORANGE}[  WARNING ]${NORMAL} overlay module not present" >&2 &&
@@ -391,9 +484,9 @@
   echo "${ORANGE}[  WARNING ]${NORMAL} rebooting before test" >&2
   adb_reboot &&
     adb_wait 2m ||
-    die "lost device after reboot after wipe"
+    die "lost device after reboot after wipe (USB stack broken?)"
   adb_root ||
-    die "lost device after elevation to root after wipe"
+    die "lost device after elevation to root after wipe (USB stack broken?)"
 fi
 D=`adb_sh df -k </dev/null` &&
   H=`echo "${D}" | head -1` &&
@@ -455,9 +548,9 @@
   L=`adb_logcat -b all -v nsec -t ${T} 2>&1`
   adb_reboot &&
     adb_wait 2m ||
-    die "lost device after reboot requested"
+    die "lost device after reboot requested (USB stack broken?)"
   adb_root ||
-    die "lost device after elevation to root"
+    die "lost device after elevation to root (USB stack broken?)"
   rebooted=true
   # re-disable verity to see the setup remarks expected
   T=`adb_date`
@@ -544,7 +637,7 @@
     echo "${D}" | grep "^overlay .* /system\$" >/dev/null ||
     die  "overlay takeover after remount"
   !(adb_sh grep "^overlay " /proc/mounts </dev/null |
-    grep -v "^overlay /\(vendor\|system\)/..* overlay ro," |
+    grep -v "^overlay /\(vendor\|system\|bionic\)/..* overlay ro," |
     grep " overlay ro,") &&
     !(adb_sh grep " rw," /proc/mounts </dev/null |
       skip_administrative_mounts data) ||
@@ -555,7 +648,7 @@
   fi
 fi
 
-# Check something
+# Check something.
 
 echo "${GREEN}[ RUN      ]${NORMAL} push content to /system and /vendor" >&2
 
@@ -569,17 +662,22 @@
   die "vendor hello"
 check_eq "${A}" "${B}" /vendor before reboot
 
-# download libc.so, append some gargage, push back, and check if the file is updated.
+# Download libc.so, append some gargage, push back, and check if the file
+# is updated.
 tempdir="`mktemp -d`"
 cleanup() {
   rm -rf ${tempdir}
 }
-adb pull /system/lib/bootstrap/libc.so ${tempdir} || die "pull libc.so from device"
+adb pull /system/lib/bootstrap/libc.so ${tempdir} >/dev/null ||
+  die "pull libc.so from device"
 garbage="`hexdump -n 16 -e '4/4 "%08X" 1 "\n"' /dev/random`"
 echo ${garbage} >> ${tempdir}/libc.so
-adb push ${tempdir}/libc.so /system/lib/bootstrap/libc.so || die "push libc.so to device"
-adb pull /system/lib/bootstrap/libc.so ${tempdir}/libc.so.fromdevice || die "pull libc.so from device"
-diff ${tempdir}/libc.so ${tempdir}/libc.so.fromdevice > /dev/null || die "libc.so differ"
+adb push ${tempdir}/libc.so /system/lib/bootstrap/libc.so >/dev/null ||
+  die "push libc.so to device"
+adb pull /system/lib/bootstrap/libc.so ${tempdir}/libc.so.fromdevice >/dev/null ||
+  die "pull libc.so from device"
+diff ${tempdir}/libc.so ${tempdir}/libc.so.fromdevice > /dev/null ||
+  die "libc.so differ"
 
 echo "${GREEN}[ RUN      ]${NORMAL} reboot to confirm content persistent" >&2
 
@@ -605,7 +703,7 @@
   die "re-read /system/hello after reboot"
 check_eq "${A}" "${B}" /system after reboot
 echo "${GREEN}[       OK ]${NORMAL} /system content remains after reboot" >&2
-# Only root can read vendor if sepolicy permissions are as expected
+# Only root can read vendor if sepolicy permissions are as expected.
 if ${enforcing}; then
   adb_unroot
   B="`adb_cat /vendor/hello`" &&
@@ -619,9 +717,9 @@
 check_eq "${A}" "${B}" vendor after reboot
 echo "${GREEN}[       OK ]${NORMAL} /vendor content remains after reboot" >&2
 
-# check if the updated libc.so is persistent after reboot
+# Check if the updated libc.so is persistent after reboot.
 adb_root &&
-  adb pull /system/lib/bootstrap/libc.so ${tempdir}/libc.so.fromdevice ||
+  adb pull /system/lib/bootstrap/libc.so ${tempdir}/libc.so.fromdevice >/dev/null ||
   die "pull libc.so from device"
 diff ${tempdir}/libc.so ${tempdir}/libc.so.fromdevice > /dev/null || die "libc.so differ"
 rm -r ${tempdir}
@@ -677,7 +775,7 @@
   fi
   fastboot reboot ||
     die "can not reboot out of fastboot"
-  echo "${ORANGE}[  WARNING ]${NORMAL} adb after fastboot ... waiting 2 minutes"
+  echo "${ORANGE}[  WARNING ]${NORMAL} adb after fastboot"
   adb_wait 2m ||
     die "did not reboot after flash"
   if ${overlayfs_needed}; then
@@ -719,9 +817,26 @@
 echo "${GREEN}[ RUN      ]${NORMAL} remove test content (cleanup)" >&2
 
 T=`adb_date`
-adb remount &&
+H=`adb remount 2>&1`
+err=${?}
+L=
+D="${H%?Now reboot your device for settings to take effect}"
+if [ X"${H}" != X"${D}" ]; then
+  echo "${ORANGE}[  WARNING ]${NORMAL} adb remount requires a reboot after partial flash (legacy avb)"
+  L=`adb_logcat -b all -v nsec -t ${T} 2>&1`
+  adb_reboot &&
+    adb_wait 2m &&
+    adb_root ||
+    die "failed to reboot"
+  T=`adb_date`
+  H=`adb remount 2>&1`
+  err=${?}
+fi
+echo "${H}"
+[ ${err} = 0 ] &&
   ( adb_sh rm /vendor/hello </dev/null 2>/dev/null || true ) &&
   adb_sh rm /system/hello </dev/null ||
+  ( [ -n "${L}" ] && echo "${L}" && false ) ||
   die -t ${T} "cleanup hello"
 B="`adb_cat /system/hello`" &&
   die "re-read /system/hello after rm"
@@ -768,12 +883,12 @@
     die -t ${T} "setup for overlayfs"
 fi
 
-echo "${GREEN}[ RUN      ]${NORMAL} test raw remount command" >&2
+echo "${GREEN}[ RUN      ]${NORMAL} test raw remount commands" >&2
 
-# prerequisite is a prepped device from above
+# Prerequisite is a prepped device from above.
 adb_reboot &&
   adb_wait 2m ||
-  die "lost device after reboot to ro state"
+  die "lost device after reboot to ro state (USB stack broken?)"
 adb_sh grep " /vendor .* rw," /proc/mounts >/dev/null &&
   die "/vendor is not read-only"
 adb_su mount -o rw,remount /vendor ||
@@ -782,4 +897,12 @@
   die "/vendor is not read-write"
 echo "${GREEN}[       OK ]${NORMAL} mount -o rw,remount command works" >&2
 
+if $VERITY_WAS_ENABLED && $overlayfs_supported; then
+  adb_root &&
+    adb enable-verity &&
+    adb_reboot &&
+    adb_wait 2m ||
+    die "failed to restore verity" >&2
+fi
+
 echo "${GREEN}[  PASSED  ]${NORMAL} adb remount" >&2
diff --git a/init/README.md b/init/README.md
index 3a7c71c..f0e5d55 100644
--- a/init/README.md
+++ b/init/README.md
@@ -161,11 +161,13 @@
 Options are modifiers to services.  They affect how and when init
 runs the service.
 
-`capabilities <capability> [ <capability>\* ]`
+`capabilities [ <capability>\* ]`
 > Set capabilities when exec'ing this service. 'capability' should be a Linux
   capability without the "CAP\_" prefix, like "NET\_ADMIN" or "SETPCAP". See
   http://man7.org/linux/man-pages/man7/capabilities.7.html for a list of Linux
   capabilities.
+  If no capabilities are provided, then all capabilities are removed from this service, even if it
+  runs as root.
 
 `class <name> [ <name>\* ]`
 > Specify class names for the service.  All services in a
diff --git a/init/builtins.cpp b/init/builtins.cpp
index c8ceb0c..538ed00 100644
--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -75,6 +75,7 @@
 
 using namespace std::literals::string_literals;
 
+using android::base::Basename;
 using android::base::unique_fd;
 using android::fs_mgr::Fstab;
 using android::fs_mgr::ReadFstabFromFile;
@@ -749,11 +750,27 @@
 }
 
 static Result<Success> do_verity_update_state(const BuiltinArguments& args) {
-    if (!fs_mgr_update_verity_state([](const std::string& mount_point, int mode) {
-            property_set("partition." + mount_point + ".verified", std::to_string(mode));
-        })) {
-        return Error() << "fs_mgr_update_verity_state() failed";
+    int mode;
+    if (!fs_mgr_load_verity_state(&mode)) {
+        return Error() << "fs_mgr_load_verity_state() failed";
     }
+
+    Fstab fstab;
+    if (!ReadDefaultFstab(&fstab)) {
+        return Error() << "Failed to read default fstab";
+    }
+
+    for (const auto& entry : fstab) {
+        if (!fs_mgr_is_verity_enabled(entry)) {
+            continue;
+        }
+
+        // To be consistent in vboot 1.0 and vboot 2.0 (AVB), use "system" for the partition even
+        // for system as root, so it has property [partition.system.verified].
+        std::string partition = entry.mount_point == "/" ? "system" : Basename(entry.mount_point);
+        property_set("partition." + partition + ".verified", std::to_string(mode));
+    }
+
     return Success();
 }
 
diff --git a/init/first_stage_mount.cpp b/init/first_stage_mount.cpp
index 7d5bf57..1b077bc 100644
--- a/init/first_stage_mount.cpp
+++ b/init/first_stage_mount.cpp
@@ -157,6 +157,37 @@
     return fstab;
 }
 
+static bool GetRootEntry(FstabEntry* root_entry) {
+    Fstab proc_mounts;
+    if (!ReadFstabFromFile("/proc/mounts", &proc_mounts)) {
+        LOG(ERROR) << "Could not read /proc/mounts and /system not in fstab, /system will not be "
+                      "available for overlayfs";
+        return false;
+    }
+
+    auto entry = std::find_if(proc_mounts.begin(), proc_mounts.end(), [](const auto& entry) {
+        return entry.mount_point == "/" && entry.fs_type != "rootfs";
+    });
+
+    if (entry == proc_mounts.end()) {
+        LOG(ERROR) << "Could not get mount point for '/' in /proc/mounts, /system will not be "
+                      "available for overlayfs";
+        return false;
+    }
+
+    *root_entry = std::move(*entry);
+
+    // We don't know if we're avb or not, so we query device mapper as if we are avb.  If we get a
+    // success, then mark as avb, otherwise default to verify.
+    auto& dm = android::dm::DeviceMapper::Instance();
+    if (dm.GetState("vroot") != android::dm::DmDeviceState::INVALID) {
+        root_entry->fs_mgr_flags.avb = true;
+    } else {
+        root_entry->fs_mgr_flags.verify = true;
+    }
+    return true;
+}
+
 // Class Definitions
 // -----------------
 FirstStageMount::FirstStageMount(Fstab fstab)
@@ -443,7 +474,7 @@
 
     if (system_partition == fstab_.end()) return true;
 
-    if (MountPartition(system_partition, true /* erase_used_fstab_entry */)) {
+    if (MountPartition(system_partition, false)) {
         SwitchRoot("/system");
     } else {
         PLOG(ERROR) << "Failed to mount /system";
@@ -487,6 +518,12 @@
     if (!TrySkipMountingPartitions()) return false;
 
     for (auto current = fstab_.begin(); current != fstab_.end();) {
+        // We've already mounted /system above.
+        if (current->mount_point == "/system") {
+            ++current;
+            continue;
+        }
+
         Fstab::iterator end;
         if (!MountPartition(current, false, &end)) {
             if (current->fs_mgr_flags.no_fail) {
@@ -503,6 +540,15 @@
         current = end;
     }
 
+    // If we don't see /system or / in the fstab, then we need to create an root entry for
+    // overlayfs.
+    if (!GetEntryForMountPoint(&fstab_, "/system") && !GetEntryForMountPoint(&fstab_, "/")) {
+        FstabEntry root_entry;
+        if (GetRootEntry(&root_entry)) {
+            fstab_.emplace_back(std::move(root_entry));
+        }
+    }
+
     // heads up for instantiating required device(s) for overlayfs logic
     const auto devices = fs_mgr_overlayfs_required_devices(&fstab_);
     for (auto const& device : devices) {
diff --git a/init/init.cpp b/init/init.cpp
index 5a3cc15..a8924f2 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -192,7 +192,8 @@
 
     if (waiting_for_prop) {
         if (wait_prop_name == name && wait_prop_value == value) {
-            LOG(INFO) << "Wait for property took " << *waiting_for_prop;
+            LOG(INFO) << "Wait for property '" << wait_prop_name << "=" << wait_prop_value
+                      << "' took " << *waiting_for_prop;
             ResetWaitForProp();
         }
     }
diff --git a/init/property_service.cpp b/init/property_service.cpp
index 91b7ddd..46e5e12 100644
--- a/init/property_service.cpp
+++ b/init/property_service.cpp
@@ -65,6 +65,7 @@
 
 using namespace std::literals;
 
+using android::base::GetProperty;
 using android::base::ReadFileToString;
 using android::base::Split;
 using android::base::StartsWith;
@@ -728,6 +729,110 @@
     property_set("ro.persistent_properties.ready", "true");
 }
 
+// If the ro.product.[brand|device|manufacturer|model|name] properties have not been explicitly
+// set, derive them from ro.product.${partition}.* properties
+static void property_initialize_ro_product_props() {
+    const char* RO_PRODUCT_PROPS_PREFIX = "ro.product.";
+    const char* RO_PRODUCT_PROPS[] = {
+            "brand", "device", "manufacturer", "model", "name",
+    };
+    const char* RO_PRODUCT_PROPS_ALLOWED_SOURCES[] = {
+            "odm", "product", "product_services", "system", "vendor",
+    };
+    const char* RO_PRODUCT_PROPS_DEFAULT_SOURCE_ORDER =
+            "product,product_services,odm,vendor,system";
+    const std::string EMPTY = "";
+
+    std::string ro_product_props_source_order =
+            GetProperty("ro.product.property_source_order", EMPTY);
+
+    if (!ro_product_props_source_order.empty()) {
+        // Verify that all specified sources are valid
+        for (const auto& source : Split(ro_product_props_source_order, ",")) {
+            // Verify that the specified source is valid
+            bool is_allowed_source = false;
+            for (const auto& allowed_source : RO_PRODUCT_PROPS_ALLOWED_SOURCES) {
+                if (source == allowed_source) {
+                    is_allowed_source = true;
+                    break;
+                }
+            }
+            if (!is_allowed_source) {
+                LOG(ERROR) << "Found unexpected source in ro.product.property_source_order; "
+                              "using the default property source order";
+                ro_product_props_source_order = RO_PRODUCT_PROPS_DEFAULT_SOURCE_ORDER;
+                break;
+            }
+        }
+    } else {
+        ro_product_props_source_order = RO_PRODUCT_PROPS_DEFAULT_SOURCE_ORDER;
+    }
+
+    for (const auto& ro_product_prop : RO_PRODUCT_PROPS) {
+        std::string base_prop(RO_PRODUCT_PROPS_PREFIX);
+        base_prop += ro_product_prop;
+
+        std::string base_prop_val = GetProperty(base_prop, EMPTY);
+        if (!base_prop_val.empty()) {
+            continue;
+        }
+
+        for (const auto& source : Split(ro_product_props_source_order, ",")) {
+            std::string target_prop(RO_PRODUCT_PROPS_PREFIX);
+            target_prop += source;
+            target_prop += '.';
+            target_prop += ro_product_prop;
+
+            std::string target_prop_val = GetProperty(target_prop, EMPTY);
+            if (!target_prop_val.empty()) {
+                LOG(INFO) << "Setting product property " << base_prop << " to '" << target_prop_val
+                          << "' (from " << target_prop << ")";
+                std::string error;
+                uint32_t res = PropertySet(base_prop, target_prop_val, &error);
+                if (res != PROP_SUCCESS) {
+                    LOG(ERROR) << "Error setting product property " << base_prop << ": err=" << res
+                               << " (" << error << ")";
+                }
+                break;
+            }
+        }
+    }
+}
+
+// If the ro.build.fingerprint property has not been set, derive it from constituent pieces
+static void property_derive_build_fingerprint() {
+    std::string build_fingerprint = GetProperty("ro.build.fingerprint", "");
+    if (!build_fingerprint.empty()) {
+        return;
+    }
+
+    const std::string UNKNOWN = "unknown";
+    build_fingerprint = GetProperty("ro.product.brand", UNKNOWN);
+    build_fingerprint += '/';
+    build_fingerprint += GetProperty("ro.product.name", UNKNOWN);
+    build_fingerprint += '/';
+    build_fingerprint += GetProperty("ro.product.device", UNKNOWN);
+    build_fingerprint += ':';
+    build_fingerprint += GetProperty("ro.build.version.release", UNKNOWN);
+    build_fingerprint += '/';
+    build_fingerprint += GetProperty("ro.build.id", UNKNOWN);
+    build_fingerprint += '/';
+    build_fingerprint += GetProperty("ro.build.version.incremental", UNKNOWN);
+    build_fingerprint += ':';
+    build_fingerprint += GetProperty("ro.build.type", UNKNOWN);
+    build_fingerprint += '/';
+    build_fingerprint += GetProperty("ro.build.tags", UNKNOWN);
+
+    LOG(INFO) << "Setting property 'ro.build.fingerprint' to '" << build_fingerprint << "'";
+
+    std::string error;
+    uint32_t res = PropertySet("ro.build.fingerprint", build_fingerprint, &error);
+    if (res != PROP_SUCCESS) {
+        LOG(ERROR) << "Error setting property 'ro.build.fingerprint': err=" << res << " (" << error
+                   << ")";
+    }
+}
+
 void property_load_boot_defaults() {
     // TODO(b/117892318): merge prop.default and build.prop files into one
     // TODO(b/122864654): read the prop files from all partitions and then
@@ -749,6 +854,9 @@
     load_properties_from_file("/vendor/build.prop", NULL);
     load_properties_from_file("/factory/factory.prop", "ro.*");
 
+    property_initialize_ro_product_props();
+    property_derive_build_fingerprint();
+
     update_sys_usb_config();
 }
 
diff --git a/init/service.cpp b/init/service.cpp
index d64f2f3..2186a85 100644
--- a/init/service.cpp
+++ b/init/service.cpp
@@ -218,12 +218,12 @@
 
 Service::Service(const std::string& name, Subcontext* subcontext_for_restart_commands,
                  const std::vector<std::string>& args)
-    : Service(name, 0, 0, 0, {}, 0, 0, "", subcontext_for_restart_commands, args) {}
+    : Service(name, 0, 0, 0, {}, 0, "", subcontext_for_restart_commands, args) {}
 
 Service::Service(const std::string& name, unsigned flags, uid_t uid, gid_t gid,
-                 const std::vector<gid_t>& supp_gids, const CapSet& capabilities,
-                 unsigned namespace_flags, const std::string& seclabel,
-                 Subcontext* subcontext_for_restart_commands, const std::vector<std::string>& args)
+                 const std::vector<gid_t>& supp_gids, unsigned namespace_flags,
+                 const std::string& seclabel, Subcontext* subcontext_for_restart_commands,
+                 const std::vector<std::string>& args)
     : name_(name),
       classnames_({"default"}),
       flags_(flags),
@@ -232,7 +232,6 @@
       uid_(uid),
       gid_(gid),
       supp_gids_(supp_gids),
-      capabilities_(capabilities),
       namespace_flags_(namespace_flags),
       seclabel_(seclabel),
       onrestart_(false, subcontext_for_restart_commands, "<Service '" + name + "' onrestart>", 0,
@@ -289,7 +288,7 @@
         }
     }
     // Keep capabilites on uid change.
-    if (capabilities_.any() && uid_) {
+    if (capabilities_ && uid_) {
         // If Android is running in a container, some securebits might already
         // be locked, so don't change those.
         unsigned long securebits = prctl(PR_GET_SECUREBITS);
@@ -328,8 +327,8 @@
             PLOG(FATAL) << "setpriority failed for " << name_;
         }
     }
-    if (capabilities_.any()) {
-        if (!SetCapsForExec(capabilities_)) {
+    if (capabilities_) {
+        if (!SetCapsForExec(*capabilities_)) {
             LOG(FATAL) << "cannot set capabilities for " << name_;
         }
     } else if (uid_) {
@@ -420,7 +419,7 @@
     }
 
     unsigned int last_valid_cap = GetLastValidCap();
-    if (last_valid_cap >= capabilities_.size()) {
+    if (last_valid_cap >= capabilities_->size()) {
         LOG(WARNING) << "last valid run-time capability is larger than CAP_LAST_CAP";
     }
 
@@ -435,7 +434,7 @@
             return Error() << StringPrintf("capability '%s' not supported by the kernel",
                                            arg.c_str());
         }
-        capabilities_[cap] = true;
+        (*capabilities_)[cap] = true;
     }
     return Success();
 }
@@ -796,7 +795,7 @@
     // clang-format off
     static const Map option_parsers = {
         {"capabilities",
-                        {1,     kMax, &Service::ParseCapabilities}},
+                        {0,     kMax, &Service::ParseCapabilities}},
         {"class",       {1,     kMax, &Service::ParseClass}},
         {"console",     {0,     1,    &Service::ParseConsole}},
         {"critical",    {0,     0,    &Service::ParseCritical}},
@@ -1268,7 +1267,6 @@
     std::string name = "exec " + std::to_string(exec_count) + " (" + Join(str_args, " ") + ")";
 
     unsigned flags = SVC_ONESHOT | SVC_TEMPORARY;
-    CapSet no_capabilities;
     unsigned namespace_flags = 0;
 
     std::string seclabel = "";
@@ -1303,8 +1301,8 @@
         }
     }
 
-    return std::make_unique<Service>(name, flags, *uid, *gid, supp_gids, no_capabilities,
-                                     namespace_flags, seclabel, nullptr, str_args);
+    return std::make_unique<Service>(name, flags, *uid, *gid, supp_gids, namespace_flags, seclabel,
+                                     nullptr, str_args);
 }
 
 // Shutdown services in the opposite order that they were started.
diff --git a/init/service.h b/init/service.h
index c29723a..c42a5a3 100644
--- a/init/service.h
+++ b/init/service.h
@@ -68,9 +68,9 @@
             const std::vector<std::string>& args);
 
     Service(const std::string& name, unsigned flags, uid_t uid, gid_t gid,
-            const std::vector<gid_t>& supp_gids, const CapSet& capabilities,
-            unsigned namespace_flags, const std::string& seclabel,
-            Subcontext* subcontext_for_restart_commands, const std::vector<std::string>& args);
+            const std::vector<gid_t>& supp_gids, unsigned namespace_flags,
+            const std::string& seclabel, Subcontext* subcontext_for_restart_commands,
+            const std::vector<std::string>& args);
 
     static std::unique_ptr<Service> MakeTemporaryOneshotService(const std::vector<std::string>& args);
 
@@ -192,7 +192,7 @@
     uid_t uid_;
     gid_t gid_;
     std::vector<gid_t> supp_gids_;
-    CapSet capabilities_;
+    std::optional<CapSet> capabilities_;
     unsigned namespace_flags_;
     // Pair of namespace type, path to namespace.
     std::vector<std::pair<int, std::string>> namespaces_to_enter_;
diff --git a/init/service_test.cpp b/init/service_test.cpp
index 194aa2b..4bfaa6b 100644
--- a/init/service_test.cpp
+++ b/init/service_test.cpp
@@ -57,7 +57,7 @@
     }
 
     Service* service_in_old_memory2 = new (old_memory) Service(
-        "test_old_memory", 0U, 0U, 0U, std::vector<gid_t>(), CapSet(), 0U, "", nullptr, dummy_args);
+            "test_old_memory", 0U, 0U, 0U, std::vector<gid_t>(), 0U, "", nullptr, dummy_args);
 
     EXPECT_EQ(0U, service_in_old_memory2->flags());
     EXPECT_EQ(0, service_in_old_memory2->pid());
diff --git a/libcutils/Android.bp b/libcutils/Android.bp
index 0dbbc3f..b4b8cd1 100644
--- a/libcutils/Android.bp
+++ b/libcutils/Android.bp
@@ -60,7 +60,6 @@
     host_supported: true,
     srcs: [
         "config_utils.cpp",
-        "fs_config.cpp",
         "canned_fs_config.cpp",
         "iosched_policy.cpp",
         "load_file.cpp",
@@ -80,6 +79,7 @@
         not_windows: {
             srcs: libcutils_nonwindows_sources + [
                 "ashmem-host.cpp",
+                "fs_config.cpp",
                 "trace-host.cpp",
             ],
         },
@@ -104,6 +104,7 @@
             srcs: libcutils_nonwindows_sources + [
                 "android_reboot.cpp",
                 "ashmem-dev.cpp",
+                "fs_config.cpp",
                 "klog.cpp",
                 "partition_utils.cpp",
                 "properties.cpp",
@@ -172,7 +173,10 @@
         }
     },
 
-    shared_libs: ["liblog"],
+    shared_libs: [
+        "liblog",
+        "libbase",
+    ],
     header_libs: [
         "libbase_headers",
         "libcutils_headers",
@@ -192,4 +196,71 @@
     ],
 }
 
-subdirs = ["tests"]
+cc_defaults {
+    name: "libcutils_test_default",
+    srcs: ["sockets_test.cpp"],
+
+    target: {
+        android: {
+            srcs: [
+                "android_get_control_file_test.cpp",
+                "android_get_control_socket_test.cpp",
+                "ashmem_test.cpp",
+                "fs_config_test.cpp",
+                "memset_test.cpp",
+                "multiuser_test.cpp",
+                "properties_test.cpp",
+                "sched_policy_test.cpp",
+                "str_parms_test.cpp",
+                "trace-dev_test.cpp",
+            ],
+        },
+
+        not_windows: {
+            srcs: [
+                "str_parms_test.cpp",
+            ],
+        },
+    },
+
+    cflags: [
+        "-Wall",
+        "-Wextra",
+        "-Werror",
+    ],
+}
+
+test_libraries = [
+    "libcutils",
+    "liblog",
+    "libbase",
+    "libjsoncpp",
+    "libprocessgroup",
+]
+
+cc_test {
+    name: "libcutils_test",
+    test_suites: ["device-tests"],
+    defaults: ["libcutils_test_default"],
+    host_supported: true,
+    shared_libs: test_libraries,
+}
+
+cc_test {
+    name: "libcutils_test_static",
+    test_suites: ["device-tests"],
+    defaults: ["libcutils_test_default"],
+    static_libs: ["libc"] + test_libraries,
+    stl: "libc++_static",
+
+    target: {
+        android: {
+            static_executable: true,
+        },
+        windows: {
+            host_ldlibs: ["-lws2_32"],
+
+            enabled: true,
+        },
+    },
+}
diff --git a/libcutils/tests/android_get_control_file_test.cpp b/libcutils/android_get_control_file_test.cpp
similarity index 100%
rename from libcutils/tests/android_get_control_file_test.cpp
rename to libcutils/android_get_control_file_test.cpp
diff --git a/libcutils/tests/android_get_control_socket_test.cpp b/libcutils/android_get_control_socket_test.cpp
similarity index 100%
rename from libcutils/tests/android_get_control_socket_test.cpp
rename to libcutils/android_get_control_socket_test.cpp
diff --git a/libcutils/ashmem-dev.cpp b/libcutils/ashmem-dev.cpp
index f65dc8b..e35b91a 100644
--- a/libcutils/ashmem-dev.cpp
+++ b/libcutils/ashmem-dev.cpp
@@ -29,17 +29,34 @@
 #include <errno.h>
 #include <fcntl.h>
 #include <linux/ashmem.h>
+#include <linux/memfd.h>
+#include <log/log.h>
 #include <pthread.h>
+#include <stdio.h>
 #include <string.h>
 #include <sys/ioctl.h>
+#include <sys/mman.h>
 #include <sys/stat.h>
+#include <sys/syscall.h>
 #include <sys/sysmacros.h>
 #include <sys/types.h>
 #include <unistd.h>
-#include <log/log.h>
+
+#include <android-base/properties.h>
+#include <android-base/unique_fd.h>
 
 #define ASHMEM_DEVICE "/dev/ashmem"
 
+/* Will be added to UAPI once upstream change is merged */
+#define F_SEAL_FUTURE_WRITE 0x0010
+
+/*
+ * The minimum vendor API level at and after which it is safe to use memfd.
+ * This is to facilitate deprecation of ashmem.
+ */
+#define MIN_MEMFD_VENDOR_API_LEVEL 29
+#define MIN_MEMFD_VENDOR_API_LEVEL_CHAR 'Q'
+
 /* ashmem identity */
 static dev_t __ashmem_rdev;
 /*
@@ -72,6 +89,130 @@
 }
 #endif
 
+/*
+ * has_memfd_support() determines if the device can use memfd. memfd support
+ * has been there for long time, but certain things in it may be missing.  We
+ * check for needed support in it. Also we check if the VNDK version of
+ * libcutils being used is new enough, if its not, then we cannot use memfd
+ * since the older copies may be using ashmem so we just use ashmem. Once all
+ * Android devices that are getting updates are new enough (ex, they were
+ * originally shipped with Android release > P), then we can just use memfd and
+ * delete all ashmem code from libcutils (while preserving the interface).
+ *
+ * NOTE:
+ * The sys.use_memfd property is set by default to false in Android
+ * to temporarily disable memfd, till vendor and apps are ready for it.
+ * The main issue: either apps or vendor processes can directly make ashmem
+ * IOCTLs on FDs they receive by assuming they are ashmem, without going
+ * through libcutils. Such fds could have very well be originally created with
+ * libcutils hence they could be memfd. Thus the IOCTLs will break.
+ *
+ * Set default value of sys.use_memfd property to true once the issue is
+ * resolved, so that the code can then self-detect if kernel support is present
+ * on the device. The property can also set to true from adb shell, for
+ * debugging.
+ */
+
+static bool debug_log = false;            /* set to true for verbose logging and other debug  */
+static bool pin_deprecation_warn = true; /* Log the pin deprecation warning only once */
+
+/* Determine if vendor processes would be ok with memfd in the system:
+ *
+ * If VNDK is using older libcutils, don't use memfd. This is so that the
+ * same shared memory mechanism is used across binder transactions between
+ * vendor partition processes and system partition processes.
+ */
+static bool check_vendor_memfd_allowed() {
+    std::string vndk_version = android::base::GetProperty("ro.vndk.version", "");
+
+    if (vndk_version == "") {
+        ALOGE("memfd: ro.vndk.version not defined or invalid (%s), this is mandated since P.\n",
+              vndk_version.c_str());
+        return false;
+    }
+
+    /* No issues if vendor is targetting current Dessert */
+    if (vndk_version == "current") {
+        return false;
+    }
+
+    /* Check if VNDK version is a number and act on it */
+    char* p;
+    long int vers = strtol(vndk_version.c_str(), &p, 10);
+    if (*p == 0) {
+        if (vers < MIN_MEMFD_VENDOR_API_LEVEL) {
+            ALOGI("memfd: device VNDK version (%s) is < Q so using ashmem.\n",
+                  vndk_version.c_str());
+            return false;
+        }
+
+        return true;
+    }
+
+    /* If its not a number, assume string, but check if its a sane string */
+    if (tolower(vndk_version[0]) < 'a' || tolower(vndk_version[0]) > 'z') {
+        ALOGE("memfd: ro.vndk.version not defined or invalid (%s), this is mandated since P.\n",
+              vndk_version.c_str());
+        return false;
+    }
+
+    if (tolower(vndk_version[0]) < tolower(MIN_MEMFD_VENDOR_API_LEVEL_CHAR)) {
+        ALOGI("memfd: device is using VNDK version (%s) which is less than Q. Use ashmem only.\n",
+              vndk_version.c_str());
+        return false;
+    }
+
+    return true;
+}
+
+
+/* Determine if memfd can be supported. This is just one-time hardwork
+ * which will be cached by the caller.
+ */
+static bool __has_memfd_support() {
+    if (check_vendor_memfd_allowed() == false) {
+        return false;
+    }
+
+    /* Used to turn on/off the detection at runtime, in the future this
+     * property will be removed once we switch everything over to ashmem.
+     * Currently it is used only for debugging to switch the system over.
+     */
+    if (!android::base::GetBoolProperty("sys.use_memfd", false)) {
+        if (debug_log) {
+            ALOGD("sys.use_memfd=false so memfd disabled\n");
+        }
+        return false;
+    }
+
+    /* Check if kernel support exists, otherwise fall back to ashmem */
+    android::base::unique_fd fd(
+            syscall(__NR_memfd_create, "test_android_memfd", MFD_ALLOW_SEALING));
+    if (fd == -1) {
+        ALOGE("memfd_create failed: %s, no memfd support.\n", strerror(errno));
+        return false;
+    }
+
+    if (fcntl(fd, F_ADD_SEALS, F_SEAL_FUTURE_WRITE) == -1) {
+        ALOGE("fcntl(F_ADD_SEALS) failed: %s, no memfd support.\n", strerror(errno));
+        return false;
+    }
+
+    if (debug_log) {
+        ALOGD("memfd: device has memfd support, using it\n");
+    }
+    return true;
+}
+
+static bool has_memfd_support() {
+    /* memfd_supported is the initial global per-process state of what is known
+     * about memfd.
+     */
+    static bool memfd_supported = __has_memfd_support();
+
+    return memfd_supported;
+}
+
 /* logistics of getting file descriptor for ashmem */
 static int __ashmem_open_locked()
 {
@@ -177,11 +318,49 @@
     return result;
 }
 
+static bool memfd_is_ashmem(int fd) {
+    static bool fd_check_error_once = false;
+
+    if (__ashmem_is_ashmem(fd, 0) == 0) {
+        if (!fd_check_error_once) {
+            ALOGE("memfd: memfd expected but ashmem fd used - please use libcutils.\n");
+            fd_check_error_once = true;
+        }
+
+        return true;
+    }
+
+    return false;
+}
+
 int ashmem_valid(int fd)
 {
+    if (has_memfd_support() && !memfd_is_ashmem(fd)) {
+        return 1;
+    }
+
     return __ashmem_is_ashmem(fd, 0) >= 0;
 }
 
+static int memfd_create_region(const char* name, size_t size) {
+    android::base::unique_fd fd(syscall(__NR_memfd_create, name, MFD_ALLOW_SEALING));
+
+    if (fd == -1) {
+        ALOGE("memfd_create(%s, %zd) failed: %s\n", name, size, strerror(errno));
+        return -1;
+    }
+
+    if (ftruncate(fd, size) == -1) {
+        ALOGE("ftruncate(%s, %zd) failed for memfd creation: %s\n", name, size, strerror(errno));
+        return -1;
+    }
+
+    if (debug_log) {
+        ALOGE("memfd_create(%s, %zd) success. fd=%d\n", name, size, fd.get());
+    }
+    return fd.release();
+}
+
 /*
  * ashmem_create_region - creates a new ashmem region and returns the file
  * descriptor, or <0 on error
@@ -193,6 +372,10 @@
 {
     int ret, save_errno;
 
+    if (has_memfd_support()) {
+        return memfd_create_region(name ? name : "none", size);
+    }
+
     int fd = __ashmem_open();
     if (fd < 0) {
         return fd;
@@ -222,28 +405,78 @@
     return ret;
 }
 
+static int memfd_set_prot_region(int fd, int prot) {
+    /* Only proceed if an fd needs to be write-protected */
+    if (prot & PROT_WRITE) {
+        return 0;
+    }
+
+    if (fcntl(fd, F_ADD_SEALS, F_SEAL_FUTURE_WRITE) == -1) {
+        ALOGE("memfd_set_prot_region(%d, %d): F_SEAL_FUTURE_WRITE seal failed: %s\n", fd, prot,
+              strerror(errno));
+        return -1;
+    }
+
+    return 0;
+}
+
 int ashmem_set_prot_region(int fd, int prot)
 {
+    if (has_memfd_support() && !memfd_is_ashmem(fd)) {
+        return memfd_set_prot_region(fd, prot);
+    }
+
     return __ashmem_check_failure(fd, TEMP_FAILURE_RETRY(ioctl(fd, ASHMEM_SET_PROT_MASK, prot)));
 }
 
 int ashmem_pin_region(int fd, size_t offset, size_t len)
 {
+    if (!pin_deprecation_warn || debug_log) {
+        ALOGE("Pinning is deprecated since Android Q. Please use trim or other methods.\n");
+        pin_deprecation_warn = true;
+    }
+
+    if (has_memfd_support() && !memfd_is_ashmem(fd)) {
+        return 0;
+    }
+
     // TODO: should LP64 reject too-large offset/len?
     ashmem_pin pin = { static_cast<uint32_t>(offset), static_cast<uint32_t>(len) };
-
     return __ashmem_check_failure(fd, TEMP_FAILURE_RETRY(ioctl(fd, ASHMEM_PIN, &pin)));
 }
 
 int ashmem_unpin_region(int fd, size_t offset, size_t len)
 {
+    if (!pin_deprecation_warn || debug_log) {
+        ALOGE("Pinning is deprecated since Android Q. Please use trim or other methods.\n");
+        pin_deprecation_warn = true;
+    }
+
+    if (has_memfd_support() && !memfd_is_ashmem(fd)) {
+        return 0;
+    }
+
     // TODO: should LP64 reject too-large offset/len?
     ashmem_pin pin = { static_cast<uint32_t>(offset), static_cast<uint32_t>(len) };
-
     return __ashmem_check_failure(fd, TEMP_FAILURE_RETRY(ioctl(fd, ASHMEM_UNPIN, &pin)));
 }
 
 int ashmem_get_size_region(int fd)
 {
+    if (has_memfd_support() && !memfd_is_ashmem(fd)) {
+        struct stat sb;
+
+        if (fstat(fd, &sb) == -1) {
+            ALOGE("ashmem_get_size_region(%d): fstat failed: %s\n", fd, strerror(errno));
+            return -1;
+        }
+
+        if (debug_log) {
+            ALOGD("ashmem_get_size_region(%d): %d\n", fd, static_cast<int>(sb.st_size));
+        }
+
+        return sb.st_size;
+    }
+
     return __ashmem_check_failure(fd, TEMP_FAILURE_RETRY(ioctl(fd, ASHMEM_GET_SIZE, NULL)));
 }
diff --git a/libcutils/tests/AshmemTest.cpp b/libcutils/ashmem_test.cpp
similarity index 100%
rename from libcutils/tests/AshmemTest.cpp
rename to libcutils/ashmem_test.cpp
diff --git a/libcutils/fs_config.cpp b/libcutils/fs_config.cpp
index 59cbbc5..f1dcd50 100644
--- a/libcutils/fs_config.cpp
+++ b/libcutils/fs_config.cpp
@@ -24,6 +24,7 @@
 
 #include <errno.h>
 #include <fcntl.h>
+#include <fnmatch.h>
 #include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -31,6 +32,9 @@
 #include <sys/stat.h>
 #include <sys/types.h>
 
+#include <string>
+
+#include <android-base/strings.h>
 #include <log/log.h>
 #include <private/android_filesystem_config.h>
 #include <utils/Compat.h>
@@ -39,6 +43,9 @@
 #define O_BINARY 0
 #endif
 
+using android::base::EndsWith;
+using android::base::StartsWith;
+
 // My kingdom for <endian.h>
 static inline uint16_t get2LE(const uint8_t* src) {
     return src[0] | (src[1] << 8);
@@ -88,6 +95,7 @@
     { 00755, AID_ROOT,         AID_ROOT,         0, "system/etc/ppp" },
     { 00755, AID_ROOT,         AID_SHELL,        0, "system/vendor" },
     { 00751, AID_ROOT,         AID_SHELL,        0, "system/xbin" },
+    { 00755, AID_ROOT,         AID_SHELL,        0, "system/apex/*/bin" },
     { 00751, AID_ROOT,         AID_SHELL,        0, "vendor/bin" },
     { 00755, AID_ROOT,         AID_SHELL,        0, "vendor" },
     { 00755, AID_ROOT,         AID_ROOT,         0, 0 },
@@ -214,6 +222,7 @@
     { 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/apex/*/bin/*" },
     { 00755, AID_ROOT,      AID_SHELL,     0, "vendor/bin/*" },
     { 00755, AID_ROOT,      AID_SHELL,     0, "vendor/xbin/*" },
     { 00644, AID_ROOT,      AID_ROOT,      0, 0 },
@@ -253,46 +262,55 @@
 
 // if path is "odm/<stuff>", "oem/<stuff>", "product/<stuff>",
 // "product_services/<stuff>" or "vendor/<stuff>"
-static bool is_partition(const char* path, size_t len) {
+static bool is_partition(const std::string& path) {
     static const char* partitions[] = {"odm/", "oem/", "product/", "product_services/", "vendor/"};
     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;
+        if (StartsWith(path, partitions[i])) return true;
     }
     return false;
 }
 
-static inline bool prefix_cmp(bool partial, const char* prefix, size_t len, const char* path,
-                              size_t plen) {
-    return ((partial && plen >= len) || (plen == len)) && !strncmp(prefix, path, len);
-}
-
 // alias prefixes of "<partition>/<stuff>" to "system/<partition>/<stuff>" or
 // "system/<partition>/<stuff>" to "<partition>/<stuff>"
-static bool fs_config_cmp(bool partial, const char* prefix, size_t len, const char* path,
-                          size_t plen) {
-    // If name ends in * then allow partial matches.
-    if (!partial && prefix[len - 1] == '*') {
-        len--;
-        partial = true;
+static bool fs_config_cmp(bool dir, const char* prefix, size_t len, const char* path, size_t plen) {
+    std::string pattern(prefix, len);
+    std::string input(path, plen);
+
+    // Massage pattern and input so that they can be used by fnmatch where
+    // directories have to end with /.
+    if (dir) {
+        if (!EndsWith(input, "/")) {
+            input.append("/");
+        }
+
+        if (!EndsWith(pattern, "/*")) {
+            if (EndsWith(pattern, "/")) {
+                pattern.append("*");
+            } else {
+                pattern.append("/*");
+            }
+        }
     }
 
-    if (prefix_cmp(partial, prefix, len, path, plen)) return true;
+    // no FNM_PATHNAME is set in order to match a/b/c/d with a/*
+    // FNM_ESCAPE is set in order to prevent using \\? and \\* and maintenance issues.
+    const int fnm_flags = FNM_NOESCAPE;
+    if (fnmatch(pattern.c_str(), input.c_str(), fnm_flags) == 0) return true;
 
-    static const char system[] = "system/";
-    if (!strncmp(path, system, strlen(system))) {
-        path += strlen(system);
-        plen -= strlen(system);
-    } else if (len <= strlen(system)) {
+    static constexpr const char* kSystem = "system/";
+    if (StartsWith(input, kSystem)) {
+        input.erase(0, strlen(kSystem));
+    } else if (input.size() <= strlen(kSystem)) {
         return false;
-    } else if (strncmp(prefix, system, strlen(system))) {
-        return false;
+    } else if (StartsWith(pattern, kSystem)) {
+        pattern.erase(0, strlen(kSystem));
     } else {
-        prefix += strlen(system);
-        len -= strlen(system);
+        return false;
     }
-    return is_partition(prefix, len) && prefix_cmp(partial, prefix, len, path, plen);
+
+    if (!is_partition(pattern)) return false;
+    if (!is_partition(input)) return false;
+    return fnmatch(pattern.c_str(), input.c_str(), fnm_flags) == 0;
 }
 #ifndef __ANDROID_VNDK__
 auto __for_testing_only__fs_config_cmp = fs_config_cmp;
diff --git a/libcutils/tests/fs_config.cpp b/libcutils/fs_config_test.cpp
similarity index 91%
rename from libcutils/tests/fs_config.cpp
rename to libcutils/fs_config_test.cpp
index d5dc66a..c26315f 100644
--- a/libcutils/tests/fs_config.cpp
+++ b/libcutils/fs_config_test.cpp
@@ -42,11 +42,15 @@
     const char* path;
     bool match;
 } fs_config_cmp_tests[] = {
-    // clang-format off
+        // clang-format off
     { true,  "system/lib",             "system/lib/hw",           true  },
     { true,  "vendor/lib",             "system/vendor/lib/hw",    true  },
     { true,  "system/vendor/lib",      "vendor/lib/hw",           true  },
     { true,  "system/vendor/lib",      "system/vendor/lib/hw",    true  },
+    { true,  "foo/*/bar/*",            "foo/1/bar/2",             true  },
+    { true,  "foo/*/bar/*",            "foo/1/bar",               true  },
+    { true,  "foo/*/bar/*",            "foo/1/bar/2/3",           true  },
+    { true,  "foo/*/bar/*",            "foo/1/bar/2/3/",          true  },
     { false, "vendor/bin/wifi",        "system/vendor/bin/w",     false },
     { false, "vendor/bin/wifi",        "system/vendor/bin/wifi",  true  },
     { false, "vendor/bin/wifi",        "system/vendor/bin/wifi2", false },
@@ -58,8 +62,14 @@
     { false, "vendor/bin/*",           "system/vendor/bin/wifi",  true  },
     { false, "system/bin/*",           "system/bin",              false },
     { false, "system/vendor/bin/*",    "vendor/bin/wifi",         true  },
+    { false, "foo/*/bar/*",            "foo/1/bar/2",             true  },
+    { false, "foo/*/bar/*",            "foo/1/bar",               false },
+    { false, "foo/*/bar/*",            "foo/1/bar/2/3",           true  },
+    { false, "foo/*/bar/*.so",         "foo/1/bar/2/3",           false },
+    { false, "foo/*/bar/*.so",         "foo/1/bar/2.so",          true  },
+    { false, "foo/*/bar/*.so",         "foo/1/bar/2/3.so",        true  },
     { false, NULL,                     NULL,                      false },
-    // clang-format on
+        // clang-format on
 };
 
 static bool check_unique(std::vector<const char*>& paths, const std::string& config_name,
diff --git a/libcutils/tests/MemsetTest.cpp b/libcutils/memset_test.cpp
similarity index 100%
rename from libcutils/tests/MemsetTest.cpp
rename to libcutils/memset_test.cpp
diff --git a/libcutils/tests/multiuser_test.cpp b/libcutils/multiuser_test.cpp
similarity index 100%
rename from libcutils/tests/multiuser_test.cpp
rename to libcutils/multiuser_test.cpp
diff --git a/libcutils/tests/PropertiesTest.cpp b/libcutils/properties_test.cpp
similarity index 100%
rename from libcutils/tests/PropertiesTest.cpp
rename to libcutils/properties_test.cpp
diff --git a/libcutils/tests/sched_policy_test.cpp b/libcutils/sched_policy_test.cpp
similarity index 96%
rename from libcutils/tests/sched_policy_test.cpp
rename to libcutils/sched_policy_test.cpp
index 1f657e2..a321c90 100644
--- a/libcutils/tests/sched_policy_test.cpp
+++ b/libcutils/sched_policy_test.cpp
@@ -90,17 +90,18 @@
     // A measureable effect of scheduling policy is that the kernel has 800x
     // greater slack time in waking up a sleeping background thread.
     //
-    // Look for 100x difference in how long FB and BG threads actually sleep
+    // Look for 10x difference in how long FB and BG threads actually sleep
     // when trying to sleep for 1 ns.  This difference is large enough not
     // to happen by chance, but small enough (compared to 800x) to keep inherent
     // fuzziness in scheduler behavior from causing false negatives.
-    const unsigned int BG_FG_SLACK_FACTOR = 100;
+    const unsigned int BG_FG_SLACK_FACTOR = 10;
 
     ASSERT_EQ(0, set_sched_policy(0, SP_BACKGROUND));
     auto bgSleepTime = medianSleepTime();
 
     ASSERT_EQ(0, set_sched_policy(0, SP_FOREGROUND));
     auto fgSleepTime = medianSleepTime();
+
     ASSERT_GT(bgSleepTime, fgSleepTime * BG_FG_SLACK_FACTOR);
 }
 
diff --git a/libcutils/tests/sockets_test.cpp b/libcutils/sockets_test.cpp
similarity index 100%
rename from libcutils/tests/sockets_test.cpp
rename to libcutils/sockets_test.cpp
diff --git a/libcutils/tests/test_str_parms.cpp b/libcutils/str_parms_test.cpp
similarity index 100%
rename from libcutils/tests/test_str_parms.cpp
rename to libcutils/str_parms_test.cpp
diff --git a/libcutils/tests/Android.bp b/libcutils/tests/Android.bp
deleted file mode 100644
index fb9bbdd..0000000
--- a/libcutils/tests/Android.bp
+++ /dev/null
@@ -1,91 +0,0 @@
-// Copyright (C) 2014 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: "libcutils_test_default",
-    srcs: ["sockets_test.cpp"],
-
-    target: {
-        android: {
-            srcs: [
-                "AshmemTest.cpp",
-                "MemsetTest.cpp",
-                "PropertiesTest.cpp",
-                "sched_policy_test.cpp",
-                "trace-dev_test.cpp",
-                "test_str_parms.cpp",
-                "android_get_control_socket_test.cpp",
-                "android_get_control_file_test.cpp",
-                "multiuser_test.cpp",
-                "fs_config.cpp",
-            ],
-        },
-
-        not_windows: {
-            srcs: [
-                "test_str_parms.cpp",
-            ],
-        },
-    },
-
-    multilib: {
-        lib32: {
-            suffix: "32",
-        },
-        lib64: {
-            suffix: "64",
-        },
-    },
-
-    cflags: [
-        "-Wall",
-        "-Wextra",
-        "-Werror",
-    ],
-}
-
-test_libraries = [
-    "libcutils",
-    "liblog",
-    "libbase",
-    "libjsoncpp",
-    "libprocessgroup",
-]
-
-cc_test {
-    name: "libcutils_test",
-    test_suites: ["device-tests"],
-    defaults: ["libcutils_test_default"],
-    host_supported: true,
-    shared_libs: test_libraries,
-}
-
-cc_test {
-    name: "libcutils_test_static",
-    test_suites: ["device-tests"],
-    defaults: ["libcutils_test_default"],
-    static_libs: ["libc"] + test_libraries,
-    stl: "libc++_static",
-
-    target: {
-        android: {
-            static_executable: true,
-        },
-        windows: {
-            host_ldlibs: ["-lws2_32"],
-
-            enabled: true,
-        },
-    },
-}
diff --git a/libcutils/tests/AndroidTest.xml b/libcutils/tests/AndroidTest.xml
deleted file mode 100644
index dd7aca2..0000000
--- a/libcutils/tests/AndroidTest.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-<configuration description="Config for libcutils_test">
-    <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
-        <option name="cleanup" value="true" />
-        <option name="push" value="libcutils_test->/data/local/tmp/libcutils_test" />
-    </target_preparer>
-    <option name="test-suite-tag" value="apct" />
-    <test class="com.android.tradefed.testtype.GTest" >
-        <option name="native-test-device-path" value="/data/local/tmp" />
-        <option name="module-name" value="libcutils_test" />
-    </test>
-</configuration>
\ No newline at end of file
diff --git a/libcutils/tests/trace-dev_test.cpp b/libcutils/trace-dev_test.cpp
similarity index 100%
rename from libcutils/tests/trace-dev_test.cpp
rename to libcutils/trace-dev_test.cpp
diff --git a/liblog/Android.bp b/liblog/Android.bp
index bd7a551..1d4a0a0 100644
--- a/liblog/Android.bp
+++ b/liblog/Android.bp
@@ -101,7 +101,6 @@
 
     cflags: [
         "-Werror",
-        "-fvisibility=hidden",
         // This is what we want to do:
         //  liblog_cflags := $(shell \
         //   sed -n \
diff --git a/liblog/config_read.cpp b/liblog/config_read.cpp
index 80177a4..3139f78 100644
--- a/liblog/config_read.cpp
+++ b/liblog/config_read.cpp
@@ -19,10 +19,10 @@
 #include "config_read.h"
 #include "logger.h"
 
-LIBLOG_HIDDEN struct listnode __android_log_transport_read = {&__android_log_transport_read,
-                                                              &__android_log_transport_read};
-LIBLOG_HIDDEN struct listnode __android_log_persist_read = {&__android_log_persist_read,
-                                                            &__android_log_persist_read};
+struct listnode __android_log_transport_read = {&__android_log_transport_read,
+                                                &__android_log_transport_read};
+struct listnode __android_log_persist_read = {&__android_log_persist_read,
+                                              &__android_log_persist_read};
 
 static void __android_log_add_transport(struct listnode* list,
                                         struct android_log_transport_read* transport) {
@@ -52,7 +52,7 @@
   }
 }
 
-LIBLOG_HIDDEN void __android_log_config_read() {
+void __android_log_config_read() {
 #if (FAKE_LOG_DEVICE == 0)
   if ((__android_log_transport == LOGGER_DEFAULT) || (__android_log_transport & LOGGER_LOGD)) {
     extern struct android_log_transport_read logdLoggerRead;
@@ -64,7 +64,7 @@
 #endif
 }
 
-LIBLOG_HIDDEN void __android_log_config_read_close() {
+void __android_log_config_read_close() {
   struct android_log_transport_read* transport;
   struct listnode* n;
 
diff --git a/liblog/config_read.h b/liblog/config_read.h
index 00ea453..212b8a0 100644
--- a/liblog/config_read.h
+++ b/liblog/config_read.h
@@ -22,8 +22,8 @@
 
 __BEGIN_DECLS
 
-extern LIBLOG_HIDDEN struct listnode __android_log_transport_read;
-extern LIBLOG_HIDDEN struct listnode __android_log_persist_read;
+extern struct listnode __android_log_transport_read;
+extern struct listnode __android_log_persist_read;
 
 #define read_transport_for_each(transp, transports)                           \
   for ((transp) = node_to_item((transports)->next,                            \
@@ -46,7 +46,7 @@
        (transp) = node_to_item((n), struct android_log_transport_read, node), \
       (n) = (transp)->node.next)
 
-LIBLOG_HIDDEN void __android_log_config_read();
-LIBLOG_HIDDEN void __android_log_config_read_close();
+void __android_log_config_read();
+void __android_log_config_read_close();
 
 __END_DECLS
diff --git a/liblog/config_write.cpp b/liblog/config_write.cpp
index e65c238..d454379 100644
--- a/liblog/config_write.cpp
+++ b/liblog/config_write.cpp
@@ -19,10 +19,10 @@
 #include "config_write.h"
 #include "logger.h"
 
-LIBLOG_HIDDEN struct listnode __android_log_transport_write = {&__android_log_transport_write,
-                                                               &__android_log_transport_write};
-LIBLOG_HIDDEN struct listnode __android_log_persist_write = {&__android_log_persist_write,
-                                                             &__android_log_persist_write};
+struct listnode __android_log_transport_write = {&__android_log_transport_write,
+                                                 &__android_log_transport_write};
+struct listnode __android_log_persist_write = {&__android_log_persist_write,
+                                               &__android_log_persist_write};
 
 static void __android_log_add_transport(struct listnode* list,
                                         struct android_log_transport_write* transport) {
@@ -52,7 +52,7 @@
   }
 }
 
-LIBLOG_HIDDEN void __android_log_config_write() {
+void __android_log_config_write() {
   if ((__android_log_transport == LOGGER_DEFAULT) || (__android_log_transport & LOGGER_LOGD)) {
 #if (FAKE_LOG_DEVICE == 0)
     extern struct android_log_transport_write logdLoggerWrite;
@@ -89,7 +89,7 @@
   }
 }
 
-LIBLOG_HIDDEN void __android_log_config_write_close() {
+void __android_log_config_write_close() {
   struct android_log_transport_write* transport;
   struct listnode* n;
 
diff --git a/liblog/config_write.h b/liblog/config_write.h
index e3be445..a901f13 100644
--- a/liblog/config_write.h
+++ b/liblog/config_write.h
@@ -22,8 +22,8 @@
 
 __BEGIN_DECLS
 
-extern LIBLOG_HIDDEN struct listnode __android_log_transport_write;
-extern LIBLOG_HIDDEN struct listnode __android_log_persist_write;
+extern struct listnode __android_log_transport_write;
+extern struct listnode __android_log_persist_write;
 
 #define write_transport_for_each(transp, transports)                           \
   for ((transp) = node_to_item((transports)->next,                             \
@@ -46,7 +46,7 @@
        (transp) = node_to_item((n), struct android_log_transport_write, node), \
       (n) = (transp)->node.next)
 
-LIBLOG_HIDDEN void __android_log_config_write();
-LIBLOG_HIDDEN void __android_log_config_write_close();
+void __android_log_config_write();
+void __android_log_config_write_close();
 
 __END_DECLS
diff --git a/liblog/event_tag_map.cpp b/liblog/event_tag_map.cpp
index 574a386..22cf43b 100644
--- a/liblog/event_tag_map.cpp
+++ b/liblog/event_tag_map.cpp
@@ -407,7 +407,7 @@
 //
 // We create a private mapping because we want to terminate the log tag
 // strings with '\0'.
-LIBLOG_ABI_PUBLIC EventTagMap* android_openEventTagMap(const char* fileName) {
+EventTagMap* android_openEventTagMap(const char* fileName) {
   EventTagMap* newTagMap;
   off_t end[NUM_MAPS];
   int save_errno, fd[NUM_MAPS];
@@ -488,7 +488,7 @@
 }
 
 // Close the map.
-LIBLOG_ABI_PUBLIC void android_closeEventTagMap(EventTagMap* map) {
+void android_closeEventTagMap(EventTagMap* map) {
   if (map) delete map;
 }
 
@@ -535,9 +535,7 @@
 }
 
 // Look up an entry in the map.
-LIBLOG_ABI_PUBLIC const char* android_lookupEventTag_len(const EventTagMap* map,
-                                                         size_t* len,
-                                                         unsigned int tag) {
+const char* android_lookupEventTag_len(const EventTagMap* map, size_t* len, unsigned int tag) {
   if (len) *len = 0;
   const TagFmt* str = map->find(tag);
   if (!str) {
@@ -549,8 +547,7 @@
 }
 
 // Look up an entry in the map.
-LIBLOG_ABI_PUBLIC const char* android_lookupEventFormat_len(
-    const EventTagMap* map, size_t* len, unsigned int tag) {
+const char* android_lookupEventFormat_len(const EventTagMap* map, size_t* len, unsigned int tag) {
   if (len) *len = 0;
   const TagFmt* str = map->find(tag);
   if (!str) {
@@ -565,8 +562,7 @@
 // since it will cause the map to change from Shared and backed by a file,
 // to Private Dirty and backed up by swap, albeit highly compressible. By
 // deprecating this function everywhere, we save 100s of MB of memory space.
-LIBLOG_ABI_PUBLIC const char* android_lookupEventTag(const EventTagMap* map,
-                                                     unsigned int tag) {
+const char* android_lookupEventTag(const EventTagMap* map, unsigned int tag) {
   size_t len;
   const char* tagStr = android_lookupEventTag_len(map, &len, tag);
 
@@ -578,9 +574,7 @@
 }
 
 // Look up tagname, generate one if necessary, and return a tag
-LIBLOG_ABI_PUBLIC int android_lookupEventTagNum(EventTagMap* map,
-                                                const char* tagname,
-                                                const char* format, int prio) {
+int android_lookupEventTagNum(EventTagMap* map, const char* tagname, const char* format, int prio) {
   const char* ep = endOfTag(tagname);
   size_t len = ep - tagname;
   if (!len || *ep) {
diff --git a/liblog/fake_log_device.cpp b/liblog/fake_log_device.cpp
index 5daae41..428a482 100644
--- a/liblog/fake_log_device.cpp
+++ b/liblog/fake_log_device.cpp
@@ -548,7 +548,7 @@
  *  tag (N bytes -- null-terminated ASCII string)
  *  message (N bytes -- null-terminated ASCII string)
  */
-LIBLOG_HIDDEN ssize_t fakeLogWritev(int fd, const struct iovec* vector, int count) {
+ssize_t fakeLogWritev(int fd, const struct iovec* vector, int count) {
   LogState* state;
 
   /* Make sure that no-one frees the LogState while we're using it.
@@ -623,7 +623,7 @@
  * call is in the exit handler. Logging can continue in the exit handler to
  * help debug HOST tools ...
  */
-LIBLOG_HIDDEN int fakeLogClose(int fd) {
+int fakeLogClose(int fd) {
   deleteFakeFd(fd);
   return 0;
 }
@@ -631,7 +631,7 @@
 /*
  * Open a log output device and return a fake fd.
  */
-LIBLOG_HIDDEN int fakeLogOpen(const char* pathName) {
+int fakeLogOpen(const char* pathName) {
   LogState* logState;
   int fd = -1;
 
@@ -650,20 +650,20 @@
   return fd;
 }
 
-LIBLOG_HIDDEN ssize_t __send_log_msg(char*, size_t) {
+ssize_t __send_log_msg(char*, size_t) {
   return -ENODEV;
 }
 
-LIBLOG_ABI_PUBLIC int __android_log_is_loggable(int prio, const char*, int def) {
+int __android_log_is_loggable(int prio, const char*, int def) {
   int logLevel = def;
   return logLevel >= 0 && prio >= logLevel;
 }
 
-LIBLOG_ABI_PUBLIC int __android_log_is_loggable_len(int prio, const char*, size_t, int def) {
+int __android_log_is_loggable_len(int prio, const char*, size_t, int def) {
   int logLevel = def;
   return logLevel >= 0 && prio >= logLevel;
 }
 
-LIBLOG_ABI_PRIVATE int __android_log_is_debuggable() {
+int __android_log_is_debuggable() {
   return 1;
 }
diff --git a/liblog/fake_log_device.h b/liblog/fake_log_device.h
index ef0beb6..ce54db2 100644
--- a/liblog/fake_log_device.h
+++ b/liblog/fake_log_device.h
@@ -25,14 +25,13 @@
 
 __BEGIN_DECLS
 
-LIBLOG_HIDDEN int fakeLogOpen(const char* pathName);
-LIBLOG_HIDDEN int fakeLogClose(int fd);
-LIBLOG_HIDDEN ssize_t fakeLogWritev(int fd, const struct iovec* vector,
-                                    int count);
+int fakeLogOpen(const char* pathName);
+int fakeLogClose(int fd);
+ssize_t fakeLogWritev(int fd, const struct iovec* vector, int count);
 
-LIBLOG_HIDDEN ssize_t __send_log_msg(char*, size_t);
-LIBLOG_ABI_PUBLIC int __android_log_is_loggable(int prio, const char*, int def);
-LIBLOG_ABI_PUBLIC int __android_log_is_loggable_len(int prio, const char*, size_t, int def);
-LIBLOG_ABI_PRIVATE int __android_log_is_debuggable();
+ssize_t __send_log_msg(char*, size_t);
+int __android_log_is_loggable(int prio, const char*, int def);
+int __android_log_is_loggable_len(int prio, const char*, size_t, int def);
+int __android_log_is_debuggable();
 
 __END_DECLS
diff --git a/liblog/fake_writer.cpp b/liblog/fake_writer.cpp
index 46d171b..c0b0e69 100644
--- a/liblog/fake_writer.cpp
+++ b/liblog/fake_writer.cpp
@@ -31,7 +31,7 @@
 
 static int logFds[(int)LOG_ID_MAX] = {-1, -1, -1, -1, -1, -1};
 
-LIBLOG_HIDDEN struct android_log_transport_write fakeLoggerWrite = {
+struct android_log_transport_write fakeLoggerWrite = {
     .node = {&fakeLoggerWrite.node, &fakeLoggerWrite.node},
     .context.priv = &logFds,
     .name = "fake",
diff --git a/liblog/log_event_list.cpp b/liblog/log_event_list.cpp
index 088ea94..b1b527c 100644
--- a/liblog/log_event_list.cpp
+++ b/liblog/log_event_list.cpp
@@ -73,7 +73,7 @@
   context->read_write_flag = kAndroidLoggerRead;
 }
 
-LIBLOG_ABI_PUBLIC android_log_context create_android_logger(uint32_t tag) {
+android_log_context create_android_logger(uint32_t tag) {
   android_log_context_internal* context;
 
   context =
@@ -86,7 +86,7 @@
   return (android_log_context)context;
 }
 
-LIBLOG_ABI_PUBLIC android_log_context create_android_log_parser(const char* msg, size_t len) {
+android_log_context create_android_log_parser(const char* msg, size_t len) {
   android_log_context_internal* context;
   size_t i;
 
@@ -100,7 +100,7 @@
   return (android_log_context)context;
 }
 
-LIBLOG_ABI_PUBLIC int android_log_destroy(android_log_context* ctx) {
+int android_log_destroy(android_log_context* ctx) {
   android_log_context_internal* context;
 
   context = (android_log_context_internal*)*ctx;
@@ -113,7 +113,7 @@
   return 0;
 }
 
-LIBLOG_ABI_PUBLIC int android_log_reset(android_log_context ctx) {
+int android_log_reset(android_log_context ctx) {
   android_log_context_internal* context;
   uint32_t tag;
 
@@ -129,8 +129,7 @@
   return 0;
 }
 
-LIBLOG_ABI_PUBLIC int android_log_parser_reset(android_log_context ctx, const char* msg,
-                                               size_t len) {
+int android_log_parser_reset(android_log_context ctx, const char* msg, size_t len) {
   android_log_context_internal* context;
 
   context = (android_log_context_internal*)ctx;
@@ -144,7 +143,7 @@
   return 0;
 }
 
-LIBLOG_ABI_PUBLIC int android_log_write_list_begin(android_log_context ctx) {
+int android_log_write_list_begin(android_log_context ctx) {
   size_t needed;
   android_log_context_internal* context;
 
@@ -185,7 +184,7 @@
   buf[3] = (val >> 24) & 0xFF;
 }
 
-LIBLOG_ABI_PUBLIC int android_log_write_int32(android_log_context ctx, int32_t value) {
+int android_log_write_int32(android_log_context ctx, int32_t value) {
   size_t needed;
   android_log_context_internal* context;
 
@@ -219,7 +218,7 @@
   buf[7] = (val >> 56) & 0xFF;
 }
 
-LIBLOG_ABI_PUBLIC int android_log_write_int64(android_log_context ctx, int64_t value) {
+int android_log_write_int64(android_log_context ctx, int64_t value) {
   size_t needed;
   android_log_context_internal* context;
 
@@ -242,8 +241,7 @@
   return 0;
 }
 
-LIBLOG_ABI_PUBLIC int android_log_write_string8_len(android_log_context ctx, const char* value,
-                                                    size_t maxlen) {
+int android_log_write_string8_len(android_log_context ctx, const char* value, size_t maxlen) {
   size_t needed;
   ssize_t len;
   android_log_context_internal* context;
@@ -278,11 +276,11 @@
   return len;
 }
 
-LIBLOG_ABI_PUBLIC int android_log_write_string8(android_log_context ctx, const char* value) {
+int android_log_write_string8(android_log_context ctx, const char* value) {
   return android_log_write_string8_len(ctx, value, MAX_EVENT_PAYLOAD);
 }
 
-LIBLOG_ABI_PUBLIC int android_log_write_float32(android_log_context ctx, float value) {
+int android_log_write_float32(android_log_context ctx, float value) {
   size_t needed;
   uint32_t ivalue;
   android_log_context_internal* context;
@@ -307,7 +305,7 @@
   return 0;
 }
 
-LIBLOG_ABI_PUBLIC int android_log_write_list_end(android_log_context ctx) {
+int android_log_write_list_end(android_log_context ctx) {
   android_log_context_internal* context;
 
   context = (android_log_context_internal*)ctx;
@@ -337,7 +335,7 @@
 /*
  * Logs the list of elements to the event log.
  */
-LIBLOG_ABI_PUBLIC int android_log_write_list(android_log_context ctx, log_id_t id) {
+int android_log_write_list(android_log_context ctx, log_id_t id) {
   android_log_context_internal* context;
   const char* msg;
   ssize_t len;
@@ -371,7 +369,7 @@
                                      : __android_log_security_bwrite(context->tag, msg, len));
 }
 
-LIBLOG_ABI_PRIVATE int android_log_write_list_buffer(android_log_context ctx, const char** buffer) {
+int android_log_write_list_buffer(android_log_context ctx, const char** buffer) {
   android_log_context_internal* context;
   const char* msg;
   ssize_t len;
@@ -593,10 +591,10 @@
   }
 }
 
-LIBLOG_ABI_PUBLIC android_log_list_element android_log_read_next(android_log_context ctx) {
+android_log_list_element android_log_read_next(android_log_context ctx) {
   return android_log_read_next_internal(ctx, 0);
 }
 
-LIBLOG_ABI_PUBLIC android_log_list_element android_log_peek_next(android_log_context ctx) {
+android_log_list_element android_log_peek_next(android_log_context ctx) {
   return android_log_read_next_internal(ctx, 1);
 }
diff --git a/liblog/log_event_write.cpp b/liblog/log_event_write.cpp
index e644a3b..d04ba90 100644
--- a/liblog/log_event_write.cpp
+++ b/liblog/log_event_write.cpp
@@ -24,8 +24,8 @@
 
 #define MAX_SUBTAG_LEN 32
 
-LIBLOG_ABI_PUBLIC int __android_log_error_write(int tag, const char* subTag, int32_t uid,
-                                                const char* data, uint32_t dataLen) {
+int __android_log_error_write(int tag, const char* subTag, int32_t uid, const char* data,
+                              uint32_t dataLen) {
   int ret = -EINVAL;
 
   if (subTag && (data || !dataLen)) {
diff --git a/liblog/log_portability.h b/liblog/log_portability.h
index b9fb1d2..468a498 100644
--- a/liblog/log_portability.h
+++ b/liblog/log_portability.h
@@ -19,25 +19,6 @@
 #include <sys/cdefs.h>
 #include <unistd.h>
 
-/* Helpful private sys/cdefs.h like definitions */
-
-/* Declare this library function hidden and internal */
-#if defined(_WIN32)
-#define LIBLOG_HIDDEN
-#else
-#define LIBLOG_HIDDEN __attribute__((visibility("hidden")))
-#endif
-
-/* Declare this library function visible and external */
-#if defined(_WIN32)
-#define LIBLOG_ABI_PUBLIC
-#else
-#define LIBLOG_ABI_PUBLIC __attribute__((visibility("default")))
-#endif
-
-/* Declare this library function visible but private */
-#define LIBLOG_ABI_PRIVATE LIBLOG_ABI_PUBLIC
-
 /*
  * Declare this library function as reimplementation.
  * Prevent circular dependencies, but allow _real_ library to hijack
diff --git a/liblog/log_time.cpp b/liblog/log_time.cpp
index 77bb94f..3ae250f 100644
--- a/liblog/log_time.cpp
+++ b/liblog/log_time.cpp
@@ -23,12 +23,12 @@
 
 #include "log_portability.h"
 
-LIBLOG_ABI_PRIVATE const char log_time::default_format[] = "%m-%d %H:%M:%S.%q";
-LIBLOG_ABI_PRIVATE const timespec log_time::EPOCH = { 0, 0 };
+const char log_time::default_format[] = "%m-%d %H:%M:%S.%q";
+const timespec log_time::EPOCH = {0, 0};
 
 // Add %#q for fractional seconds to standard strptime function
 
-LIBLOG_ABI_PRIVATE char* log_time::strptime(const char* s, const char* format) {
+char* log_time::strptime(const char* s, const char* format) {
   time_t now;
 #ifdef __linux__
   *this = log_time(CLOCK_REALTIME);
@@ -134,7 +134,7 @@
   return ret;
 }
 
-LIBLOG_ABI_PRIVATE log_time log_time::operator-=(const timespec& T) {
+log_time log_time::operator-=(const timespec& T) {
   // No concept of negative time, clamp to EPOCH
   if (*this <= T) {
     return *this = log_time(EPOCH);
@@ -151,7 +151,7 @@
   return *this;
 }
 
-LIBLOG_ABI_PRIVATE log_time log_time::operator+=(const timespec& T) {
+log_time log_time::operator+=(const timespec& T) {
   this->tv_nsec += (unsigned long int)T.tv_nsec;
   if (this->tv_nsec >= NS_PER_SEC) {
     this->tv_nsec -= NS_PER_SEC;
@@ -162,7 +162,7 @@
   return *this;
 }
 
-LIBLOG_ABI_PRIVATE log_time log_time::operator-=(const log_time& T) {
+log_time log_time::operator-=(const log_time& T) {
   // No concept of negative time, clamp to EPOCH
   if (*this <= T) {
     return *this = log_time(EPOCH);
@@ -179,7 +179,7 @@
   return *this;
 }
 
-LIBLOG_ABI_PRIVATE log_time log_time::operator+=(const log_time& T) {
+log_time log_time::operator+=(const log_time& T) {
   this->tv_nsec += T.tv_nsec;
   if (this->tv_nsec >= NS_PER_SEC) {
     this->tv_nsec -= NS_PER_SEC;
diff --git a/liblog/logd_reader.cpp b/liblog/logd_reader.cpp
index 05bbcbc..2f0af4a 100644
--- a/liblog/logd_reader.cpp
+++ b/liblog/logd_reader.cpp
@@ -67,7 +67,7 @@
 static ssize_t logdGetStats(struct android_log_logger_list* logger,
                             struct android_log_transport_context* transp, char* buf, size_t len);
 
-LIBLOG_HIDDEN struct android_log_transport_read logdLoggerRead = {
+struct android_log_transport_read logdLoggerRead = {
     .node = {&logdLoggerRead.node, &logdLoggerRead.node},
     .name = "logd",
     .available = logdAvailable,
@@ -309,7 +309,7 @@
   return ret;
 }
 
-LIBLOG_HIDDEN ssize_t __send_log_msg(char* buf, size_t buf_size) {
+ssize_t __send_log_msg(char* buf, size_t buf_size) {
   return send_log_msg(NULL, NULL, buf, buf_size);
 }
 
diff --git a/liblog/logd_reader.h b/liblog/logd_reader.h
index 0bba7cf..7c53cbb 100644
--- a/liblog/logd_reader.h
+++ b/liblog/logd_reader.h
@@ -22,6 +22,6 @@
 
 __BEGIN_DECLS
 
-LIBLOG_HIDDEN ssize_t __send_log_msg(char* buf, size_t buf_size);
+ssize_t __send_log_msg(char* buf, size_t buf_size);
 
 __END_DECLS
diff --git a/liblog/logd_writer.cpp b/liblog/logd_writer.cpp
index ed906b3..c3f72f4 100644
--- a/liblog/logd_writer.cpp
+++ b/liblog/logd_writer.cpp
@@ -48,7 +48,7 @@
 static void logdClose();
 static int logdWrite(log_id_t logId, struct timespec* ts, struct iovec* vec, size_t nr);
 
-LIBLOG_HIDDEN struct android_log_transport_write logdLoggerWrite = {
+struct android_log_transport_write logdLoggerWrite = {
     .node = {&logdLoggerWrite.node, &logdLoggerWrite.node},
     .context.sock = -EBADF,
     .name = "logd",
diff --git a/liblog/logger.h b/liblog/logger.h
index b2479d2..1f632c0 100644
--- a/liblog/logger.h
+++ b/liblog/logger.h
@@ -156,10 +156,10 @@
 }
 #endif
 
-LIBLOG_HIDDEN void __android_log_lock();
-LIBLOG_HIDDEN int __android_log_trylock();
-LIBLOG_HIDDEN void __android_log_unlock();
+void __android_log_lock();
+int __android_log_trylock();
+void __android_log_unlock();
 
-extern LIBLOG_HIDDEN int __android_log_transport;
+extern int __android_log_transport;
 
 __END_DECLS
diff --git a/liblog/logger_lock.cpp b/liblog/logger_lock.cpp
index d4e3a75..4636b00 100644
--- a/liblog/logger_lock.cpp
+++ b/liblog/logger_lock.cpp
@@ -28,7 +28,7 @@
 static pthread_mutex_t log_init_lock = PTHREAD_MUTEX_INITIALIZER;
 #endif
 
-LIBLOG_HIDDEN void __android_log_lock() {
+void __android_log_lock() {
 #if !defined(_WIN32)
   /*
    * If we trigger a signal handler in the middle of locked activity and the
@@ -38,7 +38,7 @@
 #endif
 }
 
-LIBLOG_HIDDEN int __android_log_trylock() {
+int __android_log_trylock() {
 #if !defined(_WIN32)
   return pthread_mutex_trylock(&log_init_lock);
 #else
@@ -46,7 +46,7 @@
 #endif
 }
 
-LIBLOG_HIDDEN void __android_log_unlock() {
+void __android_log_unlock() {
 #if !defined(_WIN32)
   pthread_mutex_unlock(&log_init_lock);
 #endif
diff --git a/liblog/logger_name.cpp b/liblog/logger_name.cpp
index c6f3cb7..3aa6841 100644
--- a/liblog/logger_name.cpp
+++ b/liblog/logger_name.cpp
@@ -35,7 +35,7 @@
     /* clang-format on */
 };
 
-LIBLOG_ABI_PUBLIC const char* android_log_id_to_name(log_id_t log_id) {
+const char* android_log_id_to_name(log_id_t log_id) {
   if (log_id >= LOG_ID_MAX) {
     log_id = LOG_ID_MAIN;
   }
@@ -45,7 +45,7 @@
 static_assert(std::is_same<std::underlying_type<log_id_t>::type, uint32_t>::value,
               "log_id_t must be an unsigned int");
 
-LIBLOG_ABI_PUBLIC log_id_t android_name_to_log_id(const char* logName) {
+log_id_t android_name_to_log_id(const char* logName) {
   const char* b;
   unsigned int ret;
 
diff --git a/liblog/logger_read.cpp b/liblog/logger_read.cpp
index e429c36..4cf0846 100644
--- a/liblog/logger_read.cpp
+++ b/liblog/logger_read.cpp
@@ -50,7 +50,7 @@
 /* android_logger_alloc unimplemented, no use case */
 
 /* method for getting the associated sublog id */
-LIBLOG_ABI_PUBLIC log_id_t android_logger_get_id(struct logger* logger) {
+log_id_t android_logger_get_id(struct logger* logger) {
   return ((struct android_log_logger*)logger)->logId;
 }
 
@@ -139,16 +139,16 @@
   }                                                                                  \
   return ret
 
-LIBLOG_ABI_PUBLIC int android_logger_clear(struct logger* logger) {
+int android_logger_clear(struct logger* logger) {
   LOGGER_FUNCTION(logger, -ENODEV, clear);
 }
 
 /* returns the total size of the log's ring buffer */
-LIBLOG_ABI_PUBLIC long android_logger_get_log_size(struct logger* logger) {
+long android_logger_get_log_size(struct logger* logger) {
   LOGGER_FUNCTION(logger, -ENODEV, getSize);
 }
 
-LIBLOG_ABI_PUBLIC int android_logger_set_log_size(struct logger* logger, unsigned long size) {
+int android_logger_set_log_size(struct logger* logger, unsigned long size) {
   LOGGER_FUNCTION(logger, -ENODEV, setSize, size);
 }
 
@@ -156,14 +156,14 @@
  * returns the readable size of the log's ring buffer (that is, amount of the
  * log consumed)
  */
-LIBLOG_ABI_PUBLIC long android_logger_get_log_readable_size(struct logger* logger) {
+long android_logger_get_log_readable_size(struct logger* logger) {
   LOGGER_FUNCTION(logger, -ENODEV, getReadableSize);
 }
 
 /*
  * returns the logger version
  */
-LIBLOG_ABI_PUBLIC int android_logger_get_log_version(struct logger* logger) {
+int android_logger_get_log_version(struct logger* logger) {
   LOGGER_FUNCTION(logger, 4, version);
 }
 
@@ -191,23 +191,19 @@
 /*
  * returns statistics
  */
-LIBLOG_ABI_PUBLIC ssize_t android_logger_get_statistics(struct logger_list* logger_list, char* buf,
-                                                        size_t len) {
+ssize_t android_logger_get_statistics(struct logger_list* logger_list, char* buf, size_t len) {
   LOGGER_LIST_FUNCTION(logger_list, -ENODEV, getStats, buf, len);
 }
 
-LIBLOG_ABI_PUBLIC ssize_t android_logger_get_prune_list(struct logger_list* logger_list, char* buf,
-                                                        size_t len) {
+ssize_t android_logger_get_prune_list(struct logger_list* logger_list, char* buf, size_t len) {
   LOGGER_LIST_FUNCTION(logger_list, -ENODEV, getPrune, buf, len);
 }
 
-LIBLOG_ABI_PUBLIC int android_logger_set_prune_list(struct logger_list* logger_list, char* buf,
-                                                    size_t len) {
+int android_logger_set_prune_list(struct logger_list* logger_list, char* buf, size_t len) {
   LOGGER_LIST_FUNCTION(logger_list, -ENODEV, setPrune, buf, len);
 }
 
-LIBLOG_ABI_PUBLIC struct logger_list* android_logger_list_alloc(int mode, unsigned int tail,
-                                                                pid_t pid) {
+struct logger_list* android_logger_list_alloc(int mode, unsigned int tail, pid_t pid) {
   struct android_log_logger_list* logger_list;
 
   logger_list = static_cast<android_log_logger_list*>(calloc(1, sizeof(*logger_list)));
@@ -224,8 +220,7 @@
   return (struct logger_list*)logger_list;
 }
 
-LIBLOG_ABI_PUBLIC struct logger_list* android_logger_list_alloc_time(int mode, log_time start,
-                                                                     pid_t pid) {
+struct logger_list* android_logger_list_alloc_time(int mode, log_time start, pid_t pid) {
   struct android_log_logger_list* logger_list;
 
   logger_list = static_cast<android_log_logger_list*>(calloc(1, sizeof(*logger_list)));
@@ -246,8 +241,7 @@
 /* android_logger_list_unregister unimplemented, no use case */
 
 /* Open the named log and add it to the logger list */
-LIBLOG_ABI_PUBLIC struct logger* android_logger_open(struct logger_list* logger_list,
-                                                     log_id_t logId) {
+struct logger* android_logger_open(struct logger_list* logger_list, log_id_t logId) {
   struct android_log_logger_list* logger_list_internal =
       (struct android_log_logger_list*)logger_list;
   struct android_log_logger* logger;
@@ -289,8 +283,8 @@
 }
 
 /* Open the single named log and make it part of a new logger list */
-LIBLOG_ABI_PUBLIC struct logger_list* android_logger_list_open(log_id_t logId, int mode,
-                                                               unsigned int tail, pid_t pid) {
+struct logger_list* android_logger_list_open(log_id_t logId, int mode, unsigned int tail,
+                                             pid_t pid) {
   struct logger_list* logger_list = android_logger_list_alloc(mode, tail, pid);
 
   if (!logger_list) {
@@ -345,8 +339,7 @@
 }
 
 /* Read from the selected logs */
-LIBLOG_ABI_PUBLIC int android_logger_list_read(struct logger_list* logger_list,
-                                               struct log_msg* log_msg) {
+int android_logger_list_read(struct logger_list* logger_list, struct log_msg* log_msg) {
   struct android_log_transport_context* transp;
   struct android_log_logger_list* logger_list_internal =
       (struct android_log_logger_list*)logger_list;
@@ -437,7 +430,7 @@
 }
 
 /* Close all the logs */
-LIBLOG_ABI_PUBLIC void android_logger_list_free(struct logger_list* logger_list) {
+void android_logger_list_free(struct logger_list* logger_list) {
   struct android_log_logger_list* logger_list_internal =
       (struct android_log_logger_list*)logger_list;
 
diff --git a/liblog/logger_write.cpp b/liblog/logger_write.cpp
index af8cb2d..908fe7f 100644
--- a/liblog/logger_write.cpp
+++ b/liblog/logger_write.cpp
@@ -105,7 +105,7 @@
   }
 }
 
-LIBLOG_ABI_PUBLIC extern "C" int __android_log_dev_available() {
+extern "C" int __android_log_dev_available() {
   struct android_log_transport_write* node;
 
   if (list_empty(&__android_log_transport_write)) {
@@ -128,7 +128,7 @@
 /*
  * Release any logger resources. A new log write will immediately re-acquire.
  */
-LIBLOG_ABI_PUBLIC void __android_log_close() {
+void __android_log_close() {
   struct android_log_transport_write* transport;
 #if defined(__ANDROID__)
   EventTagMap* m;
@@ -402,12 +402,11 @@
   return ret;
 }
 
-LIBLOG_ABI_PUBLIC int __android_log_write(int prio, const char* tag, const char* msg) {
+int __android_log_write(int prio, const char* tag, const char* msg) {
   return __android_log_buf_write(LOG_ID_MAIN, prio, tag, msg);
 }
 
-LIBLOG_ABI_PUBLIC int __android_log_buf_write(int bufID, int prio, const char* tag,
-                                              const char* msg) {
+int __android_log_buf_write(int bufID, int prio, const char* tag, const char* msg) {
   struct iovec vec[3];
   char tmp_tag[32];
 
@@ -472,7 +471,7 @@
   return write_to_log(static_cast<log_id_t>(bufID), vec, 3);
 }
 
-LIBLOG_ABI_PUBLIC int __android_log_vprint(int prio, const char* tag, const char* fmt, va_list ap) {
+int __android_log_vprint(int prio, const char* tag, const char* fmt, va_list ap) {
   char buf[LOG_BUF_SIZE];
 
   vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
@@ -480,7 +479,7 @@
   return __android_log_write(prio, tag, buf);
 }
 
-LIBLOG_ABI_PUBLIC int __android_log_print(int prio, const char* tag, const char* fmt, ...) {
+int __android_log_print(int prio, const char* tag, const char* fmt, ...) {
   va_list ap;
   char buf[LOG_BUF_SIZE];
 
@@ -491,8 +490,7 @@
   return __android_log_write(prio, tag, buf);
 }
 
-LIBLOG_ABI_PUBLIC int __android_log_buf_print(int bufID, int prio, const char* tag, const char* fmt,
-                                              ...) {
+int __android_log_buf_print(int bufID, int prio, const char* tag, const char* fmt, ...) {
   va_list ap;
   char buf[LOG_BUF_SIZE];
 
@@ -503,8 +501,7 @@
   return __android_log_buf_write(bufID, prio, tag, buf);
 }
 
-LIBLOG_ABI_PUBLIC void __android_log_assert(const char* cond, const char* tag, const char* fmt,
-                                            ...) {
+void __android_log_assert(const char* cond, const char* tag, const char* fmt, ...) {
   char buf[LOG_BUF_SIZE];
 
   if (fmt) {
@@ -533,7 +530,7 @@
            /* NOTREACHED */
 }
 
-LIBLOG_ABI_PUBLIC int __android_log_bwrite(int32_t tag, const void* payload, size_t len) {
+int __android_log_bwrite(int32_t tag, const void* payload, size_t len) {
   struct iovec vec[2];
 
   vec[0].iov_base = &tag;
@@ -544,7 +541,7 @@
   return write_to_log(LOG_ID_EVENTS, vec, 2);
 }
 
-LIBLOG_ABI_PUBLIC int __android_log_stats_bwrite(int32_t tag, const void* payload, size_t len) {
+int __android_log_stats_bwrite(int32_t tag, const void* payload, size_t len) {
   struct iovec vec[2];
 
   vec[0].iov_base = &tag;
@@ -555,7 +552,7 @@
   return write_to_log(LOG_ID_STATS, vec, 2);
 }
 
-LIBLOG_ABI_PUBLIC int __android_log_security_bwrite(int32_t tag, const void* payload, size_t len) {
+int __android_log_security_bwrite(int32_t tag, const void* payload, size_t len) {
   struct iovec vec[2];
 
   vec[0].iov_base = &tag;
@@ -571,8 +568,7 @@
  * for the general case where we're generating lists of stuff, but very
  * handy if we just want to dump an integer into the log.
  */
-LIBLOG_ABI_PUBLIC int __android_log_btwrite(int32_t tag, char type, const void* payload,
-                                            size_t len) {
+int __android_log_btwrite(int32_t tag, char type, const void* payload, size_t len) {
   struct iovec vec[3];
 
   vec[0].iov_base = &tag;
@@ -589,7 +585,7 @@
  * Like __android_log_bwrite, but used for writing strings to the
  * event log.
  */
-LIBLOG_ABI_PUBLIC int __android_log_bswrite(int32_t tag, const char* payload) {
+int __android_log_bswrite(int32_t tag, const char* payload) {
   struct iovec vec[4];
   char type = EVENT_TYPE_STRING;
   uint32_t len = strlen(payload);
@@ -610,7 +606,7 @@
  * Like __android_log_security_bwrite, but used for writing strings to the
  * security log.
  */
-LIBLOG_ABI_PUBLIC int __android_log_security_bswrite(int32_t tag, const char* payload) {
+int __android_log_security_bswrite(int32_t tag, const char* payload) {
   struct iovec vec[4];
   char type = EVENT_TYPE_STRING;
   uint32_t len = strlen(payload);
@@ -645,9 +641,9 @@
 
 /* Following functions need access to our internal write_to_log status */
 
-LIBLOG_HIDDEN int __android_log_transport;
+int __android_log_transport;
 
-LIBLOG_ABI_PUBLIC int android_set_log_transport(int transport_flag) {
+int android_set_log_transport(int transport_flag) {
   int retval;
 
   if (transport_flag < 0) {
@@ -688,7 +684,7 @@
   return retval;
 }
 
-LIBLOG_ABI_PUBLIC int android_get_log_transport() {
+int android_get_log_transport() {
   int ret = LOGGER_DEFAULT;
 
   __android_log_lock();
diff --git a/liblog/logprint.cpp b/liblog/logprint.cpp
index 798b089..bc056cb 100644
--- a/liblog/logprint.cpp
+++ b/liblog/logprint.cpp
@@ -195,12 +195,12 @@
  * returns 1 if this log line should be printed based on its priority
  * and tag, and 0 if it should not
  */
-LIBLOG_ABI_PUBLIC int android_log_shouldPrintLine(AndroidLogFormat* p_format, const char* tag,
-                                                  android_LogPriority pri) {
+int android_log_shouldPrintLine(AndroidLogFormat* p_format, const char* tag,
+                                android_LogPriority pri) {
   return pri >= filterPriForTag(p_format, tag);
 }
 
-LIBLOG_ABI_PUBLIC AndroidLogFormat* android_log_format_new() {
+AndroidLogFormat* android_log_format_new() {
   AndroidLogFormat* p_ret;
 
   p_ret = static_cast<AndroidLogFormat*>(calloc(1, sizeof(AndroidLogFormat)));
@@ -228,7 +228,7 @@
 
 static list_declare(convertHead);
 
-LIBLOG_ABI_PUBLIC void android_log_format_free(AndroidLogFormat* p_format) {
+void android_log_format_free(AndroidLogFormat* p_format) {
   FilterInfo *p_info, *p_info_old;
 
   p_info = p_format->filters;
@@ -251,8 +251,7 @@
   }
 }
 
-LIBLOG_ABI_PUBLIC int android_log_setPrintFormat(AndroidLogFormat* p_format,
-                                                 AndroidLogPrintFormat format) {
+int android_log_setPrintFormat(AndroidLogFormat* p_format, AndroidLogPrintFormat format) {
   switch (format) {
     case FORMAT_MODIFIER_COLOR:
       p_format->colored_output = true;
@@ -298,7 +297,7 @@
 /**
  * Returns FORMAT_OFF on invalid string
  */
-LIBLOG_ABI_PUBLIC AndroidLogPrintFormat android_log_formatFromString(const char* formatString) {
+AndroidLogPrintFormat android_log_formatFromString(const char* formatString) {
   static AndroidLogPrintFormat format;
 
   /* clang-format off */
@@ -367,8 +366,7 @@
  * Assumes single threaded execution
  */
 
-LIBLOG_ABI_PUBLIC int android_log_addFilterRule(AndroidLogFormat* p_format,
-                                                const char* filterExpression) {
+int android_log_addFilterRule(AndroidLogFormat* p_format, const char* filterExpression) {
   size_t tagNameLength;
   android_LogPriority pri = ANDROID_LOG_DEFAULT;
 
@@ -463,8 +461,7 @@
  * Assumes single threaded execution
  *
  */
-LIBLOG_ABI_PUBLIC int android_log_addFilterString(AndroidLogFormat* p_format,
-                                                  const char* filterString) {
+int android_log_addFilterString(AndroidLogFormat* p_format, const char* filterString) {
   char* filterStringCopy = strdup(filterString);
   char* p_cur = filterStringCopy;
   char* p_ret;
@@ -496,8 +493,7 @@
  * Returns 0 on success and -1 on invalid wire format (entry will be
  * in unspecified state)
  */
-LIBLOG_ABI_PUBLIC int android_log_processLogBuffer(struct logger_entry* buf,
-                                                   AndroidLogEntry* entry) {
+int android_log_processLogBuffer(struct logger_entry* buf, AndroidLogEntry* entry) {
   entry->message = NULL;
   entry->messageLen = 0;
 
@@ -997,7 +993,7 @@
  * it however we choose, which means we can't really use a fixed-size buffer
  * here.
  */
-LIBLOG_ABI_PUBLIC int android_log_processBinaryLogBuffer(
+int android_log_processBinaryLogBuffer(
     struct logger_entry* buf, AndroidLogEntry* entry,
     [[maybe_unused]] const EventTagMap* map, /* only on !__ANDROID__ */
     char* messageBuf, int messageBufLen) {
@@ -1525,10 +1521,9 @@
  * Returns NULL on malloc error
  */
 
-LIBLOG_ABI_PUBLIC char* android_log_formatLogLine(AndroidLogFormat* p_format, char* defaultBuffer,
-                                                  size_t defaultBufferSize,
-                                                  const AndroidLogEntry* entry,
-                                                  size_t* p_outLength) {
+char* android_log_formatLogLine(AndroidLogFormat* p_format, char* defaultBuffer,
+                                size_t defaultBufferSize, const AndroidLogEntry* entry,
+                                size_t* p_outLength) {
 #if !defined(_WIN32)
   struct tm tmBuf;
 #endif
@@ -1819,8 +1814,7 @@
  * Returns count bytes written
  */
 
-LIBLOG_ABI_PUBLIC int android_log_printLogLine(AndroidLogFormat* p_format, int fd,
-                                               const AndroidLogEntry* entry) {
+int android_log_printLogLine(AndroidLogFormat* p_format, int fd, const AndroidLogEntry* entry) {
   int ret;
   char defaultBuffer[512];
   char* outBuffer = NULL;
diff --git a/liblog/pmsg_reader.cpp b/liblog/pmsg_reader.cpp
index 7bc6e4a..ba27fd7 100644
--- a/liblog/pmsg_reader.cpp
+++ b/liblog/pmsg_reader.cpp
@@ -38,7 +38,7 @@
 static int pmsgClear(struct android_log_logger* logger,
                      struct android_log_transport_context* transp);
 
-LIBLOG_HIDDEN struct android_log_transport_read pmsgLoggerRead = {
+struct android_log_transport_read pmsgLoggerRead = {
     .node = {&pmsgLoggerRead.node, &pmsgLoggerRead.node},
     .name = "pmsg",
     .available = pmsgAvailable,
@@ -270,10 +270,8 @@
   return result;
 }
 
-LIBLOG_ABI_PRIVATE ssize_t __android_log_pmsg_file_read(log_id_t logId, char prio,
-                                                        const char* prefix,
-                                                        __android_log_pmsg_file_read_fn fn,
-                                                        void* arg) {
+ssize_t __android_log_pmsg_file_read(log_id_t logId, char prio, const char* prefix,
+                                     __android_log_pmsg_file_read_fn fn, void* arg) {
   ssize_t ret;
   struct android_log_logger_list logger_list;
   struct android_log_transport_context transp;
diff --git a/liblog/pmsg_writer.cpp b/liblog/pmsg_writer.cpp
index b2fc6d0..e851100 100644
--- a/liblog/pmsg_writer.cpp
+++ b/liblog/pmsg_writer.cpp
@@ -40,7 +40,7 @@
 static int pmsgAvailable(log_id_t logId);
 static int pmsgWrite(log_id_t logId, struct timespec* ts, struct iovec* vec, size_t nr);
 
-LIBLOG_HIDDEN struct android_log_transport_write pmsgLoggerWrite = {
+struct android_log_transport_write pmsgLoggerWrite = {
     .node = {&pmsgLoggerWrite.node, &pmsgLoggerWrite.node},
     .context.fd = -1,
     .name = "pmsg",
@@ -200,9 +200,8 @@
 }
 
 /* Write a buffer as filename references (tag = <basedir>:<basename>) */
-LIBLOG_ABI_PRIVATE ssize_t __android_log_pmsg_file_write(log_id_t logId, char prio,
-                                                         const char* filename, const char* buf,
-                                                         size_t len) {
+ssize_t __android_log_pmsg_file_write(log_id_t logId, char prio, const char* filename,
+                                      const char* buf, size_t len) {
   bool weOpened;
   size_t length, packet_len;
   const char* tag;
diff --git a/liblog/properties.cpp b/liblog/properties.cpp
index 764877e..2e0a8c9 100644
--- a/liblog/properties.cpp
+++ b/liblog/properties.cpp
@@ -264,18 +264,17 @@
   return default_prio;
 }
 
-LIBLOG_ABI_PUBLIC int __android_log_is_loggable_len(int prio, const char* tag, size_t len,
-                                                    int default_prio) {
+int __android_log_is_loggable_len(int prio, const char* tag, size_t len, int default_prio) {
   int logLevel = __android_log_level(tag, len, default_prio);
   return logLevel >= 0 && prio >= logLevel;
 }
 
-LIBLOG_ABI_PUBLIC int __android_log_is_loggable(int prio, const char* tag, int default_prio) {
+int __android_log_is_loggable(int prio, const char* tag, int default_prio) {
   int logLevel = __android_log_level(tag, (tag && *tag) ? strlen(tag) : 0, default_prio);
   return logLevel >= 0 && prio >= logLevel;
 }
 
-LIBLOG_ABI_PUBLIC int __android_log_is_debuggable() {
+int __android_log_is_debuggable() {
   static uint32_t serial;
   static struct cache_char tag_cache;
   static const char key[] = "ro.debuggable";
@@ -361,7 +360,7 @@
  * Timestamp state generally remains constant, but can change at any time
  * to handle developer requirements.
  */
-LIBLOG_ABI_PUBLIC clockid_t android_log_clockid() {
+clockid_t android_log_clockid() {
   static struct cache2_char clockid = {PTHREAD_MUTEX_INITIALIZER, 0,
                                        "persist.logd.timestamp",  {{NULL, 0xFFFFFFFF}, '\0'},
                                        "ro.logd.timestamp",       {{NULL, 0xFFFFFFFF}, '\0'},
@@ -380,7 +379,7 @@
   return (c != BOOLEAN_FALSE) && c && (self->cache_persist.c == BOOLEAN_TRUE);
 }
 
-LIBLOG_ABI_PUBLIC int __android_log_security() {
+int __android_log_security() {
   static struct cache2_char security = {
       PTHREAD_MUTEX_INITIALIZER, 0,
       "persist.logd.security",   {{NULL, 0xFFFFFFFF}, BOOLEAN_FALSE},
@@ -428,7 +427,7 @@
 }
 
 /* get boolean with the logger twist that supports eng adjustments */
-LIBLOG_ABI_PRIVATE bool __android_logger_property_get_bool(const char* key, int flag) {
+bool __android_logger_property_get_bool(const char* key, int flag) {
   struct cache_property property = {{NULL, 0xFFFFFFFF}, {0}};
   if (flag & BOOL_DEFAULT_FLAG_PERSIST) {
     char newkey[strlen("persist.") + strlen(key) + 1];
@@ -478,7 +477,7 @@
   return (flag & BOOL_DEFAULT_FLAG_TRUE_FALSE) != BOOL_DEFAULT_FALSE;
 }
 
-LIBLOG_ABI_PRIVATE bool __android_logger_valid_buffer_size(unsigned long value) {
+bool __android_logger_valid_buffer_size(unsigned long value) {
   static long pages, pagesize;
   unsigned long maximum;
 
@@ -583,7 +582,7 @@
   return property_get_size_from_cache(&self->cache_ro);
 }
 
-LIBLOG_ABI_PRIVATE unsigned long __android_logger_get_buffer_size(log_id_t logId) {
+unsigned long __android_logger_get_buffer_size(log_id_t logId) {
   static const char global_tunable[] = "persist.logd.size"; /* Settings App */
   static const char global_default[] = "ro.logd.size";      /* BoardConfig.mk */
   static struct cache2_property_size global = {
diff --git a/liblog/stderr_write.cpp b/liblog/stderr_write.cpp
index 28195aa..e324a7c 100644
--- a/liblog/stderr_write.cpp
+++ b/liblog/stderr_write.cpp
@@ -54,7 +54,7 @@
 #endif
 };
 
-LIBLOG_HIDDEN struct android_log_transport_write stderrLoggerWrite = {
+struct android_log_transport_write stderrLoggerWrite = {
     .node = {&stderrLoggerWrite.node, &stderrLoggerWrite.node},
     .context.priv = NULL,
     .name = "stderr",
diff --git a/libmeminfo/libdmabufinfo/Android.bp b/libmeminfo/libdmabufinfo/Android.bp
index 3d5f2e7..4aed45c 100644
--- a/libmeminfo/libdmabufinfo/Android.bp
+++ b/libmeminfo/libdmabufinfo/Android.bp
@@ -17,9 +17,11 @@
     name: "dmabufinfo_defaults",
     static_libs: [
         "libbase",
-        "liblog",
         "libprocinfo",
     ],
+    shared_libs: [
+        "liblog",
+    ],
 
     cflags: [
         "-Wall",
@@ -30,10 +32,9 @@
 
 cc_library_static {
     name: "libdmabufinfo",
+    vendor_available: true,
     defaults: ["dmabufinfo_defaults"],
     export_include_dirs: ["include"],
-    static_libs: ["libc++fs"],
-
     srcs: [
          "dmabufinfo.cpp",
     ],
diff --git a/libmeminfo/libdmabufinfo/dmabufinfo.cpp b/libmeminfo/libdmabufinfo/dmabufinfo.cpp
index b4ad667..439cf68 100644
--- a/libmeminfo/libdmabufinfo/dmabufinfo.cpp
+++ b/libmeminfo/libdmabufinfo/dmabufinfo.cpp
@@ -14,8 +14,7 @@
  * limitations under the License.
  */
 
-#include <dmabufinfo/dmabufinfo.h>
-
+#include <dirent.h>
 #include <inttypes.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -35,6 +34,8 @@
 #include <android-base/strings.h>
 #include <procinfo/process_map.h>
 
+#include <dmabufinfo/dmabufinfo.h>
+
 namespace android {
 namespace dmabufinfo {
 
@@ -80,16 +81,42 @@
     return true;
 }
 
+// TODO: std::filesystem::is_symlink fails to link on vendor code,
+// forcing this workaround.
+// Move back to libc++fs once it is vendor-available. See b/124012728
+static bool is_symlink(const char *filename)
+{
+    struct stat p_statbuf;
+    if (lstat(filename, &p_statbuf) < 0) {
+        return false;
+    }
+    if (S_ISLNK(p_statbuf.st_mode) == 1) {
+        return true;
+    }
+    return false;
+}
+
 static bool ReadDmaBufFdRefs(pid_t pid, std::vector<DmaBuffer>* dmabufs) {
     std::string fdpath = ::android::base::StringPrintf("/proc/%d/fd", pid);
-    for (auto& de : std::filesystem::directory_iterator(fdpath)) {
-        if (!std::filesystem::is_symlink(de.path())) {
+
+    std::unique_ptr<DIR, int (*)(DIR*)> dir(opendir(fdpath.c_str()), closedir);
+    if (!dir) {
+        LOG(ERROR) << "Failed to open " << fdpath << " directory" << std::endl;
+        return false;
+    }
+    struct dirent* dent;
+    while ((dent = readdir(dir.get()))) {
+        std::string path =
+            ::android::base::StringPrintf("%s/%s", fdpath.c_str(), dent->d_name);
+
+        if (!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, "..") ||
+            !is_symlink(path.c_str())) {
             continue;
         }
 
         std::string target;
-        if (!::android::base::Readlink(de.path().string(), &target)) {
-            LOG(ERROR) << "Failed to find target for symlink: " << de.path().string();
+        if (!::android::base::Readlink(path, &target)) {
+            LOG(ERROR) << "Failed to find target for symlink: " << path;
             return false;
         }
 
@@ -98,8 +125,8 @@
         }
 
         int fd;
-        if (!::android::base::ParseInt(de.path().filename().string(), &fd)) {
-            LOG(ERROR) << "Dmabuf fd: " << de.path().string() << " is invalid";
+        if (!::android::base::ParseInt(dent->d_name, &fd)) {
+            LOG(ERROR) << "Dmabuf fd: " << path << " is invalid";
             return false;
         }
 
@@ -109,13 +136,13 @@
         std::string exporter = "<unknown>";
         uint64_t count = 0;
         if (!ReadDmaBufFdInfo(pid, fd, &name, &exporter, &count)) {
-            LOG(ERROR) << "Failed to read fdinfo for: " << de.path().string();
+            LOG(ERROR) << "Failed to read fdinfo for: " << path;
             return false;
         }
 
         struct stat sb;
-        if (stat(de.path().c_str(), &sb) < 0) {
-            PLOG(ERROR) << "Failed to stat: " << de.path().string();
+        if (stat(path.c_str(), &sb) < 0) {
+            PLOG(ERROR) << "Failed to stat: " << path;
             return false;
         }
 
@@ -130,7 +157,7 @@
             if (buf->count() == 0)
                 buf->SetCount(count);
             buf->AddFdRef(pid);
-            return true;
+            continue;
         }
 
         DmaBuffer& db =
diff --git a/libmeminfo/libdmabufinfo/include/dmabufinfo/dmabufinfo.h b/libmeminfo/libdmabufinfo/include/dmabufinfo/dmabufinfo.h
index e3be320..a16c3fd 100644
--- a/libmeminfo/libdmabufinfo/include/dmabufinfo/dmabufinfo.h
+++ b/libmeminfo/libdmabufinfo/include/dmabufinfo/dmabufinfo.h
@@ -30,17 +30,21 @@
   public:
     DmaBuffer(ino_t inode, uint64_t size, uint64_t count, const std::string& exporter,
               const std::string& name)
-        : inode_(inode), size_(size), count_(count), exporter_(exporter), name_(name) {}
+        : inode_(inode), size_(size), count_(count), exporter_(exporter), name_(name) {
+        total_refs_ = 0;
+    }
     ~DmaBuffer() = default;
 
     // Adds one file descriptor reference for the given pid
     void AddFdRef(pid_t pid) {
         AddRefToPidMap(pid, &fdrefs_);
+        total_refs_++;
     }
 
     // Adds one map reference for the given pid
     void AddMapRef(pid_t pid) {
         AddRefToPidMap(pid, &maprefs_);
+        total_refs_++;
     }
 
     // Getters for each property
@@ -48,7 +52,7 @@
     const std::unordered_map<pid_t, int>& fdrefs() const { return fdrefs_; }
     const std::unordered_map<pid_t, int>& maprefs() const { return maprefs_; }
     ino_t inode() const { return inode_; }
-    uint64_t total_refs() const { return fdrefs_.size() + maprefs_.size(); }
+    uint64_t total_refs() const { return total_refs_; }
     uint64_t count() const { return count_; };
     const std::string& name() const { return name_; }
     const std::string& exporter() const { return exporter_; }
@@ -65,6 +69,7 @@
     ino_t inode_;
     uint64_t size_;
     uint64_t count_;
+    uint64_t total_refs_;
     std::string exporter_;
     std::string name_;
     std::unordered_map<pid_t, int> fdrefs_;
@@ -81,7 +86,6 @@
 // Read and return current dma buf objects from
 // DEBUGFS/dma_buf/bufinfo. The references to each dma buffer are not
 // populated here and will return an empty vector.
-//
 // Returns false if something went wrong with the function, true otherwise.
 bool ReadDmaBufInfo(std::vector<DmaBuffer>* dmabufs,
                     const std::string& path = "/sys/kernel/debug/dma_buf/bufinfo");
@@ -89,13 +93,13 @@
 
 // Read and return dmabuf objects for a given process without the help
 // of DEBUGFS
-//
 // Returns false if something went wrong with the function, true otherwise.
 bool ReadDmaBufInfo(pid_t pid, std::vector<DmaBuffer>* dmabufs);
 
-// Append dmabuf objects for a given process without the help
-// of DEBUGFS to an existing vector
-//
+// Append new dmabuf objects from a given process to an existing vector.
+// When the vector contains an existing element with a matching inode,
+// the reference counts will be updated.
+// Does not depend on DEBUGFS.
 // Returns false if something went wrong with the function, true otherwise.
 bool AppendDmaBufInfo(pid_t pid, std::vector<DmaBuffer>* dmabufs);
 
diff --git a/libmeminfo/libdmabufinfo/tools/Android.bp b/libmeminfo/libdmabufinfo/tools/Android.bp
new file mode 100644
index 0000000..0af3c48
--- /dev/null
+++ b/libmeminfo/libdmabufinfo/tools/Android.bp
@@ -0,0 +1,30 @@
+// Copyright (C) 2019 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: "dmabuf_dump",
+    cflags: [
+        "-Wall",
+        "-Werror",
+    ],
+
+    srcs: ["dmabuf_dump.cpp"],
+    shared_libs: [
+        "libbase",
+    ],
+    static_libs: [
+        "libdmabufinfo",
+    ],
+    soc_specific: true,
+}
\ No newline at end of file
diff --git a/libmeminfo/libdmabufinfo/tools/dmabuf_dump.cpp b/libmeminfo/libdmabufinfo/tools/dmabuf_dump.cpp
new file mode 100644
index 0000000..0851fb3
--- /dev/null
+++ b/libmeminfo/libdmabufinfo/tools/dmabuf_dump.cpp
@@ -0,0 +1,185 @@
+/*
+ * Copyright (C) 2019 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 <errno.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <iostream>
+#include <fstream>
+#include <sstream>
+#include <string>
+#include <vector>
+#include <map>
+#include <set>
+
+#include <android-base/stringprintf.h>
+#include <dmabufinfo/dmabufinfo.h>
+
+using DmaBuffer = ::android::dmabufinfo::DmaBuffer;
+
+[[noreturn]] static void usage(int exit_status) {
+    fprintf(stderr,
+            "Usage: %s [PID] \n"
+            "\t If PID is supplied, the dmabuf information for this process is shown.\n"
+            "\t Otherwise, shows the information for all processes.\n",
+            getprogname());
+
+    exit(exit_status);
+}
+
+static std::string GetProcessBaseName(pid_t pid) {
+    std::string pid_path = android::base::StringPrintf("/proc/%d/comm", pid);
+    std::ifstream in{pid_path};
+    if (!in) return std::string("N/A");
+    std::string line;
+    std::getline(in, line);
+    if (!in) return std::string("N/A");
+    return line;
+}
+
+static void AddPidsToSet(const std::unordered_map<pid_t, int>& map, std::set<pid_t>* set)
+{
+    for (auto it = map.begin(); it != map.end(); ++it)
+        set->insert(it->first);
+}
+
+static void PrintDmaBufInfo(const std::vector<DmaBuffer>& bufs) {
+    std::set<pid_t> pid_set;
+    std::map<pid_t, int> pid_column;
+
+    if (bufs.empty()) {
+        std::cout << "dmabuf info not found ¯\\_(ツ)_/¯" << std::endl;
+        return;
+    }
+
+    // Find all unique pids in the input vector, create a set
+    for (int i = 0; i < bufs.size(); i++) {
+        AddPidsToSet(bufs[i].fdrefs(), &pid_set);
+        AddPidsToSet(bufs[i].maprefs(), &pid_set);
+    }
+
+    int pid_count = 0;
+
+    std::cout << "\t\t\t\t\t\t";
+
+    // Create a map to convert each unique pid into a column number
+    for (auto it = pid_set.begin(); it != pid_set.end(); ++it, ++pid_count) {
+        pid_column.insert(std::make_pair(*it, pid_count));
+        std::cout << ::android::base::StringPrintf("[pid: % 4d]\t", *it);
+    }
+
+    std::cout << std::endl << "\t\t\t\t\t\t";
+
+    for (auto it = pid_set.begin(); it != pid_set.end(); ++it) {
+        std::cout << ::android::base::StringPrintf("%16s",
+            GetProcessBaseName(*it).c_str());
+    }
+
+    std::cout << std::endl << "\tinode\t\tsize\t\tcount\t";
+    for (int i = 0; i < pid_count; i++) {
+        std::cout << "fd\tmap\t";
+    }
+    std::cout << std::endl;
+
+    auto fds = std::make_unique<int[]>(pid_count);
+    auto maps = std::make_unique<int[]>(pid_count);
+    auto pss = std::make_unique<long[]>(pid_count);
+
+    memset(pss.get(), 0, sizeof(long) * pid_count);
+
+    for (auto buf = bufs.begin(); buf != bufs.end(); ++buf) {
+
+        std::cout << ::android::base::StringPrintf("%16lu\t%10" PRIu64 "\t%" PRIu64 "\t",
+            buf->inode(),buf->size(), buf->count());
+
+        memset(fds.get(), 0, sizeof(int) * pid_count);
+        memset(maps.get(), 0, sizeof(int) * pid_count);
+
+        for (auto it = buf->fdrefs().begin(); it != buf->fdrefs().end(); ++it) {
+            fds[pid_column[it->first]] = it->second;
+            pss[pid_column[it->first]] += buf->size() * it->second / buf->count();
+        }
+
+        for (auto it = buf->maprefs().begin(); it != buf->maprefs().end(); ++it) {
+            maps[pid_column[it->first]] = it->second;
+            pss[pid_column[it->first]] += buf->size() * it->second / buf->count();
+        }
+
+        for (int i = 0; i < pid_count; i++) {
+            std::cout << ::android::base::StringPrintf("%d\t%d\t", fds[i], maps[i]);
+        }
+        std::cout << std::endl;
+    }
+    std::cout << "-----------------------------------------" << std::endl;
+    std::cout << "PSS                                      ";
+    for (int i = 0; i < pid_count; i++) {
+        std::cout << ::android::base::StringPrintf("%15ldK", pss[i] / 1024);
+    }
+    std::cout << std::endl;
+}
+
+int main(int argc, char* argv[]) {
+    pid_t pid = -1;
+    std::vector<DmaBuffer> bufs;
+    bool show_all = true;
+
+    if (argc > 1) {
+        if (sscanf(argv[1], "%d", &pid) == 1) {
+            show_all = false;
+        }
+        else {
+            usage(EXIT_FAILURE);
+        }
+    }
+
+    if (show_all) {
+        if (!ReadDmaBufInfo(&bufs)) {
+            std::cerr << "debugfs entry for dmabuf not available, skipping" << std::endl;
+            bufs.clear();
+        }
+        std::unique_ptr<DIR, int (*)(DIR*)> dir(opendir("/proc"), closedir);
+        if (!dir) {
+            std::cerr << "Failed to open /proc directory" << std::endl;
+            exit(EXIT_FAILURE);
+        }
+        struct dirent* dent;
+        while ((dent = readdir(dir.get()))) {
+            if (dent->d_type != DT_DIR) continue;
+
+            int matched = sscanf(dent->d_name, "%d", &pid);
+            if (matched != 1) {
+                continue;
+            }
+
+            if (!AppendDmaBufInfo(pid, &bufs)) {
+                std::cerr << "Unable to read dmabuf info for pid " << pid << std::endl;
+                exit(EXIT_FAILURE);
+            }
+        }
+    } else {
+        if (!ReadDmaBufInfo(pid, &bufs)) {
+            std::cerr << "Unable to read dmabuf info" << std::endl;
+            exit(EXIT_FAILURE);
+        }
+    }
+    PrintDmaBufInfo(bufs);
+    return 0;
+}
+
+
diff --git a/libmeminfo/vts/Android.bp b/libmeminfo/vts/Android.bp
new file mode 100644
index 0000000..5a3a23b
--- /dev/null
+++ b/libmeminfo/vts/Android.bp
@@ -0,0 +1,20 @@
+// Copyright (C) 2019 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_test {
+    name: "vts_meminfo_test",
+    defaults: ["libmeminfo_defaults"],
+    srcs: ["vts_meminfo_test.cpp"],
+    static_libs: ["libmeminfo"],
+}
diff --git a/libmeminfo/vts/Android.mk b/libmeminfo/vts/Android.mk
new file mode 100644
index 0000000..62d68d9
--- /dev/null
+++ b/libmeminfo/vts/Android.mk
@@ -0,0 +1,22 @@
+#
+# Copyright (C) 2019 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)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := VtsKernelMemInfoTest
+-include test/vts/tools/build/Android.host_config.mk
diff --git a/libmeminfo/vts/AndroidTest.xml b/libmeminfo/vts/AndroidTest.xml
new file mode 100644
index 0000000..530d16e
--- /dev/null
+++ b/libmeminfo/vts/AndroidTest.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2019 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.
+-->
+<configuration description="Config for VTS VtsKernelMemInfoTest.">
+    <option name="config-descriptor:metadata" key="plan" value="vts-kernel" />
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.VtsFilePusher">
+        <option name="abort-on-push-failure" value="false"/>
+        <option name="push-group" value="HostDrivenTest.push"/>
+    </target_preparer>
+    <test class="com.android.tradefed.testtype.VtsMultiDeviceTest">
+        <option name="test-module-name" value="VtsKernelMemInfoTest"/>
+        <option name="binary-test-source" value="_32bit::DATA/nativetest/vts_meminfo_test/vts_meminfo_test" />
+        <option name="binary-test-source" value="_64bit::DATA/nativetest64/vts_meminfo_test/vts_meminfo_test" />
+        <option name="binary-test-type" value="gtest"/>
+        <option name="test-timeout" value="10m"/>
+    </test>
+</configuration>
diff --git a/libmeminfo/vts/vts_meminfo_test.cpp b/libmeminfo/vts/vts_meminfo_test.cpp
new file mode 100644
index 0000000..3193c31
--- /dev/null
+++ b/libmeminfo/vts/vts_meminfo_test.cpp
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2019 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 <gtest/gtest.h>
+
+#include <meminfo/procmeminfo.h>
+
+namespace android {
+namespace meminfo {
+
+// /proc/<pid>/smaps_rollup support is required.
+TEST(SmapsRollup, IsSupported) {
+    // Use init's pid for this test since it's the only known pid.
+    ASSERT_TRUE(IsSmapsRollupSupported(1));
+}
+
+}  // namespace meminfo
+}  // namespace android
diff --git a/libnativebridge/Android.bp b/libnativebridge/Android.bp
index c54570e..10d42e4 100644
--- a/libnativebridge/Android.bp
+++ b/libnativebridge/Android.bp
@@ -1,5 +1,18 @@
+cc_defaults {
+    name: "libnativebridge-defaults",
+    cflags: [
+        "-Werror",
+        "-Wall",
+    ],
+    cppflags: [
+        "-fvisibility=protected",
+    ],
+    header_libs: ["libnativebridge-headers"],
+    export_header_lib_headers: ["libnativebridge-headers"],
+}
+
 cc_library_headers {
-    name: "libnativebridge-dummy-headers",
+    name: "libnativebridge-headers",
 
     host_supported: true,
     export_include_dirs: ["include"],
@@ -7,6 +20,7 @@
 
 cc_library {
     name: "libnativebridge",
+    defaults: ["libnativebridge-defaults"],
 
     host_supported: true,
     srcs: ["native_bridge.cc"],
@@ -16,6 +30,8 @@
     shared_libs: [
         "liblog",
     ],
+    // TODO(jiyong): remove this line after aosp/885921 lands
+    export_include_dirs: ["include"],
 
     target: {
         android: {
@@ -30,16 +46,16 @@
         symbol_file: "libnativebridge.map.txt",
         versions: ["1"],
     },
+}
 
-    export_include_dirs: ["include"],
+// TODO(b/124250621): eliminate the need for this library
+cc_library {
+    name: "libnativebridge_lazy",
+    defaults: ["libnativebridge-defaults"],
 
-    cflags: [
-        "-Werror",
-        "-Wall",
-    ],
-    cppflags: [
-        "-fvisibility=protected",
-    ],
+    host_supported: false,
+    srcs: ["native_bridge_lazy.cc"],
+    required: ["libnativebridge"],
 }
 
 subdirs = ["tests"]
diff --git a/libnativebridge/native_bridge_lazy.cc b/libnativebridge/native_bridge_lazy.cc
new file mode 100644
index 0000000..94c8084
--- /dev/null
+++ b/libnativebridge/native_bridge_lazy.cc
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 2019 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 "nativebridge/native_bridge.h"
+#define LOG_TAG "nativebridge"
+
+#include <dlfcn.h>
+#include <errno.h>
+#include <string.h>
+
+#include <log/log.h>
+
+namespace android {
+
+namespace {
+
+void* GetLibHandle() {
+  static void* handle = dlopen("libnativebridge.so", RTLD_NOW);
+  LOG_FATAL_IF(handle == nullptr, "Failed to load libnativebridge.so: %s", dlerror());
+  return handle;
+}
+
+template <typename FuncPtr>
+FuncPtr GetFuncPtr(const char* function_name) {
+  auto f = reinterpret_cast<FuncPtr>(dlsym(GetLibHandle(), function_name));
+  LOG_FATAL_IF(f == nullptr, "Failed to get address of %s: %s", function_name, dlerror());
+  return f;
+}
+
+#define GET_FUNC_PTR(name) GetFuncPtr<decltype(&name)>(#name)
+
+}  // namespace
+
+bool LoadNativeBridge(const char* native_bridge_library_filename,
+                      const struct NativeBridgeRuntimeCallbacks* runtime_callbacks) {
+  static auto f = GET_FUNC_PTR(LoadNativeBridge);
+  return f(native_bridge_library_filename, runtime_callbacks);
+}
+
+bool NeedsNativeBridge(const char* instruction_set) {
+  static auto f = GET_FUNC_PTR(NeedsNativeBridge);
+  return f(instruction_set);
+}
+
+bool PreInitializeNativeBridge(const char* app_data_dir, const char* instruction_set) {
+  static auto f = GET_FUNC_PTR(PreInitializeNativeBridge);
+  return f(app_data_dir, instruction_set);
+}
+
+bool InitializeNativeBridge(JNIEnv* env, const char* instruction_set) {
+  static auto f = GET_FUNC_PTR(InitializeNativeBridge);
+  return f(env, instruction_set);
+}
+
+void UnloadNativeBridge() {
+  static auto f = GET_FUNC_PTR(UnloadNativeBridge);
+  return f();
+}
+
+bool NativeBridgeAvailable() {
+  static auto f = GET_FUNC_PTR(NativeBridgeAvailable);
+  return f();
+}
+
+bool NativeBridgeInitialized() {
+  static auto f = GET_FUNC_PTR(NativeBridgeInitialized);
+  return f();
+}
+
+void* NativeBridgeLoadLibrary(const char* libpath, int flag) {
+  static auto f = GET_FUNC_PTR(NativeBridgeLoadLibrary);
+  return f(libpath, flag);
+}
+
+void* NativeBridgeGetTrampoline(void* handle, const char* name, const char* shorty, uint32_t len) {
+  static auto f = GET_FUNC_PTR(NativeBridgeGetTrampoline);
+  return f(handle, name, shorty, len);
+}
+
+bool NativeBridgeIsSupported(const char* libpath) {
+  static auto f = GET_FUNC_PTR(NativeBridgeIsSupported);
+  return f(libpath);
+}
+
+uint32_t NativeBridgeGetVersion() {
+  static auto f = GET_FUNC_PTR(NativeBridgeGetVersion);
+  return f();
+}
+
+NativeBridgeSignalHandlerFn NativeBridgeGetSignalHandler(int signal) {
+  static auto f = GET_FUNC_PTR(NativeBridgeGetSignalHandler);
+  return f(signal);
+}
+
+bool NativeBridgeError() {
+  static auto f = GET_FUNC_PTR(NativeBridgeError);
+  return f();
+}
+
+bool NativeBridgeNameAcceptable(const char* native_bridge_library_filename) {
+  static auto f = GET_FUNC_PTR(NativeBridgeNameAcceptable);
+  return f(native_bridge_library_filename);
+}
+
+int NativeBridgeUnloadLibrary(void* handle) {
+  static auto f = GET_FUNC_PTR(NativeBridgeUnloadLibrary);
+  return f(handle);
+}
+
+const char* NativeBridgeGetError() {
+  static auto f = GET_FUNC_PTR(NativeBridgeGetError);
+  return f();
+}
+
+bool NativeBridgeIsPathSupported(const char* path) {
+  static auto f = GET_FUNC_PTR(NativeBridgeIsPathSupported);
+  return f(path);
+}
+
+bool NativeBridgeInitAnonymousNamespace(const char* public_ns_sonames,
+                                        const char* anon_ns_library_path) {
+  static auto f = GET_FUNC_PTR(NativeBridgeInitAnonymousNamespace);
+  return f(public_ns_sonames, anon_ns_library_path);
+}
+
+struct native_bridge_namespace_t* NativeBridgeCreateNamespace(
+    const char* name, const char* ld_library_path, const char* default_library_path, uint64_t type,
+    const char* permitted_when_isolated_path, struct native_bridge_namespace_t* parent_ns) {
+  static auto f = GET_FUNC_PTR(NativeBridgeCreateNamespace);
+  return f(name, ld_library_path, default_library_path, type, permitted_when_isolated_path,
+           parent_ns);
+}
+
+bool NativeBridgeLinkNamespaces(struct native_bridge_namespace_t* from,
+                                struct native_bridge_namespace_t* to,
+                                const char* shared_libs_sonames) {
+  static auto f = GET_FUNC_PTR(NativeBridgeLinkNamespaces);
+  return f(from, to, shared_libs_sonames);
+}
+
+void* NativeBridgeLoadLibraryExt(const char* libpath, int flag,
+                                 struct native_bridge_namespace_t* ns) {
+  static auto f = GET_FUNC_PTR(NativeBridgeLoadLibraryExt);
+  return f(libpath, flag, ns);
+}
+
+struct native_bridge_namespace_t* NativeBridgeGetVendorNamespace() {
+  static auto f = GET_FUNC_PTR(NativeBridgeGetVendorNamespace);
+  return f();
+}
+
+#undef GET_FUNC_PTR
+
+}  // namespace android
diff --git a/libnativebridge/tests/Android.bp b/libnativebridge/tests/Android.bp
index 744a4a8..2bb8467 100644
--- a/libnativebridge/tests/Android.bp
+++ b/libnativebridge/tests/Android.bp
@@ -23,7 +23,7 @@
         "-Wextra",
         "-Werror",
     ],
-    header_libs: ["libnativebridge-dummy-headers"],
+    header_libs: ["libnativebridge-headers"],
     cppflags: ["-fvisibility=protected"],
 }
 
@@ -46,9 +46,8 @@
 }
 
 // Build the unit tests.
-cc_test {
-    name: "libnativebridge-tests",
-    host_supported: true,
+cc_defaults {
+    name: "libnativebridge-tests-defaults",
     test_per_src: true,
 
     cflags: [
@@ -81,12 +80,24 @@
 
     shared_libs: [
         "liblog",
-        "libnativebridge",
         "libnativebridge-dummy",
     ],
     header_libs: ["libbase_headers"],
 }
 
+cc_test {
+    name: "libnativebridge-tests",
+    defaults: ["libnativebridge-tests-defaults"],
+    host_supported: true,
+    shared_libs: ["libnativebridge"],
+}
+
+cc_test {
+    name: "libnativebridge-lazy-tests",
+    defaults: ["libnativebridge-tests-defaults"],
+    shared_libs: ["libnativebridge_lazy"],
+}
+
 // Build the test for the C API.
 cc_test {
     name: "libnativebridge-api-tests",
@@ -95,5 +106,5 @@
     srcs: [
         "NativeBridgeApi.c",
     ],
-    header_libs: ["libnativebridge-dummy-headers"],
+    header_libs: ["libnativebridge-headers"],
 }
diff --git a/libnativeloader/Android.bp b/libnativeloader/Android.bp
index 2802d36..b806ae4 100644
--- a/libnativeloader/Android.bp
+++ b/libnativeloader/Android.bp
@@ -1,7 +1,21 @@
 // Shared library for target
 // ========================================================
+cc_defaults {
+    name: "libnativeloader-defaults",
+    cflags: [
+        "-Werror",
+        "-Wall",
+    ],
+    cppflags: [
+        "-fvisibility=hidden",
+    ],
+    header_libs: ["libnativeloader-headers"],
+    export_header_lib_headers: ["libnativeloader-headers"],
+}
+
 cc_library {
     name: "libnativeloader",
+    defaults: ["libnativeloader-defaults"],
     host_supported: true,
     srcs: ["native_loader.cpp"],
     shared_libs: [
@@ -11,23 +25,35 @@
         "libnativebridge",
         "libbase",
     ],
-    cflags: [
-        "-Werror",
-        "-Wall",
-    ],
-    cppflags: [
-        "-fvisibility=hidden",
-    ],
-    export_include_dirs: ["include"],
     required: [
         "llndk.libraries.txt",
         "vndksp.libraries.txt",
     ],
+    stubs: {
+        symbol_file: "libnativeloader.map.txt",
+        versions: ["1"],
+    },
+}
+
+// TODO(b/124250621) eliminate the need for this library
+cc_library {
+    name: "libnativeloader_lazy",
+    defaults: ["libnativeloader-defaults"],
+    host_supported: false,
+    srcs: ["native_loader_lazy.cpp"],
+    required: ["libnativeloader"],
 }
 
 cc_library_headers {
-    name: "libnativeloader-dummy-headers",
+    name: "libnativeloader-headers",
+    host_supported: true,
+    export_include_dirs: ["include"],
+}
 
+// TODO(jiyong) Remove this when its use in the internal master is
+// switched to libnativeloader-headers
+cc_library_headers {
+    name: "libnativeloader-dummy-headers",
     host_supported: true,
     export_include_dirs: ["include"],
 }
diff --git a/libnativeloader/native_loader.cpp b/libnativeloader/native_loader.cpp
index a4e00bd..5394d7e 100644
--- a/libnativeloader/native_loader.cpp
+++ b/libnativeloader/native_loader.cpp
@@ -118,7 +118,16 @@
 
 static constexpr const char* kRuntimeNamespaceName = "runtime";
 
+// classloader-namespace is a linker namespace that is created for the loaded
+// app. To be specific, it is created for the app classloader. When
+// System.load() is called from a Java class that is loaded from the
+// classloader, the classloader-namespace namespace associated with that
+// classloader is selected for dlopen. The namespace is configured so that its
+// search path is set to the app-local JNI directory and it is linked to the
+// default namespace with the names of libs listed in the public.libraries.txt.
+// This way an app can only load its own JNI libraries along with the public libs.
 static constexpr const char* kClassloaderNamespaceName = "classloader-namespace";
+// Same thing for vendor APKs.
 static constexpr const char* kVendorClassloaderNamespaceName = "vendor-classloader-namespace";
 
 // (http://b/27588281) This is a workaround for apps using custom classloaders and calling
diff --git a/libnativeloader/native_loader_lazy.cpp b/libnativeloader/native_loader_lazy.cpp
new file mode 100644
index 0000000..11ecc43
--- /dev/null
+++ b/libnativeloader/native_loader_lazy.cpp
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2019 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 "nativeloader/native_loader.h"
+#define LOG_TAG "nativeloader"
+
+#include <dlfcn.h>
+#include <errno.h>
+#include <string.h>
+
+#include <log/log.h>
+
+namespace android {
+
+namespace {
+
+void* GetLibHandle() {
+  static void* handle = dlopen("libnativeloader.so", RTLD_NOW);
+  LOG_FATAL_IF(handle == nullptr, "Failed to load libnativeloader.so: %s", dlerror());
+  return handle;
+}
+
+template <typename FuncPtr>
+FuncPtr GetFuncPtr(const char* function_name) {
+  auto f = reinterpret_cast<FuncPtr>(dlsym(GetLibHandle(), function_name));
+  LOG_FATAL_IF(f == nullptr, "Failed to get address of %s: %s", function_name, dlerror());
+  return f;
+}
+
+#define GET_FUNC_PTR(name) GetFuncPtr<decltype(&name)>(#name)
+
+}  // namespace
+
+void InitializeNativeLoader() {
+  static auto f = GET_FUNC_PTR(InitializeNativeLoader);
+  return f();
+}
+
+jstring CreateClassLoaderNamespace(JNIEnv* env, int32_t target_sdk_version, jobject class_loader,
+                                   bool is_shared, bool is_for_vendor, jstring library_path,
+                                   jstring permitted_path) {
+  static auto f = GET_FUNC_PTR(CreateClassLoaderNamespace);
+  return f(env, target_sdk_version, class_loader, is_shared, is_for_vendor, library_path,
+           permitted_path);
+}
+
+void* OpenNativeLibrary(JNIEnv* env, int32_t target_sdk_version, const char* path,
+                        jobject class_loader, const char* caller_location, jstring library_path,
+                        bool* needs_native_bridge, char** error_msg) {
+  static auto f = GET_FUNC_PTR(OpenNativeLibrary);
+  return f(env, target_sdk_version, path, class_loader, caller_location, library_path,
+           needs_native_bridge, error_msg);
+}
+
+bool CloseNativeLibrary(void* handle, const bool needs_native_bridge, char** error_msg) {
+  static auto f = GET_FUNC_PTR(CloseNativeLibrary);
+  return f(handle, needs_native_bridge, error_msg);
+}
+
+void NativeLoaderFreeErrorMessage(char* msg) {
+  static auto f = GET_FUNC_PTR(NativeLoaderFreeErrorMessage);
+  return f(msg);
+}
+
+struct android_namespace_t* FindNamespaceByClassLoader(JNIEnv* env, jobject class_loader) {
+  static auto f = GET_FUNC_PTR(FindNamespaceByClassLoader);
+  return f(env, class_loader);
+}
+
+struct NativeLoaderNamespace* FindNativeLoaderNamespaceByClassLoader(JNIEnv* env,
+                                                                     jobject class_loader) {
+  static auto f = GET_FUNC_PTR(FindNativeLoaderNamespaceByClassLoader);
+  return f(env, class_loader);
+}
+
+void* OpenNativeLibraryInNamespace(struct NativeLoaderNamespace* ns, const char* path,
+                                   bool* needs_native_bridge, char** error_msg) {
+  static auto f = GET_FUNC_PTR(OpenNativeLibraryInNamespace);
+  return f(ns, path, needs_native_bridge, error_msg);
+}
+
+void ResetNativeLoader() {
+  static auto f = GET_FUNC_PTR(ResetNativeLoader);
+  return f();
+}
+
+#undef GET_FUNC_PTR
+
+}  // namespace android
diff --git a/libnativeloader/test/Android.bp b/libnativeloader/test/Android.bp
index 1464e39..4d5c53d 100644
--- a/libnativeloader/test/Android.bp
+++ b/libnativeloader/test/Android.bp
@@ -78,5 +78,5 @@
     srcs: [
         "api_test.c",
     ],
-    header_libs: ["libnativeloader-dummy-headers"],
+    header_libs: ["libnativeloader-headers"],
 }
diff --git a/libnetutils/OWNERS b/libnetutils/OWNERS
index e3ec950..8321de6 100644
--- a/libnetutils/OWNERS
+++ b/libnetutils/OWNERS
@@ -1,3 +1,2 @@
-# TODO: should this be in system/netd?
-ek@google.com
-lorenzo@google.com
+include platform/system/netd:/OWNERS
+
diff --git a/libpixelflinger/tests/Android.bp b/libpixelflinger/tests/Android.bp
index 820a84d..e20dd93 100644
--- a/libpixelflinger/tests/Android.bp
+++ b/libpixelflinger/tests/Android.bp
@@ -8,6 +8,7 @@
 
     header_libs: ["libpixelflinger_internal"],
     static_libs: [
+        "libbase",
         "libcutils",
         "liblog",
         "libpixelflinger",
diff --git a/libprocessgroup/cgroup_map.cpp b/libprocessgroup/cgroup_map.cpp
index 12cfb7e..cd8ef94 100644
--- a/libprocessgroup/cgroup_map.cpp
+++ b/libprocessgroup/cgroup_map.cpp
@@ -19,6 +19,7 @@
 
 #include <errno.h>
 #include <fcntl.h>
+#include <grp.h>
 #include <pwd.h>
 #include <sys/mman.h>
 #include <sys/mount.h>
@@ -72,26 +73,28 @@
         }
     }
 
-    passwd* uid_pwd = nullptr;
-    passwd* gid_pwd = nullptr;
-
-    if (!uid.empty()) {
-        uid_pwd = getpwnam(uid.c_str());
-        if (!uid_pwd) {
-            PLOG(ERROR) << "Unable to decode UID for '" << uid << "'";
-            return false;
-        }
-
-        if (!gid.empty()) {
-            gid_pwd = getpwnam(gid.c_str());
-            if (!gid_pwd) {
-                PLOG(ERROR) << "Unable to decode GID for '" << gid << "'";
-                return false;
-            }
-        }
+    if (uid.empty()) {
+        return true;
     }
 
-    if (uid_pwd && lchown(path.c_str(), uid_pwd->pw_uid, gid_pwd ? gid_pwd->pw_uid : -1) < 0) {
+    passwd* uid_pwd = getpwnam(uid.c_str());
+    if (!uid_pwd) {
+        PLOG(ERROR) << "Unable to decode UID for '" << uid << "'";
+        return false;
+    }
+
+    uid_t pw_uid = uid_pwd->pw_uid;
+    gid_t gr_gid = -1;
+    if (!gid.empty()) {
+        group* gid_pwd = getgrnam(gid.c_str());
+        if (!gid_pwd) {
+            PLOG(ERROR) << "Unable to decode GID for '" << gid << "'";
+            return false;
+        }
+        gr_gid = gid_pwd->gr_gid;
+    }
+
+    if (lchown(path.c_str(), pw_uid, gr_gid) < 0) {
         PLOG(ERROR) << "lchown() failed for " << path;
         return false;
     }
@@ -128,7 +131,8 @@
         std::string name = cgroups[i]["Controller"].asString();
         descriptors->emplace(std::make_pair(
                 name,
-                CgroupDescriptor(1, name, cgroups[i]["Path"].asString(), cgroups[i]["Mode"].asInt(),
+                CgroupDescriptor(1, name, cgroups[i]["Path"].asString(),
+                                 std::strtoul(cgroups[i]["Mode"].asString().c_str(), 0, 8),
                                  cgroups[i]["UID"].asString(), cgroups[i]["GID"].asString())));
     }
 
@@ -136,8 +140,8 @@
     descriptors->emplace(std::make_pair(
             CGROUPV2_CONTROLLER_NAME,
             CgroupDescriptor(2, CGROUPV2_CONTROLLER_NAME, cgroups2["Path"].asString(),
-                             cgroups2["Mode"].asInt(), cgroups2["UID"].asString(),
-                             cgroups2["GID"].asString())));
+                             std::strtoul(cgroups2["Mode"].asString().c_str(), 0, 8),
+                             cgroups2["UID"].asString(), cgroups2["GID"].asString())));
 
     return true;
 }
diff --git a/libprocessgroup/task_profiles.cpp b/libprocessgroup/task_profiles.cpp
index ec6cbbc..447852d 100644
--- a/libprocessgroup/task_profiles.cpp
+++ b/libprocessgroup/task_profiles.cpp
@@ -132,6 +132,7 @@
 
 SetCgroupAction::SetCgroupAction(const CgroupController* c, const std::string& p)
     : controller_(c), path_(p) {
+#ifdef CACHE_FILE_DESCRIPTORS
     // cache file descriptor only if path is app independent
     if (IsAppDependentPath(path_)) {
         // file descriptor is not cached
@@ -155,6 +156,7 @@
     }
 
     fd_ = std::move(fd);
+#endif
 }
 
 bool SetCgroupAction::AddTidToCgroup(int tid, int fd) {
@@ -176,6 +178,7 @@
 }
 
 bool SetCgroupAction::ExecuteForProcess(uid_t uid, pid_t pid) const {
+#ifdef CACHE_FILE_DESCRIPTORS
     if (fd_ >= 0) {
         // fd is cached, reuse it
         if (!AddTidToCgroup(pid, fd_)) {
@@ -203,9 +206,24 @@
     }
 
     return true;
+#else
+    std::string procs_path = controller_->GetProcsFilePath(path_.c_str(), uid, pid);
+    unique_fd tmp_fd(TEMP_FAILURE_RETRY(open(procs_path.c_str(), O_WRONLY | O_CLOEXEC)));
+    if (tmp_fd < 0) {
+        // no permissions to access the file, ignore
+        return true;
+    }
+    if (!AddTidToCgroup(pid, tmp_fd)) {
+        PLOG(ERROR) << "Failed to add task into cgroup";
+        return false;
+    }
+
+    return true;
+#endif
 }
 
 bool SetCgroupAction::ExecuteForTask(int tid) const {
+#ifdef CACHE_FILE_DESCRIPTORS
     if (fd_ >= 0) {
         // fd is cached, reuse it
         if (!AddTidToCgroup(tid, fd_)) {
@@ -223,6 +241,20 @@
     // application-dependent path can't be used with tid
     PLOG(ERROR) << "Application profile can't be applied to a thread";
     return false;
+#else
+    std::string tasks_path = controller_->GetTasksFilePath(path_.c_str());
+    unique_fd tmp_fd(TEMP_FAILURE_RETRY(open(tasks_path.c_str(), O_WRONLY | O_CLOEXEC)));
+    if (tmp_fd < 0) {
+        // no permissions to access the file, ignore
+        return true;
+    }
+    if (!AddTidToCgroup(tid, tmp_fd)) {
+        PLOG(ERROR) << "Failed to add task into cgroup";
+        return false;
+    }
+
+    return true;
+#endif
 }
 
 bool TaskProfile::ExecuteForProcess(uid_t uid, pid_t pid) const {
diff --git a/libprocessgroup/task_profiles.h b/libprocessgroup/task_profiles.h
index 83e74b2..b2e39f9 100644
--- a/libprocessgroup/task_profiles.h
+++ b/libprocessgroup/task_profiles.h
@@ -117,7 +117,9 @@
   private:
     const CgroupController* controller_;
     std::string path_;
+#ifdef CACHE_FILE_DESCRIPTORS
     android::base::unique_fd fd_;
+#endif
 
     static bool IsAppDependentPath(const std::string& path);
     static bool AddTidToCgroup(int tid, int fd);
diff --git a/libsystem/OWNERS b/libsystem/OWNERS
index aeb160c..fdea804 100644
--- a/libsystem/OWNERS
+++ b/libsystem/OWNERS
@@ -1,2 +1,9 @@
-jessehall@google.com
-olv@google.com
+# graphics/composer
+adyabr@google.com
+lpy@google.com
+marissaw@google.com
+stoza@google.com
+vhau@google.com
+
+# camera
+etalvala@google.com
diff --git a/libutils/Android.bp b/libutils/Android.bp
index fb7ca32..93aa1e6 100644
--- a/libutils/Android.bp
+++ b/libutils/Android.bp
@@ -195,17 +195,83 @@
     },
 }
 
-// Include subdirectory makefiles
-// ============================================================
-
 cc_test {
-    name: "SharedBufferTest",
+    name: "libutils_test",
     host_supported: true,
-    static_libs: ["libutils"],
-    shared_libs: ["liblog"],
-    srcs: ["SharedBufferTest.cpp"],
+
+    srcs: [
+        "BitSet_test.cpp",
+        "FileMap_test.cpp",
+        "LruCache_test.cpp",
+        "Mutex_test.cpp",
+        "SharedBuffer_test.cpp",
+        "Singleton_test.cpp",
+        "String8_test.cpp",
+        "StrongPointer_test.cpp",
+        "Unicode_test.cpp",
+        "Vector_test.cpp",
+    ],
+
+    target: {
+        android: {
+            srcs: [
+                "SystemClock_test.cpp",
+            ],
+            shared_libs: [
+                "libz",
+                "liblog",
+                "libcutils",
+                "libutils",
+                "libbase",
+            ],
+        },
+        linux: {
+            srcs: [
+                "Looper_test.cpp",
+                "RefBase_test.cpp",
+            ],
+        },
+        host: {
+            static_libs: [
+                "libutils",
+                "liblog",
+                "libbase",
+            ],
+        },
+    },
+
+    required: [
+        "libutils_test_singleton1",
+        "libutils_test_singleton2",
+    ],
+
+    cflags: [
+        "-Wall",
+        "-Wextra",
+        "-Werror",
+        "-Wthread-safety",
+    ],
+}
+
+cc_test_library {
+    name: "libutils_test_singleton1",
+    host_supported: true,
+    relative_install_path: "libutils_test",
+    srcs: ["Singleton_test1.cpp"],
     cflags: [
         "-Wall",
         "-Werror",
     ],
 }
+
+cc_test_library {
+    name: "libutils_test_singleton2",
+    host_supported: true,
+    relative_install_path: "libutils_test",
+    srcs: ["Singleton_test2.cpp"],
+    cflags: [
+        "-Wall",
+        "-Werror",
+    ],
+    shared_libs: ["libutils_test_singleton1"],
+}
diff --git a/libutils/tests/BitSet_test.cpp b/libutils/BitSet_test.cpp
similarity index 100%
rename from libutils/tests/BitSet_test.cpp
rename to libutils/BitSet_test.cpp
diff --git a/libutils/FileMap.cpp b/libutils/FileMap.cpp
index 5feb2aa..1202c15 100644
--- a/libutils/FileMap.cpp
+++ b/libutils/FileMap.cpp
@@ -174,12 +174,6 @@
         return false;
     }
 #else // !defined(__MINGW32__)
-    int     prot, flags, adjust;
-    off64_t adjOffset;
-    size_t  adjLength;
-
-    void* ptr;
-
     assert(fd >= 0);
     assert(offset >= 0);
     assert(length > 0);
@@ -193,20 +187,23 @@
         }
     }
 
-    adjust = offset % mPageSize;
-    adjOffset = offset - adjust;
-    adjLength = length + adjust;
+    int adjust = offset % mPageSize;
+    off64_t adjOffset = offset - adjust;
+    size_t adjLength = length + adjust;
 
-    flags = MAP_SHARED;
-    prot = PROT_READ;
-    if (!readOnly)
-        prot |= PROT_WRITE;
+    int flags = MAP_SHARED;
+    int prot = PROT_READ;
+    if (!readOnly) prot |= PROT_WRITE;
 
-    ptr = mmap(nullptr, adjLength, prot, flags, fd, adjOffset);
+    void* ptr = mmap(nullptr, adjLength, prot, flags, fd, adjOffset);
     if (ptr == MAP_FAILED) {
-        ALOGE("mmap(%lld,%zu) failed: %s\n",
-            (long long)adjOffset, adjLength, strerror(errno));
-        return false;
+        if (errno == EINVAL && length == 0) {
+            ptr = nullptr;
+            adjust = 0;
+        } else {
+            ALOGE("mmap(%lld,%zu) failed: %s\n", (long long)adjOffset, adjLength, strerror(errno));
+            return false;
+        }
     }
     mBasePtr = ptr;
 #endif // !defined(__MINGW32__)
@@ -217,8 +214,6 @@
     mDataPtr = (char*) mBasePtr + adjust;
     mDataLength = length;
 
-    assert(mBasePtr != NULL);
-
     ALOGV("MAP: base %p/%zu data %p/%zu\n",
         mBasePtr, mBaseLength, mDataPtr, mDataLength);
 
diff --git a/libutils/FileMap_test.cpp b/libutils/FileMap_test.cpp
new file mode 100644
index 0000000..576d89b
--- /dev/null
+++ b/libutils/FileMap_test.cpp
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2019 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 "utils/FileMap.h"
+
+#include <gtest/gtest.h>
+
+#include "android-base/file.h"
+
+TEST(FileMap, zero_length_mapping) {
+    // http://b/119818070 "app crashes when reading asset of zero length".
+    // mmap fails with EINVAL for a zero length region.
+    TemporaryFile tf;
+    ASSERT_TRUE(tf.fd != -1);
+
+    android::FileMap m;
+    ASSERT_TRUE(m.create("test", tf.fd, 4096, 0, true));
+    ASSERT_STREQ("test", m.getFileName());
+    ASSERT_EQ(0u, m.getDataLength());
+    ASSERT_EQ(4096, m.getDataOffset());
+}
diff --git a/libutils/tests/Looper_test.cpp b/libutils/Looper_test.cpp
similarity index 96%
rename from libutils/tests/Looper_test.cpp
rename to libutils/Looper_test.cpp
index 2282ced..6fdc0ed 100644
--- a/libutils/tests/Looper_test.cpp
+++ b/libutils/Looper_test.cpp
@@ -9,7 +9,7 @@
 #include <unistd.h>
 #include <time.h>
 
-#include "TestHelpers.h"
+#include <utils/threads.h>
 
 // # of milliseconds to fudge stopwatch measurements
 #define TIMING_TOLERANCE_MS 25
@@ -23,6 +23,59 @@
     MSG_TEST4 = 4,
 };
 
+class Pipe {
+public:
+    int sendFd;
+    int receiveFd;
+
+    Pipe() {
+        int fds[2];
+        ::pipe(fds);
+
+        receiveFd = fds[0];
+        sendFd = fds[1];
+    }
+
+    ~Pipe() {
+        if (sendFd != -1) {
+            ::close(sendFd);
+        }
+
+        if (receiveFd != -1) {
+            ::close(receiveFd);
+        }
+    }
+
+    status_t writeSignal() {
+        ssize_t nWritten = ::write(sendFd, "*", 1);
+        return nWritten == 1 ? 0 : -errno;
+    }
+
+    status_t readSignal() {
+        char buf[1];
+        ssize_t nRead = ::read(receiveFd, buf, 1);
+        return nRead == 1 ? 0 : nRead == 0 ? -EPIPE : -errno;
+    }
+};
+
+class DelayedTask : public Thread {
+    int mDelayMillis;
+
+public:
+    explicit DelayedTask(int delayMillis) : mDelayMillis(delayMillis) { }
+
+protected:
+    virtual ~DelayedTask() { }
+
+    virtual void doTask() = 0;
+
+    virtual bool threadLoop() {
+        usleep(mDelayMillis * 1000);
+        doTask();
+        return false;
+    }
+};
+
 class DelayedWake : public DelayedTask {
     sp<Looper> mLooper;
 
diff --git a/libutils/tests/LruCache_test.cpp b/libutils/LruCache_test.cpp
similarity index 100%
rename from libutils/tests/LruCache_test.cpp
rename to libutils/LruCache_test.cpp
diff --git a/libutils/tests/Mutex_test.cpp b/libutils/Mutex_test.cpp
similarity index 100%
rename from libutils/tests/Mutex_test.cpp
rename to libutils/Mutex_test.cpp
diff --git a/libutils/tests/RefBase_test.cpp b/libutils/RefBase_test.cpp
similarity index 100%
rename from libutils/tests/RefBase_test.cpp
rename to libutils/RefBase_test.cpp
diff --git a/libutils/SharedBufferTest.cpp b/libutils/SharedBuffer_test.cpp
similarity index 100%
rename from libutils/SharedBufferTest.cpp
rename to libutils/SharedBuffer_test.cpp
diff --git a/libutils/tests/Singleton_test.cpp b/libutils/Singleton_test.cpp
similarity index 88%
rename from libutils/tests/Singleton_test.cpp
rename to libutils/Singleton_test.cpp
index 9acd3c3..61084b0 100644
--- a/libutils/tests/Singleton_test.cpp
+++ b/libutils/Singleton_test.cpp
@@ -30,15 +30,15 @@
 
 TEST(SingletonTest, bug35674422) {
     std::string path = android::base::GetExecutableDirectory();
-    // libutils_tests_singleton1.so contains the ANDROID_SINGLETON_STATIC_INSTANCE
+    // libutils_test_singleton1.so contains the ANDROID_SINGLETON_STATIC_INSTANCE
     // definition of SingletonTestData, load it first.
-    std::string lib = android::base::StringPrintf("%s/libutils_tests_singleton1.so", path.c_str());
+    std::string lib = android::base::StringPrintf("%s/libutils_test_singleton1.so", path.c_str());
     void* handle1 = dlopen(lib.c_str(), RTLD_NOW);
     ASSERT_TRUE(handle1 != nullptr) << dlerror();
 
-    // libutils_tests_singleton2.so references SingletonTestData but should not
+    // libutils_test_singleton2.so references SingletonTestData but should not
     // have a definition
-    lib = android::base::StringPrintf("%s/libutils_tests_singleton2.so", path.c_str());
+    lib = android::base::StringPrintf("%s/libutils_test_singleton2.so", path.c_str());
     void* handle2 = dlopen(lib.c_str(), RTLD_NOW);
     ASSERT_TRUE(handle2 != nullptr) << dlerror();
 
diff --git a/libutils/tests/Singleton_test.h b/libutils/Singleton_test.h
similarity index 100%
rename from libutils/tests/Singleton_test.h
rename to libutils/Singleton_test.h
diff --git a/libutils/tests/Singleton_test1.cpp b/libutils/Singleton_test1.cpp
similarity index 100%
rename from libutils/tests/Singleton_test1.cpp
rename to libutils/Singleton_test1.cpp
diff --git a/libutils/tests/Singleton_test2.cpp b/libutils/Singleton_test2.cpp
similarity index 100%
rename from libutils/tests/Singleton_test2.cpp
rename to libutils/Singleton_test2.cpp
diff --git a/libutils/tests/String8_test.cpp b/libutils/String8_test.cpp
similarity index 100%
rename from libutils/tests/String8_test.cpp
rename to libutils/String8_test.cpp
diff --git a/libutils/tests/StrongPointer_test.cpp b/libutils/StrongPointer_test.cpp
similarity index 100%
rename from libutils/tests/StrongPointer_test.cpp
rename to libutils/StrongPointer_test.cpp
diff --git a/libutils/tests/SystemClock_test.cpp b/libutils/SystemClock_test.cpp
similarity index 100%
rename from libutils/tests/SystemClock_test.cpp
rename to libutils/SystemClock_test.cpp
diff --git a/libutils/tests/Unicode_test.cpp b/libutils/Unicode_test.cpp
similarity index 100%
rename from libutils/tests/Unicode_test.cpp
rename to libutils/Unicode_test.cpp
diff --git a/libutils/tests/Vector_test.cpp b/libutils/Vector_test.cpp
similarity index 100%
rename from libutils/tests/Vector_test.cpp
rename to libutils/Vector_test.cpp
diff --git a/libutils/tests/Android.bp b/libutils/tests/Android.bp
deleted file mode 100644
index 1390552..0000000
--- a/libutils/tests/Android.bp
+++ /dev/null
@@ -1,96 +0,0 @@
-//
-// Copyright (C) 2014 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.
-//
-
-// Build the unit tests.
-
-cc_test {
-    name: "libutils_tests",
-    host_supported: true,
-
-    srcs: [
-        "BitSet_test.cpp",
-        "LruCache_test.cpp",
-        "Mutex_test.cpp",
-        "Singleton_test.cpp",
-        "String8_test.cpp",
-        "StrongPointer_test.cpp",
-        "Unicode_test.cpp",
-        "Vector_test.cpp",
-    ],
-
-    target: {
-        android: {
-            srcs: [
-                "SystemClock_test.cpp",
-            ],
-            shared_libs: [
-                "libz",
-                "liblog",
-                "libcutils",
-                "libutils",
-                "libbase",
-            ],
-        },
-        linux: {
-            srcs: [
-                "Looper_test.cpp",
-                "RefBase_test.cpp",
-            ],
-        },
-        host: {
-            static_libs: [
-                "libutils",
-                "liblog",
-                "libbase",
-            ],
-        },
-    },
-
-    required: [
-        "libutils_tests_singleton1",
-        "libutils_tests_singleton2",
-    ],
-
-    cflags: [
-        "-Wall",
-        "-Wextra",
-        "-Werror",
-        "-Wthread-safety",
-    ],
-}
-
-cc_test_library {
-    name: "libutils_tests_singleton1",
-    host_supported: true,
-    relative_install_path: "libutils_tests",
-    srcs: ["Singleton_test1.cpp"],
-    cflags: [
-        "-Wall",
-        "-Werror",
-    ],
-}
-
-cc_test_library {
-    name: "libutils_tests_singleton2",
-    host_supported: true,
-    relative_install_path: "libutils_tests",
-    srcs: ["Singleton_test2.cpp"],
-    cflags: [
-        "-Wall",
-        "-Werror",
-    ],
-    shared_libs: ["libutils_tests_singleton1"],
-}
diff --git a/libutils/tests/README.txt b/libutils/tests/README.txt
deleted file mode 100644
index ad54e57..0000000
--- a/libutils/tests/README.txt
+++ /dev/null
@@ -1,8 +0,0 @@
-Run device tests:
-
-mma -j<whatever>
-(after adb root; adb disable-verity; adb reboot)
-adb root
-adb remount
-adb sync
-adb shell /data/nativetest/libutils_tests/libutils_tests
diff --git a/libutils/tests/TestHelpers.h b/libutils/tests/TestHelpers.h
deleted file mode 100644
index 6801cd7..0000000
--- a/libutils/tests/TestHelpers.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (C) 2010 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 TESTHELPERS_H
-#define TESTHELPERS_H
-
-#include <utils/threads.h>
-
-namespace android {
-
-class Pipe {
-public:
-    int sendFd;
-    int receiveFd;
-
-    Pipe() {
-        int fds[2];
-        ::pipe(fds);
-
-        receiveFd = fds[0];
-        sendFd = fds[1];
-    }
-
-    ~Pipe() {
-        if (sendFd != -1) {
-            ::close(sendFd);
-        }
-
-        if (receiveFd != -1) {
-            ::close(receiveFd);
-        }
-    }
-
-    status_t writeSignal() {
-        ssize_t nWritten = ::write(sendFd, "*", 1);
-        return nWritten == 1 ? 0 : -errno;
-    }
-
-    status_t readSignal() {
-        char buf[1];
-        ssize_t nRead = ::read(receiveFd, buf, 1);
-        return nRead == 1 ? 0 : nRead == 0 ? -EPIPE : -errno;
-    }
-};
-
-class DelayedTask : public Thread {
-    int mDelayMillis;
-
-public:
-    explicit DelayedTask(int delayMillis) : mDelayMillis(delayMillis) { }
-
-protected:
-    virtual ~DelayedTask() { }
-
-    virtual void doTask() = 0;
-
-    virtual bool threadLoop() {
-        usleep(mDelayMillis * 1000);
-        doTask();
-        return false;
-    }
-};
-
-} // namespace android
-
-#endif // TESTHELPERS_H
diff --git a/libvndksupport/Android.bp b/libvndksupport/Android.bp
index e73b366..bfa2508 100644
--- a/libvndksupport/Android.bp
+++ b/libvndksupport/Android.bp
@@ -10,6 +10,11 @@
     local_include_dirs: ["include/vndksupport"],
     export_include_dirs: ["include"],
     shared_libs: ["liblog"],
+    version_script: "libvndksupport.map.txt",
+    stubs: {
+        symbol_file: "libvndksupport.map.txt",
+        versions: ["29"],
+    },
 }
 
 llndk_library {
diff --git a/libvndksupport/libvndksupport.map.txt b/libvndksupport/libvndksupport.map.txt
index 16e38da..d3db10f 100644
--- a/libvndksupport/libvndksupport.map.txt
+++ b/libvndksupport/libvndksupport.map.txt
@@ -1,7 +1,7 @@
 LIBVNDKSUPPORT {
   global:
-    android_load_sphal_library; # vndk
-    android_unload_sphal_library; # vndk
+    android_load_sphal_library; # vndk apex
+    android_unload_sphal_library; # vndk apex
   local:
     *;
 };
diff --git a/rootdir/cgroups.json b/rootdir/cgroups.json
index 6eb88c9..aa71956 100644
--- a/rootdir/cgroups.json
+++ b/rootdir/cgroups.json
@@ -3,40 +3,40 @@
     {
       "Controller": "cpu",
       "Path": "/dev/cpuctl",
-      "Mode": 0755,
+      "Mode": "0755",
       "UID": "system",
       "GID": "system"
     },
     {
       "Controller": "cpuacct",
       "Path": "/acct",
-      "Mode": 0555
+      "Mode": "0555"
     },
     {
       "Controller": "cpuset",
       "Path": "/dev/cpuset",
-      "Mode": 0755,
+      "Mode": "0755",
       "UID": "system",
       "GID": "system"
     },
     {
       "Controller": "memory",
       "Path": "/dev/memcg",
-      "Mode": 0700,
+      "Mode": "0700",
       "UID": "root",
       "GID": "system"
     },
     {
       "Controller": "schedtune",
       "Path": "/dev/stune",
-      "Mode": 0755,
+      "Mode": "0755",
       "UID": "system",
       "GID": "system"
     }
   ],
   "Cgroups2": {
     "Path": "/dev/cg2_bpf",
-    "Mode": 0600,
+    "Mode": "0600",
     "UID": "root",
     "GID": "root"
   }
diff --git a/rootdir/etc/ld.config.legacy.txt b/rootdir/etc/ld.config.legacy.txt
index 48ca998..e897d81 100644
--- a/rootdir/etc/ld.config.legacy.txt
+++ b/rootdir/etc/ld.config.legacy.txt
@@ -126,6 +126,7 @@
 namespace.resolv.link.default.shared_libs += libm.so
 namespace.resolv.link.default.shared_libs += libdl.so
 namespace.resolv.link.default.shared_libs += libbinder_ndk.so
+namespace.resolv.link.default.shared_libs += libvndksupport.so
 
 ###############################################################################
 # Namespace config for binaries under /postinstall.
diff --git a/rootdir/etc/ld.config.txt b/rootdir/etc/ld.config.txt
index 7aa097d..5e2d79c 100644
--- a/rootdir/etc/ld.config.txt
+++ b/rootdir/etc/ld.config.txt
@@ -200,6 +200,7 @@
 namespace.resolv.link.default.shared_libs += libm.so
 namespace.resolv.link.default.shared_libs += libdl.so
 namespace.resolv.link.default.shared_libs += libbinder_ndk.so
+namespace.resolv.link.default.shared_libs += libvndksupport.so
 
 ###############################################################################
 # "sphal" namespace
@@ -408,6 +409,7 @@
 
 # Keep in sync with ld.config.txt in the com.android.runtime APEX.
 namespace.runtime.search.paths = /apex/com.android.runtime/${LIB}
+namespace.runtime.asan.search.paths = /apex/com.android.runtime/${LIB}
 namespace.runtime.links = system
 # TODO(b/119867084): Restrict to Bionic dlopen dependencies and PALette library
 # when it exists.
diff --git a/rootdir/etc/ld.config.vndk_lite.txt b/rootdir/etc/ld.config.vndk_lite.txt
index 1904445..3c97a49 100644
--- a/rootdir/etc/ld.config.vndk_lite.txt
+++ b/rootdir/etc/ld.config.vndk_lite.txt
@@ -145,6 +145,7 @@
 namespace.resolv.link.default.shared_libs += libm.so
 namespace.resolv.link.default.shared_libs += libdl.so
 namespace.resolv.link.default.shared_libs += libbinder_ndk.so
+namespace.resolv.link.default.shared_libs += libvndksupport.so
 
 ###############################################################################
 # "sphal" namespace
@@ -305,11 +306,11 @@
 namespace.default.search.paths += /vendor/${LIB}/vndk-sp
 
 # Access to system libraries is allowed
-namespace.default.search.paths += /system/${LIB}/vndk%VNDK_VER%
 namespace.default.search.paths += /system/${LIB}/vndk-sp%VNDK_VER%
 namespace.default.search.paths += /system/${LIB}
 namespace.default.search.paths += /%PRODUCT%/${LIB}
 namespace.default.search.paths += /%PRODUCT_SERVICES%/${LIB}
+namespace.default.search.paths += /system/${LIB}/vndk%VNDK_VER%
 
 namespace.default.asan.search.paths  = /data/asan/odm/${LIB}
 namespace.default.asan.search.paths +=           /odm/${LIB}
@@ -323,8 +324,6 @@
 namespace.default.asan.search.paths +=           /vendor/${LIB}/vndk
 namespace.default.asan.search.paths += /data/asan/vendor/${LIB}/vndk-sp
 namespace.default.asan.search.paths +=           /vendor/${LIB}/vndk-sp
-namespace.default.asan.search.paths += /data/asan/system/${LIB}/vndk%VNDK_VER%
-namespace.default.asan.search.paths +=           /system/${LIB}/vndk%VNDK_VER%
 namespace.default.asan.search.paths += /data/asan/system/${LIB}/vndk-sp%VNDK_VER%
 namespace.default.asan.search.paths +=           /system/${LIB}/vndk-sp%VNDK_VER%
 namespace.default.asan.search.paths += /data/asan/system/${LIB}
@@ -333,6 +332,8 @@
 namespace.default.asan.search.paths +=           /%PRODUCT%/${LIB}
 namespace.default.asan.search.paths += /data/asan/product_services/${LIB}
 namespace.default.asan.search.paths +=           /%PRODUCT_SERVICES%/${LIB}
+namespace.default.asan.search.paths += /data/asan/system/${LIB}/vndk%VNDK_VER%
+namespace.default.asan.search.paths +=           /system/${LIB}/vndk%VNDK_VER%
 
 namespace.default.links = runtime
 namespace.default.link.runtime.shared_libs  = libdexfile_external.so
@@ -349,6 +350,7 @@
 
 # Keep in sync with ld.config.txt in the com.android.runtime APEX.
 namespace.runtime.search.paths = /apex/com.android.runtime/${LIB}
+namespace.runtime.asan.search.paths = /apex/com.android.runtime/${LIB}
 namespace.runtime.links = default
 # TODO(b/119867084): Restrict to Bionic dlopen dependencies and PALette library
 # when it exists.
diff --git a/rootdir/init.rc b/rootdir/init.rc
index c6e2116..57032bc 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -277,6 +277,10 @@
 
     # Start logd before any other services run to ensure we capture all of their logs.
     start logd
+
+    # Start apexd as soon as we can
+    start apexd
+
     # Start essential services.
     start servicemanager
     start hwservicemanager
@@ -412,8 +416,8 @@
     mkdir /data/bootchart 0755 shell shell
     bootchart start
 
-    # Start apexd as soon as we can
-    start apexd
+    # /data/apex is now available. Let apexd to scan and activate APEXes.
+    setprop apexd.data.status ready
 
     # Avoid predictable entropy pool. Carry over entropy from previous boot.
     copy /data/system/entropy.dat /dev/urandom
@@ -531,6 +535,9 @@
     mkdir /data/anr 0775 system system
 
     mkdir /data/apex 0750 root system
+    mkdir /data/apex/active 0750 root system
+    mkdir /data/apex/backup 0700 root system
+    mkdir /data/apex/sessions 0700 root system
     mkdir /data/staging 0750 system system
 
     # NFC: create data/nfc for nv storage
@@ -590,6 +597,11 @@
     # Set indication (checked by vold) that we have finished this action
     #setprop vold.post_fs_data_done 1
 
+    # sys.memfd_use set to false by default, which keeps it disabled
+    # until it is confirmed that apps and vendor processes don't make
+    # IOCTLs on ashmem fds any more.
+    setprop sys.use_memfd false
+
 # It is recommended to put unnecessary data/ initialization from post-fs-data
 # to start-zygote in device's init.rc to unblock zygote start.
 on zygote-start && property:ro.crypto.state=unencrypted