Merge changes from topic "base_cmsg"

* changes:
  adb: switch to base::{Send,Receive}FileDescriptors.
  debuggerd: switch to base::{Send,Receive}FileDescriptors.
  base: add helpers for sending/receiving file descriptors.
diff --git a/TEST_MAPPING b/TEST_MAPPING
index cc85408..716378b 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -10,6 +10,9 @@
       "name": "fs_mgr_unit_test"
     },
     {
+      "name": "fs_mgr_vendor_overlay_test"
+    },
+    {
       "name": "init_tests"
     },
     {
diff --git a/adb/daemon/usb.cpp b/adb/daemon/usb.cpp
index f603d13..f0e2861 100644
--- a/adb/daemon/usb.cpp
+++ b/adb/daemon/usb.cpp
@@ -53,6 +53,9 @@
 
 using android::base::StringPrintf;
 
+// We can't find out whether we have support for AIO on ffs endpoints until we submit a read.
+static std::optional<bool> gFfsAioSupported;
+
 static constexpr size_t kUsbReadQueueDepth = 16;
 static constexpr size_t kUsbReadSize = 16384;
 
@@ -169,8 +172,13 @@
           read_fd_(std::move(read)),
           write_fd_(std::move(write)) {
         LOG(INFO) << "UsbFfsConnection constructed";
-        event_fd_.reset(eventfd(0, EFD_CLOEXEC));
-        if (event_fd_ == -1) {
+        worker_event_fd_.reset(eventfd(0, EFD_CLOEXEC));
+        if (worker_event_fd_ == -1) {
+            PLOG(FATAL) << "failed to create eventfd";
+        }
+
+        monitor_event_fd_.reset(eventfd(0, EFD_CLOEXEC));
+        if (monitor_event_fd_ == -1) {
             PLOG(FATAL) << "failed to create eventfd";
         }
 
@@ -181,6 +189,13 @@
         LOG(INFO) << "UsbFfsConnection being destroyed";
         Stop();
         monitor_thread_.join();
+
+        // We need to explicitly close our file descriptors before we notify our destruction,
+        // because the thread listening on the future will immediately try to reopen the endpoint.
+        control_fd_.reset();
+        read_fd_.reset();
+        write_fd_.reset();
+
         destruction_notifier_.set_value();
     }
 
@@ -207,11 +222,18 @@
         }
         stopped_ = true;
         uint64_t notify = 1;
-        ssize_t rc = adb_write(event_fd_.get(), &notify, sizeof(notify));
+        ssize_t rc = adb_write(worker_event_fd_.get(), &notify, sizeof(notify));
         if (rc < 0) {
-            PLOG(FATAL) << "failed to notify eventfd to stop UsbFfsConnection";
+            PLOG(FATAL) << "failed to notify worker eventfd to stop UsbFfsConnection";
         }
         CHECK_EQ(static_cast<size_t>(rc), sizeof(notify));
+
+        rc = adb_write(monitor_event_fd_.get(), &notify, sizeof(notify));
+        if (rc < 0) {
+            PLOG(FATAL) << "failed to notify monitor eventfd to stop UsbFfsConnection";
+        }
+
+        CHECK_EQ(static_cast<size_t>(rc), sizeof(notify));
     }
 
   private:
@@ -235,22 +257,33 @@
             bool started = false;
             bool running = true;
             while (running) {
+                int timeout = -1;
                 if (!bound || !started) {
-                    adb_pollfd pfd = {.fd = control_fd_.get(), .events = POLLIN, .revents = 0};
-                    int rc = TEMP_FAILURE_RETRY(adb_poll(&pfd, 1, 5000 /*ms*/));
-                    if (rc == -1) {
-                        PLOG(FATAL) << "poll on USB control fd failed";
-                    } else if (rc == 0) {
-                        // Something in the kernel presumably went wrong.
-                        // Close our endpoints, wait for a bit, and then try again.
-                        aio_context_.reset();
-                        read_fd_.reset();
-                        write_fd_.reset();
-                        control_fd_.reset();
-                        std::this_thread::sleep_for(5s);
-                        HandleError("didn't receive FUNCTIONFS_ENABLE, retrying");
-                        return;
-                    }
+                    timeout = 5000 /*ms*/;
+                }
+
+                adb_pollfd pfd[2] = {
+                  { .fd = control_fd_.get(), .events = POLLIN, .revents = 0 },
+                  { .fd = monitor_event_fd_.get(), .events = POLLIN, .revents = 0 },
+                };
+                int rc = TEMP_FAILURE_RETRY(adb_poll(pfd, 2, timeout));
+                if (rc == -1) {
+                    PLOG(FATAL) << "poll on USB control fd failed";
+                } else if (rc == 0) {
+                    // Something in the kernel presumably went wrong.
+                    // Close our endpoints, wait for a bit, and then try again.
+                    aio_context_.reset();
+                    read_fd_.reset();
+                    write_fd_.reset();
+                    control_fd_.reset();
+                    std::this_thread::sleep_for(5s);
+                    HandleError("didn't receive FUNCTIONFS_ENABLE, retrying");
+                    return;
+                }
+
+                if (pfd[1].revents) {
+                    // We were told to die.
+                    break;
                 }
 
                 struct usb_functionfs_event event;
@@ -313,12 +346,14 @@
             adb_thread_setname("UsbFfs-worker");
             for (size_t i = 0; i < kUsbReadQueueDepth; ++i) {
                 read_requests_[i] = CreateReadBlock(next_read_id_++);
-                SubmitRead(&read_requests_[i]);
+                if (!SubmitRead(&read_requests_[i])) {
+                    return;
+                }
             }
 
             while (!stopped_) {
                 uint64_t dummy;
-                ssize_t rc = adb_read(event_fd_.get(), &dummy, sizeof(dummy));
+                ssize_t rc = adb_read(worker_event_fd_.get(), &dummy, sizeof(dummy));
                 if (rc == -1) {
                     PLOG(FATAL) << "failed to read from eventfd";
                 } else if (rc == 0) {
@@ -347,7 +382,7 @@
         block.control.aio_fildes = read_fd_.get();
         block.control.aio_offset = 0;
         block.control.aio_flags = IOCB_FLAG_RESFD;
-        block.control.aio_resfd = event_fd_.get();
+        block.control.aio_resfd = worker_event_fd_.get();
         return block;
     }
 
@@ -438,13 +473,22 @@
         SubmitRead(block);
     }
 
-    void SubmitRead(IoBlock* block) {
+    bool SubmitRead(IoBlock* block) {
         block->pending = true;
         struct iocb* iocb = &block->control;
         if (io_submit(aio_context_.get(), 1, &iocb) != 1) {
+            if (errno == EINVAL && !gFfsAioSupported.has_value()) {
+                HandleError("failed to submit first read, AIO on FFS not supported");
+                gFfsAioSupported = false;
+                return false;
+            }
+
             HandleError(StringPrintf("failed to submit read: %s", strerror(errno)));
-            return;
+            return false;
         }
+
+        gFfsAioSupported = true;
+        return true;
     }
 
     void HandleWrite(TransferId id) {
@@ -474,7 +518,7 @@
         block->control.aio_nbytes = block->payload.size();
         block->control.aio_offset = 0;
         block->control.aio_flags = IOCB_FLAG_RESFD;
-        block->control.aio_resfd = event_fd_.get();
+        block->control.aio_resfd = worker_event_fd_.get();
         return block;
     }
 
@@ -526,7 +570,8 @@
     std::promise<void> destruction_notifier_;
     std::once_flag error_flag_;
 
-    unique_fd event_fd_;
+    unique_fd worker_event_fd_;
+    unique_fd monitor_event_fd_;
 
     ScopedAioContext aio_context_;
     unique_fd control_fd_;
@@ -551,10 +596,17 @@
     size_t writes_submitted_ GUARDED_BY(write_mutex_) = 0;
 };
 
+void usb_init_legacy();
+
 static void usb_ffs_open_thread() {
     adb_thread_setname("usb ffs open");
 
     while (true) {
+        if (gFfsAioSupported.has_value() && !gFfsAioSupported.value()) {
+            LOG(INFO) << "failed to use nonblocking ffs, falling back to legacy";
+            return usb_init_legacy();
+        }
+
         unique_fd control;
         unique_fd bulk_out;
         unique_fd bulk_in;
@@ -575,7 +627,6 @@
     }
 }
 
-void usb_init_legacy();
 void usb_init() {
     if (!android::base::GetBoolProperty("persist.adb.nonblocking_ffs", false)) {
         usb_init_legacy();
diff --git a/adb/transport.cpp b/adb/transport.cpp
index ae53597..90f94ee 100644
--- a/adb/transport.cpp
+++ b/adb/transport.cpp
@@ -52,6 +52,8 @@
 #include "fdevent.h"
 #include "sysdeps/chrono.h"
 
+using android::base::ScopedLockAssertion;
+
 static void remove_transport(atransport* transport);
 static void transport_unref(atransport* transport);
 
@@ -72,17 +74,6 @@
 
 namespace {
 
-// A class that helps the Clang Thread Safety Analysis deal with
-// std::unique_lock. Given that std::unique_lock is movable, and the analysis
-// can not currently perform alias analysis, it is not annotated. In order to
-// assert that the mutex is held, a ScopedAssumeLocked can be created just after
-// the std::unique_lock.
-class SCOPED_CAPABILITY ScopedAssumeLocked {
-  public:
-    ScopedAssumeLocked(std::mutex& mutex) ACQUIRE(mutex) {}
-    ~ScopedAssumeLocked() RELEASE() {}
-};
-
 #if ADB_HOST
 // Tracks and handles atransport*s that are attempting reconnection.
 class ReconnectHandler {
@@ -180,7 +171,7 @@
         ReconnectAttempt attempt;
         {
             std::unique_lock<std::mutex> lock(reconnect_mutex_);
-            ScopedAssumeLocked assume_lock(reconnect_mutex_);
+            ScopedLockAssertion assume_lock(reconnect_mutex_);
 
             if (!reconnect_queue_.empty()) {
                 // FIXME: libstdc++ (used on Windows) implements condition_variable with
@@ -296,7 +287,7 @@
         LOG(INFO) << this->transport_name_ << ": write thread spawning";
         while (true) {
             std::unique_lock<std::mutex> lock(mutex_);
-            ScopedAssumeLocked assume_locked(mutex_);
+            ScopedLockAssertion assume_locked(mutex_);
             cv_.wait(lock, [this]() REQUIRES(mutex_) {
                 return this->stopped_ || !this->write_queue_.empty();
             });
@@ -923,7 +914,7 @@
 
 bool ConnectionWaitable::WaitForConnection(std::chrono::milliseconds timeout) {
     std::unique_lock<std::mutex> lock(mutex_);
-    ScopedAssumeLocked assume_locked(mutex_);
+    ScopedLockAssertion assume_locked(mutex_);
     return cv_.wait_for(lock, timeout, [&]() REQUIRES(mutex_) {
         return connection_established_ready_;
     }) && connection_established_;
diff --git a/base/include/android-base/thread_annotations.h b/base/include/android-base/thread_annotations.h
index 5c55e63..53fe6da 100644
--- a/base/include/android-base/thread_annotations.h
+++ b/base/include/android-base/thread_annotations.h
@@ -16,6 +16,8 @@
 
 #pragma once
 
+#include <mutex>
+
 #define THREAD_ANNOTATION_ATTRIBUTE__(x) __attribute__((x))
 
 #define CAPABILITY(x) \
@@ -104,3 +106,39 @@
 
 #define NO_THREAD_SAFETY_ANALYSIS \
       THREAD_ANNOTATION_ATTRIBUTE__(no_thread_safety_analysis)
+
+namespace android {
+namespace base {
+
+// A class to help thread safety analysis deal with std::unique_lock and condition_variable.
+//
+// Clang's thread safety analysis currently doesn't perform alias analysis, so movable types
+// like std::unique_lock can't be marked with thread safety annotations. This helper allows
+// for manual assertion of lock state in a scope.
+//
+// For example:
+//
+//   std::mutex mutex;
+//   std::condition_variable cv;
+//   std::vector<int> vec GUARDED_BY(mutex);
+//
+//   int pop() {
+//     std::unique_lock lock(mutex);
+//     ScopedLockAssertion lock_assertion(mutex);
+//     cv.wait(lock, []() {
+//       ScopedLockAssertion lock_assertion(mutex);
+//       return !vec.empty();
+//     });
+//
+//     int result = vec.back();
+//     vec.pop_back();
+//     return result;
+//   }
+class SCOPED_CAPABILITY ScopedLockAssertion {
+ public:
+  ScopedLockAssertion(std::mutex& mutex) ACQUIRE(mutex) {}
+  ~ScopedLockAssertion() RELEASE() {}
+};
+
+}  // namespace base
+}  // namespace android
diff --git a/debuggerd/Android.bp b/debuggerd/Android.bp
index 4a53a33..76c5ade 100644
--- a/debuggerd/Android.bp
+++ b/debuggerd/Android.bp
@@ -115,19 +115,14 @@
         "libbase",
         "libdebuggerd",
         "libunwindstack",
-        "libdexfile",  // libunwindstack dependency
-        "libdexfile_external",  // libunwindstack dependency
-        "libdexfile_support",  // libunwindstack dependency
+        "libdexfile_support_static",  // libunwindstack dependency
         "liblzma",
         "libcutils",
     ],
     target: {
         recovery: {
             exclude_static_libs: [
-                "libartbase",
-                "libdexfile",
-                "libdexfile_external",
-                "libdexfile_support",
+                "libdexfile_support_static",
             ],
         },
     },
@@ -174,8 +169,7 @@
     include_dirs: ["bionic/libc"],
 
     static_libs: [
-        "libdexfile_external",  // libunwindstack dependency
-        "libdexfile_support",  // libunwindstack dependency
+        "libdexfile_support_static",  // libunwindstack dependency
         "libunwindstack",
         "liblzma",
         "libbase",
@@ -185,8 +179,7 @@
     target: {
         recovery: {
             exclude_static_libs: [
-                "libdexfile_external",
-                "libdexfile_support",
+                "libdexfile_support_static",
             ],
         },
     },
diff --git a/adf/Android.bp b/deprecated-adf/Android.bp
similarity index 100%
rename from adf/Android.bp
rename to deprecated-adf/Android.bp
diff --git a/adf/OWNERS b/deprecated-adf/OWNERS
similarity index 100%
rename from adf/OWNERS
rename to deprecated-adf/OWNERS
diff --git a/adf/libadf/Android.bp b/deprecated-adf/libadf/Android.bp
similarity index 100%
rename from adf/libadf/Android.bp
rename to deprecated-adf/libadf/Android.bp
diff --git a/adf/libadf/adf.cpp b/deprecated-adf/libadf/adf.cpp
similarity index 100%
rename from adf/libadf/adf.cpp
rename to deprecated-adf/libadf/adf.cpp
diff --git a/adf/libadf/include/adf/adf.h b/deprecated-adf/libadf/include/adf/adf.h
similarity index 100%
rename from adf/libadf/include/adf/adf.h
rename to deprecated-adf/libadf/include/adf/adf.h
diff --git a/adf/libadf/include/video/adf.h b/deprecated-adf/libadf/include/video/adf.h
similarity index 100%
rename from adf/libadf/include/video/adf.h
rename to deprecated-adf/libadf/include/video/adf.h
diff --git a/adf/libadf/original-kernel-headers/video/adf.h b/deprecated-adf/libadf/original-kernel-headers/video/adf.h
similarity index 100%
rename from adf/libadf/original-kernel-headers/video/adf.h
rename to deprecated-adf/libadf/original-kernel-headers/video/adf.h
diff --git a/adf/libadf/tests/Android.bp b/deprecated-adf/libadf/tests/Android.bp
similarity index 100%
rename from adf/libadf/tests/Android.bp
rename to deprecated-adf/libadf/tests/Android.bp
diff --git a/adf/libadf/tests/adf_test.cpp b/deprecated-adf/libadf/tests/adf_test.cpp
similarity index 100%
rename from adf/libadf/tests/adf_test.cpp
rename to deprecated-adf/libadf/tests/adf_test.cpp
diff --git a/adf/libadfhwc/Android.bp b/deprecated-adf/libadfhwc/Android.bp
similarity index 100%
rename from adf/libadfhwc/Android.bp
rename to deprecated-adf/libadfhwc/Android.bp
diff --git a/adf/libadfhwc/adfhwc.cpp b/deprecated-adf/libadfhwc/adfhwc.cpp
similarity index 100%
rename from adf/libadfhwc/adfhwc.cpp
rename to deprecated-adf/libadfhwc/adfhwc.cpp
diff --git a/adf/libadfhwc/include/adfhwc/adfhwc.h b/deprecated-adf/libadfhwc/include/adfhwc/adfhwc.h
similarity index 100%
rename from adf/libadfhwc/include/adfhwc/adfhwc.h
rename to deprecated-adf/libadfhwc/include/adfhwc/adfhwc.h
diff --git a/fs_mgr/fs_mgr_fstab.cpp b/fs_mgr/fs_mgr_fstab.cpp
index 4d44fcf..4659add 100644
--- a/fs_mgr/fs_mgr_fstab.cpp
+++ b/fs_mgr/fs_mgr_fstab.cpp
@@ -588,18 +588,7 @@
     return boot_devices;
 }
 
-void EraseFstabEntry(Fstab* fstab, const std::string& mount_point) {
-    auto iter = std::remove_if(fstab->begin(), fstab->end(),
-                               [&](const auto& entry) { return entry.mount_point == mount_point; });
-    fstab->erase(iter, fstab->end());
-}
-
-void TransformFstabForGsi(Fstab* fstab) {
-    EraseFstabEntry(fstab, "/system");
-    EraseFstabEntry(fstab, "/data");
-
-    fstab->emplace_back(BuildGsiSystemFstabEntry());
-
+FstabEntry BuildGsiUserdataFstabEntry() {
     constexpr uint32_t kFlags = MS_NOATIME | MS_NOSUID | MS_NODEV;
 
     FstabEntry userdata = {
@@ -615,6 +604,34 @@
     userdata.fs_mgr_flags.quota = true;
     userdata.fs_mgr_flags.late_mount = true;
     userdata.fs_mgr_flags.formattable = true;
+    return userdata;
+}
+
+void EraseFstabEntry(Fstab* fstab, const std::string& mount_point) {
+    auto iter = std::remove_if(fstab->begin(), fstab->end(),
+                               [&](const auto& entry) { return entry.mount_point == mount_point; });
+    fstab->erase(iter, fstab->end());
+}
+
+void TransformFstabForGsi(Fstab* fstab) {
+    // Inherit fstab properties for userdata.
+    FstabEntry userdata;
+    if (FstabEntry* entry = GetEntryForMountPoint(fstab, "/data")) {
+        userdata = *entry;
+        userdata.blk_device = "userdata_gsi";
+        userdata.fs_mgr_flags.logical = true;
+        userdata.fs_mgr_flags.formattable = true;
+        if (!userdata.key_dir.empty()) {
+            userdata.key_dir += "/gsi";
+        }
+    } else {
+        userdata = BuildGsiUserdataFstabEntry();
+    }
+
+    EraseFstabEntry(fstab, "/system");
+    EraseFstabEntry(fstab, "/data");
+
+    fstab->emplace_back(BuildGsiSystemFstabEntry());
     fstab->emplace_back(userdata);
 }
 
diff --git a/fs_mgr/fs_mgr_overlayfs.cpp b/fs_mgr/fs_mgr_overlayfs.cpp
index 87729cd..9364b2d 100644
--- a/fs_mgr/fs_mgr_overlayfs.cpp
+++ b/fs_mgr/fs_mgr_overlayfs.cpp
@@ -78,6 +78,10 @@
 
 #if ALLOW_ADBD_DISABLE_VERITY == 0  // If we are a user build, provide stubs
 
+Fstab fs_mgr_overlayfs_candidate_list(const Fstab&) {
+    return {};
+}
+
 bool fs_mgr_overlayfs_mount_all(Fstab*) {
     return false;
 }
@@ -238,8 +242,7 @@
     return ret;
 }
 
-const char* fs_mgr_mount_point(const char* mount_point) {
-    if (!mount_point) return mount_point;
+const std::string fs_mgr_mount_point(const std::string& mount_point) {
     if ("/"s != mount_point) return mount_point;
     return "/system";
 }
@@ -526,40 +529,6 @@
     }
 }
 
-std::vector<std::string> fs_mgr_candidate_list(Fstab* fstab, const char* mount_point = nullptr) {
-    std::vector<std::string> mounts;
-    for (auto& entry : *fstab) {
-        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) ||
-                (android::base::StartsWith(new_mount_point, *it + "/"))) {
-                duplicate_or_more_specific = true;
-                break;
-            }
-            if (android::base::StartsWith(*it, new_mount_point + "/")) {
-                it = mounts.erase(it);
-            } else {
-                ++it;
-            }
-        }
-        if (!duplicate_or_more_specific) mounts.emplace_back(new_mount_point);
-    }
-
-    return mounts;
-}
-
 // Mount kScratchMountPoint
 bool fs_mgr_overlayfs_mount_scratch(const std::string& device_path, const std::string mnt_type,
                                     bool readonly = false) {
@@ -802,12 +771,42 @@
 
 }  // namespace
 
+Fstab fs_mgr_overlayfs_candidate_list(const Fstab& fstab) {
+    Fstab candidates;
+    for (const auto& entry : fstab) {
+        FstabEntry new_entry = entry;
+        if (!fs_mgr_overlayfs_already_mounted(entry.mount_point) &&
+            !fs_mgr_wants_overlayfs(&new_entry)) {
+            continue;
+        }
+        auto new_mount_point = fs_mgr_mount_point(entry.mount_point);
+        auto duplicate_or_more_specific = false;
+        for (auto it = candidates.begin(); it != candidates.end();) {
+            auto it_mount_point = fs_mgr_mount_point(it->mount_point);
+            if ((it_mount_point == new_mount_point) ||
+                (android::base::StartsWith(new_mount_point, it_mount_point + "/"))) {
+                duplicate_or_more_specific = true;
+                break;
+            }
+            if (android::base::StartsWith(it_mount_point, new_mount_point + "/")) {
+                it = candidates.erase(it);
+            } else {
+                ++it;
+            }
+        }
+        if (!duplicate_or_more_specific) candidates.emplace_back(std::move(new_entry));
+    }
+    return candidates;
+}
+
 bool fs_mgr_overlayfs_mount_all(Fstab* fstab) {
     auto ret = false;
     if (fs_mgr_overlayfs_invalid()) return ret;
 
     auto scratch_can_be_mounted = true;
-    for (const auto& mount_point : fs_mgr_candidate_list(fstab)) {
+    for (const auto& entry : fs_mgr_overlayfs_candidate_list(*fstab)) {
+        if (fs_mgr_is_verity_enabled(entry)) continue;
+        auto mount_point = fs_mgr_mount_point(entry.mount_point);
         if (fs_mgr_overlayfs_already_mounted(mount_point)) {
             ret = true;
             continue;
@@ -840,8 +839,9 @@
         return {};
     }
 
-    for (const auto& mount_point : fs_mgr_candidate_list(fstab)) {
-        if (fs_mgr_overlayfs_already_mounted(mount_point)) continue;
+    for (const auto& entry : fs_mgr_overlayfs_candidate_list(*fstab)) {
+        if (fs_mgr_is_verity_enabled(entry)) continue;
+        if (fs_mgr_overlayfs_already_mounted(fs_mgr_mount_point(entry.mount_point))) continue;
         auto device = fs_mgr_overlayfs_scratch_device();
         if (!fs_mgr_overlayfs_scratch_can_be_mounted(device)) break;
         return {device};
@@ -867,8 +867,24 @@
         return false;
     }
     errno = save_errno;
-    auto mounts = fs_mgr_candidate_list(&fstab, fs_mgr_mount_point(mount_point));
-    if (mounts.empty()) return ret;
+    auto candidates = fs_mgr_overlayfs_candidate_list(fstab);
+    for (auto it = candidates.begin(); it != candidates.end();) {
+        if (mount_point &&
+            (fs_mgr_mount_point(it->mount_point) != fs_mgr_mount_point(mount_point))) {
+            it = candidates.erase(it);
+            continue;
+        }
+        save_errno = errno;
+        auto verity_enabled = fs_mgr_is_verity_enabled(*it);
+        if (errno == ENOENT || errno == ENXIO) errno = save_errno;
+        if (verity_enabled) {
+            it = candidates.erase(it);
+            continue;
+        }
+        ++it;
+    }
+
+    if (candidates.empty()) return ret;
 
     std::string dir;
     for (const auto& overlay_mount_point : kOverlayMountPoints) {
@@ -891,8 +907,8 @@
 
     std::string overlay;
     ret |= fs_mgr_overlayfs_setup_dir(dir, &overlay, change);
-    for (const auto& fsrec_mount_point : mounts) {
-        ret |= fs_mgr_overlayfs_setup_one(overlay, fsrec_mount_point, change);
+    for (const auto& entry : candidates) {
+        ret |= fs_mgr_overlayfs_setup_one(overlay, fs_mgr_mount_point(entry.mount_point), change);
     }
     return ret;
 }
@@ -901,7 +917,6 @@
 // If something is altered, set *change.
 bool fs_mgr_overlayfs_teardown(const char* mount_point, bool* change) {
     if (change) *change = false;
-    mount_point = fs_mgr_mount_point(mount_point);
     auto ret = true;
     // If scratch exists, but is not mounted, lets gain access to clean
     // specific override entries.
@@ -919,7 +934,8 @@
                                                        fs_mgr_overlayfs_scratch_mount_type());
     }
     for (const auto& overlay_mount_point : kOverlayMountPoints) {
-        ret &= fs_mgr_overlayfs_teardown_one(overlay_mount_point, mount_point ?: "", change);
+        ret &= fs_mgr_overlayfs_teardown_one(
+                overlay_mount_point, mount_point ? fs_mgr_mount_point(mount_point) : "", change);
     }
     if (fs_mgr_overlayfs_valid() == OverlayfsValidResult::kNotSupported) {
         // After obligatory teardown to make sure everything is clean, but if
@@ -946,8 +962,9 @@
         return false;
     }
     if (fs_mgr_overlayfs_invalid()) return false;
-    for (const auto& mount_point : fs_mgr_candidate_list(&fstab)) {
-        if (fs_mgr_overlayfs_already_mounted(mount_point)) return true;
+    for (const auto& entry : fs_mgr_overlayfs_candidate_list(fstab)) {
+        if (fs_mgr_is_verity_enabled(entry)) continue;
+        if (fs_mgr_overlayfs_already_mounted(fs_mgr_mount_point(entry.mount_point))) return true;
     }
     return false;
 }
diff --git a/fs_mgr/include/fs_mgr_overlayfs.h b/fs_mgr/include/fs_mgr_overlayfs.h
index 64682cc..6aaf1f3 100644
--- a/fs_mgr/include/fs_mgr_overlayfs.h
+++ b/fs_mgr/include/fs_mgr_overlayfs.h
@@ -21,6 +21,8 @@
 #include <string>
 #include <vector>
 
+android::fs_mgr::Fstab fs_mgr_overlayfs_candidate_list(const android::fs_mgr::Fstab& fstab);
+
 bool fs_mgr_overlayfs_mount_all(android::fs_mgr::Fstab* fstab);
 std::vector<std::string> fs_mgr_overlayfs_required_devices(android::fs_mgr::Fstab* fstab);
 bool fs_mgr_overlayfs_setup(const char* backing = nullptr, const char* mount_point = nullptr,
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/Android.bp b/fs_mgr/tests/Android.bp
index ea12e96..59af924 100644
--- a/fs_mgr/tests/Android.bp
+++ b/fs_mgr/tests/Android.bp
@@ -36,3 +36,32 @@
         "-Werror",
     ],
 }
+
+cc_prebuilt_binary {
+    name: "adb-remount-test.sh",
+    srcs: ["adb-remount-test.sh"],
+    target: {
+        darwin: {
+            enabled: false,
+        },
+        windows: {
+            enabled: false,
+        },
+        android: {
+            enabled: false,
+        },
+    },
+    host_supported: true,
+}
+
+java_test_host {
+    name: "fs_mgr_vendor_overlay_test",
+
+    srcs:  ["src/**/VendorOverlayHostTest.java"],
+
+    libs: ["tradefed"],
+
+    test_config: "vendor-overlay-test.xml",
+
+    test_suites: ["general-tests"],
+}
diff --git a/fs_mgr/tests/adb-remount-test.sh b/fs_mgr/tests/adb-remount-test.sh
index 8298bf2..e4ff765 100755
--- a/fs_mgr/tests/adb-remount-test.sh
+++ b/fs_mgr/tests/adb-remount-test.sh
@@ -11,23 +11,23 @@
 ##  USAGE
 ##
 
-USAGE="USAGE: `basename ${0}` [-s <SerialNumber>]
+USAGE="USAGE: `basename ${0}` [--help] [--serial <SerialNumber>] [--color]
 
-adb remount tests (overlayfs focus)
+adb remount tests
+
+--help      This help
+--serial    Specify device (must if multiple are present)
+--color     Dress output with highlighting colors
 
 Conditions:
  - Must be a userdebug build.
  - Must be in adb mode.
- - Kernel must have overlayfs enabled and patched to support override_creds.
- - Must have either squashfs, ext4-dedupe or right-sized partitions.
- - Minimum expectation system and vender are overlayfs covered partitions.
+ - Also tests overlayfs
+  - Kernel must have overlayfs enabled and patched to support override_creds.
+  - Must have either erofs, squashfs, ext4-dedupe or full partitions.
+  - Minimum expectation system and vender are overlayfs covered partitions.
 "
 
-if [ X"${1}" = X"--help" -o X"${1}" = X"-h" -o X"${1}" = X"-?" ]; then
-  echo "${USAGE}" >&2
-  exit 0
-fi
-
 ##
 ##  Helper Variables
 ##
@@ -44,6 +44,7 @@
 ORANGE="${ESCAPE}[38;5;255:165:0m"
 BLUE="${ESCAPE}[35m"
 NORMAL="${ESCAPE}[0m"
+TMPDIR=${TMPDIR:-/tmp}
 
 ##
 ##  Helper Functions
@@ -210,6 +211,21 @@
   fi
 }
 
+[ "USAGE: usb_status > stdout
+
+If adb_wait failed, check if device is in fastboot mode and report status
+
+Returns: \"(USB stack borken?)\", \"(In fastboot mode)\" or \"(in adb mode)\"" ]
+usb_status() {
+  if inFastboot; then
+    echo "(In fastboot mode)"
+  elif inAdb; then
+    echo "(In adb mode)"
+  else
+    echo "(USB stack borken?)"
+  fi
+}
+
 [ "USAGE: fastboot_wait [timeout]
 
 Returns: waits until the device has returned for fastboot or optional timeout" ]
@@ -278,13 +294,22 @@
   echo ${O} >&2
 }
 
+[ "USAGE: restore
+
+Do nothing: should be redefined when necessary.  Called after cleanup.
+
+Returns: reverses configurations" ]
+restore() {
+  true
+}
+
 [ "USAGE: cleanup
 
 Do nothing: should be redefined when necessary
 
-Returns: cleans up any latent resources, reverses configurations" ]
-cleanup () {
-  :
+Returns: cleans up any latent resources" ]
+cleanup() {
+  true
 }
 
 [ "USAGE: die [-d|-t <epoch>] [message] >/dev/stderr
@@ -306,6 +331,7 @@
   fi
   echo "${RED}[  FAILED  ]${NORMAL} ${@}" >&2
   cleanup
+  restore
   exit 1
 }
 
@@ -383,13 +409,63 @@
     -e " /\(cache\|mnt/scratch\|mnt/vendor/persist\|persist\|metadata\) "
 }
 
+[ "USAGE: skip_unrelated_mounts < /proc/mounts
+
+or output from df
+
+Filters out all apex and vendor override administrative overlay mounts
+uninteresting to the test" ]
+skip_unrelated_mounts() {
+    grep -v "^overlay.* /\(apex\|bionic\|system\|vendor\)/[^ ]" |
+      grep -v "[%] /\(apex\|bionic\|system\|vendor\)/[^ ][^ ]*$"
+}
+
 ##
 ##  MAINLINE
 ##
 
-if [ X"-s" = X"${1}" -a -n "${2}" ]; then
-  export ANDROID_SERIAL="${2}"
-  shift 2
+OPTIONS=`getopt --alternative --unquoted --longoptions help,serial:,colour,color,no-colour,no-color -- "?hs:" ${*}` ||
+  ( echo "${USAGE}" >&2 ; false ) ||
+  die "getopt failure"
+set -- ${OPTIONS}
+
+color=false
+while [ ${#} -gt 0 ]; do
+  case ${1} in
+    -h | --help | -\?)
+      echo "${USAGE}" >&2
+      exit 0
+      ;;
+    -s | --serial)
+      export ANDROID_SERIAL=${2}
+      shift
+      ;;
+    --color | --colour)
+      color=true
+      ;;
+    --no-color | --no-colour)
+      color=false
+      ;;
+    --)
+      shift
+      break
+      ;;
+    -*)
+      echo "${USAGE}" >&2
+      die "${0}: error unknown option ${1}"
+      ;;
+    *)
+      break
+      ;;
+  esac
+  shift
+done
+if ! ${color}; then
+  GREEN=""
+  RED=""
+  ORANGE=""
+  BLUE=""
+  NORMAL=""
 fi
 
 inFastboot && die "device in fastboot mode"
@@ -425,15 +501,43 @@
 [ -z "${BUILD_DESCRIPTION}" ] ||
   echo "${BLUE}[     INFO ]${NORMAL} ${BUILD_DESCRIPTION}" >&2
 
-VERITY_WAS_ENABLED=false
+# Report existing partition sizes
+adb_sh ls -l /dev/block/by-name/ </dev/null 2>/dev/null |
+  sed -n 's@.* \([^ ]*\) -> /dev/block/\([^ ]*\)$@\1 \2@p' |
+  while read name device; do
+    case ${name} in
+      system_[ab] | system | vendor_[ab] | vendor | super | cache)
+        case ${device} in
+          sd*)
+            device=${device%%[0-9]*}/${device}
+            ;;
+        esac
+        size=`adb_su cat /sys/block/${device}/size 2>/dev/null </dev/null` &&
+          size=`expr ${size} / 2` &&
+          echo "${BLUE}[     INFO ]${NORMAL} partition ${name} device ${device} size ${size}K" >&2
+        ;;
+    esac
+  done
+
+# Can we test remount -R command?
+overlayfs_supported=true
 if [ "orange" = "`get_property ro.boot.verifiedbootstate`" -a \
      "2" = "`get_property partition.system.verified`" ]; then
-  VERITY_WAS_ENABLED=true
+  restore() {
+    ${overlayfs_supported} || return 0
+    echo "${GREEN}[     INFO ]${NORMAL} restoring verity" >&2
+    inFastboot &&
+      fastboot reboot &&
+      adb_wait 2m
+    adb_root &&
+      adb enable-verity &&
+      adb_reboot &&
+      adb_wait 2m
+  }
 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 2>/dev/null ||
   adb_sh grep "nodev${TAB}overlay" /proc/filesystems </dev/null >/dev/null 2>/dev/null &&
@@ -452,7 +556,7 @@
           echo "${ORANGE}[  WARNING ]${NORMAL} overlay module does not support override_creds" >&2 &&
           false
         ) ||
-        overlayfs_supported=false;
+        overlayfs_supported=false
       ;;
     *)
       echo "${GREEN}[       OK ]${NORMAL} overlay module uses callers creds" >&2
@@ -484,9 +588,9 @@
   echo "${ORANGE}[  WARNING ]${NORMAL} rebooting before test" >&2
   adb_reboot &&
     adb_wait 2m ||
-    die "lost device after reboot after wipe (USB stack broken?)"
+    die "lost device after reboot after wipe `usb_status`"
   adb_root ||
-    die "lost device after elevation to root after wipe (USB stack broken?)"
+    die "lost device after elevation to root after wipe `usb_status`"
 fi
 D=`adb_sh df -k </dev/null` &&
   H=`echo "${D}" | head -1` &&
@@ -509,7 +613,8 @@
     grep "Filesystem features:.*shared_blocks" >/dev/null &&
   no_dedupe=false
 done
-D=`adb_sh df -k ${D} </dev/null`
+D=`adb_sh df -k ${D} </dev/null |
+   sed 's@\([%] /\)\(apex\|bionic\|system\|vendor\)/[^ ][^ ]*$@\1@'`
 echo "${D}"
 if [ X"${D}" = X"${D##* 100[%] }" ] && ${no_dedupe} ; then
   overlayfs_needed=false
@@ -523,8 +628,8 @@
 H=`adb disable-verity 2>&1`
 err=${?}
 L=
-D="${H%?Now reboot your device for settings to take effect}"
-if [ X"${D}" != X"${D##*using overlayfs}" ]; then
+D="${H%?Now reboot your device for settings to take effect*}"
+if [ X"${D}" != X"${D##*[Uu]sing overlayfs}" ]; then
   echo "${GREEN}[       OK ]${NORMAL} using overlayfs" >&2
 fi
 if [ ${err} != 0 ]; then
@@ -548,16 +653,16 @@
   L=`adb_logcat -b all -v nsec -t ${T} 2>&1`
   adb_reboot &&
     adb_wait 2m ||
-    die "lost device after reboot requested (USB stack broken?)"
+    die "lost device after reboot requested `usb_status`"
   adb_root ||
-    die "lost device after elevation to root (USB stack broken?)"
+    die "lost device after elevation to root `usb_status`"
   rebooted=true
   # re-disable verity to see the setup remarks expected
   T=`adb_date`
   H=`adb disable-verity 2>&1`
   err=${?}
-  D="${H%?Now reboot your device for settings to take effect}"
-  if [ X"${D}" != X"${D##*using overlayfs}" ]; then
+  D="${H%?Now reboot your device for settings to take effect*}"
+  if [ X"${D}" != X"${D##*[Uu]sing overlayfs}" ]; then
     echo "${GREEN}[       OK ]${NORMAL} using overlayfs" >&2
   fi
   if [ ${err} != 0 ]; then
@@ -588,12 +693,16 @@
 
 echo "${GREEN}[ RUN      ]${NORMAL} remount" >&2
 
-adb remount ||
+D=`adb remount 2>&1`
+ret=${?}
+echo "${D}"
+[ ${ret} != 0 ] ||
+  [ X"${D}" = X"${D##*remount failed}" ] ||
   ( [ -n "${L}" ] && echo "${L}" && false ) ||
   die -t "${T}" "adb remount failed"
 D=`adb_sh df -k </dev/null` &&
   H=`echo "${D}" | head -1` &&
-  D=`echo "${D}" | grep -v " /vendor/..*$" | grep "^overlay "` ||
+  D=`echo "${D}" | skip_unrelated_mounts | grep "^overlay "` ||
   ( [ -n "${L}" ] && echo "${L}" && false )
 ret=${?}
 uses_dynamic_scratch=false
@@ -637,11 +746,34 @@
     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\|bionic\)/..* overlay ro," |
-    grep " overlay ro,") &&
-    !(adb_sh grep " rw," /proc/mounts </dev/null |
-      skip_administrative_mounts data) ||
+    skip_unrelated_mounts |
+    grep " overlay ro,") ||
     die "remount overlayfs missed a spot (ro)"
+  D=`adb_sh grep " rw," /proc/mounts </dev/null |
+     skip_administrative_mounts data`
+  if echo "${D}" | grep /dev/root >/dev/null; then
+    D=`echo / /
+       echo "${D}" | grep -v /dev/root`
+  fi
+  D=`echo "${D}" | cut -s -d' ' -f1 | sort -u`
+  bad_rw=false
+  for d in ${D}; do
+    if adb_sh tune2fs -l $d 2>&1 |
+       grep "Filesystem features:.*shared_blocks" >/dev/null; then
+      bad_rw=true
+    else
+      d=`adb_sh df -k ${D} </dev/null |
+       sed 's@\([%] /\)\(apex\|bionic\|system\|vendor\)/[^ ][^ ]*$@\1@'`
+      [ X"${d}" = X"${d##* 100[%] }" ] ||
+        bad_rw=true
+    fi
+  done
+  [ -z "${D}" ] ||
+    D=`adb_sh df -k ${D} </dev/null |
+       sed -e 's@\([%] /\)\(apex\|bionic\|system\|vendor\)/[^ ][^ ]*$@\1@' \
+           -e 's/^Filesystem      /Filesystem (rw) /'`
+  [ -z "${D}" ] || echo "${D}"
+  ${bad_rw} && die "remount overlayfs missed a spot (rw)"
 else
   if [ ${ret} = 0 ]; then
     die -t ${T} "unexpected overlay takeover"
@@ -694,7 +826,7 @@
 
   adb_su sed -n '1,/overlay \/system/p' /proc/mounts </dev/null |
     skip_administrative_mounts |
-    grep -v ' \(squashfs\|ext4\|f2fs\) ' &&
+    grep -v ' \(erofs\|squashfs\|ext4\|f2fs\|vfat\) ' &&
     echo "${ORANGE}[  WARNING ]${NORMAL} overlay takeover after first stage init" >&2 ||
     echo "${GREEN}[       OK ]${NORMAL} overlay takeover in first stage init" >&2
 fi
@@ -722,7 +854,10 @@
   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}
+rm -rf ${tempdir}
+cleanup() {
+  true
+}
 echo "${GREEN}[       OK ]${NORMAL} /system/lib/bootstrap/libc.so content remains after reboot" >&2
 
 echo "${GREEN}[ RUN      ]${NORMAL} flash vendor, confirm its content disappears" >&2
@@ -735,10 +870,14 @@
   echo "${ORANGE}[  WARNING ]${NORMAL} vendor image missing, skipping"
 elif [ "${ANDROID_PRODUCT_OUT}" = "${ANDROID_PRODUCT_OUT%*/${H}}" ]; then
   echo "${ORANGE}[  WARNING ]${NORMAL} wrong vendor image, skipping"
+elif [ -z "${ANDROID_HOST_OUT}" ]; then
+  echo "${ORANGE}[  WARNING ]${NORMAL} please run lunch, skipping"
 else
-  adb reboot-fastboot &&
-    fastboot_wait 2m &&
-    fastboot flash vendor ||
+  adb reboot-fastboot ||
+    die "fastbootd not supported (wrong adb in path?)"
+  fastboot_wait 2m ||
+    die "reboot into fastboot to flash vendor `usb_status`"
+  fastboot flash vendor ||
     ( fastboot reboot && false) ||
     die "fastboot flash vendor"
   fastboot_getvar is-userspace yes &&
@@ -777,12 +916,12 @@
     die "can not reboot out of fastboot"
   echo "${ORANGE}[  WARNING ]${NORMAL} adb after fastboot"
   adb_wait 2m ||
-    die "did not reboot after flash"
+    die "did not reboot after flash `usb_status`"
   if ${overlayfs_needed}; then
     adb_root &&
       D=`adb_sh df -k </dev/null` &&
       H=`echo "${D}" | head -1` &&
-      D=`echo "${D}" | grep -v " /vendor/..*$" | grep "^overlay "` &&
+      D=`echo "${D}" | skip_unrelated_mounts | grep "^overlay "` &&
       echo "${H}" &&
       echo "${D}" &&
       echo "${D}" | grep "^overlay .* /system\$" >/dev/null ||
@@ -820,7 +959,7 @@
 H=`adb remount 2>&1`
 err=${?}
 L=
-D="${H%?Now reboot your device for settings to take effect}"
+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`
@@ -851,17 +990,18 @@
 
   adb reboot-fastboot ||
     die "Reboot into fastbootd"
+  img=${TMPDIR}/adb-remount-test-${$}.img
   cleanup() {
-    rm /tmp/adb-remount-test.img
+    rm ${img}
   }
-  dd if=/dev/zero of=/tmp/adb-remount-test.img bs=4096 count=16 2>/dev/null &&
+  dd if=/dev/zero of=${img} bs=4096 count=16 2>/dev/null &&
     fastboot_wait 2m ||
-    die "reboot into fastboot"
-  fastboot flash --force ${scratch_partition} /tmp/adb-remount-test.img
+    die "reboot into fastboot `usb_status`"
+  fastboot flash --force ${scratch_partition} ${img}
   err=${?}
   cleanup
   cleanup() {
-    :
+    true
   }
   fastboot reboot ||
     die "can not reboot out of fastboot"
@@ -873,14 +1013,32 @@
   T=`adb_date`
   D=`adb disable-verity 2>&1`
   err=${?}
-  adb remount ||
-    die "remount failed"
+  if [ X"${D}" != "${D%?Now reboot your device for settings to take effect*}" ]
+  then
+    echo "${ORANGE}[  WARNING ]${NORMAL} adb disable-verity requires a reboot after partial flash"
+    adb_reboot &&
+      adb_wait 2m &&
+      adb_root ||
+      die "failed to reboot"
+    T=`adb_date`
+    D="${D}
+`adb disable-verity 2>&1`"
+    err=${?}
+  fi
+
   echo "${D}"
   [ ${err} = 0 ] &&
     [ X"${D}" = X"${D##*setup failed}" ] &&
-    [ X"${D}" != X"${D##*using overlayfs}" ] &&
+    [ X"${D}" != X"${D##*[Uu]sing overlayfs}" ] &&
     echo "${GREEN}[       OK ]${NORMAL} ${scratch_partition} recreated" >&2 ||
     die -t ${T} "setup for overlayfs"
+  D=`adb remount 2>&1`
+  err=${?}
+  echo "${D}"
+  [ ${err} != 0 ] ||
+    [ X"${D}" = X"${D##*remount failed}" ] ||
+    ( echo "${D}" && false ) ||
+    die -t ${T} "remount failed"
 fi
 
 echo "${GREEN}[ RUN      ]${NORMAL} test raw remount commands" >&2
@@ -888,7 +1046,7 @@
 # Prerequisite is a prepped device from above.
 adb_reboot &&
   adb_wait 2m ||
-  die "lost device after reboot to ro state (USB stack broken?)"
+  die "lost device after reboot to ro state `usb_status`"
 adb_sh grep " /vendor .* rw," /proc/mounts >/dev/null &&
   die "/vendor is not read-only"
 adb_su mount -o rw,remount /vendor ||
@@ -897,12 +1055,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
+restore
+err=${?}
+restore() {
+  true
+}
+[ ${err} = 0 ] ||
+  die "failed to restore verity" >&2
 
 echo "${GREEN}[  PASSED  ]${NORMAL} adb remount" >&2
diff --git a/fs_mgr/tests/src/com/android/tests/vendoroverlay/VendorOverlayHostTest.java b/fs_mgr/tests/src/com/android/tests/vendoroverlay/VendorOverlayHostTest.java
new file mode 100644
index 0000000..f08cab2
--- /dev/null
+++ b/fs_mgr/tests/src/com/android/tests/vendoroverlay/VendorOverlayHostTest.java
@@ -0,0 +1,151 @@
+/*
+ * 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.
+ */
+
+package com.android.tests.vendoroverlay;
+
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
+import com.android.tradefed.util.CommandResult;
+import com.android.tradefed.util.CommandStatus;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Assume;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Test the vendor overlay feature. Requires adb remount with OverlayFS.
+ */
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class VendorOverlayHostTest extends BaseHostJUnit4Test {
+  boolean wasRoot = false;
+
+  @Before
+  public void setup() throws DeviceNotAvailableException {
+    wasRoot = getDevice().isAdbRoot();
+    if (!wasRoot) {
+      Assume.assumeTrue("Test requires root", getDevice().enableAdbRoot());
+    }
+
+    Assume.assumeTrue("Skipping vendor overlay test due to lack of necessary OverlayFS support",
+        testConditionsMet());
+
+    getDevice().remountSystemWritable();
+    // Was OverlayFS used by adb remount? Without it we can't safely re-enable dm-verity.
+    Pattern vendorPattern = Pattern.compile("^overlay .+ /vendor$", Pattern.MULTILINE);
+    Pattern productPattern = Pattern.compile("^overlay .+ /product$", Pattern.MULTILINE);
+    CommandResult result = getDevice().executeShellV2Command("df");
+    Assume.assumeTrue("OverlayFS not used for adb remount on /vendor",
+        vendorPattern.matcher(result.getStdout()).find());
+    Assume.assumeTrue("OverlayFS not used for adb remount on /product",
+        productPattern.matcher(result.getStdout()).find());
+  }
+
+  private boolean cmdSucceeded(CommandResult result) {
+    return result.getStatus() == CommandStatus.SUCCESS;
+  }
+
+  private void assumeMkdirSuccess(String dir) throws DeviceNotAvailableException {
+    CommandResult result = getDevice().executeShellV2Command("mkdir -p " + dir);
+    Assume.assumeTrue("Couldn't create " + dir, cmdSucceeded(result));
+  }
+
+  /**
+   * Tests that files in the appropriate /product/vendor_overlay dir are overlaid onto /vendor.
+   */
+  @Test
+  public void testVendorOverlay() throws DeviceNotAvailableException {
+    String vndkVersion = getDevice().executeShellV2Command("getprop ro.vndk.version").getStdout();
+
+    // Create files and modify policy
+    CommandResult result = getDevice().executeShellV2Command(
+        "echo '/(product|system/product)/vendor_overlay/" + vndkVersion +
+        "/.* u:object_r:vendor_file:s0'" + " >> /system/etc/selinux/plat_file_contexts");
+    Assume.assumeTrue("Couldn't modify plat_file_contexts", cmdSucceeded(result));
+    assumeMkdirSuccess("/vendor/testdir");
+    assumeMkdirSuccess("/vendor/diffcontext");
+    assumeMkdirSuccess("/product/vendor_overlay/'" + vndkVersion + "'/testdir");
+    result = getDevice().executeShellV2Command(
+        "echo overlay > /product/vendor_overlay/'" + vndkVersion + "'/testdir/test");
+    Assume.assumeTrue("Couldn't create text file in testdir", cmdSucceeded(result));
+    assumeMkdirSuccess("/product/vendor_overlay/'" + vndkVersion + "'/noexist/test");
+    assumeMkdirSuccess("/product/vendor_overlay/'" + vndkVersion + "'/diffcontext/test");
+    result = getDevice().executeShellV2Command(
+        "restorecon -r /product/vendor_overlay/'" + vndkVersion + "'/testdir");
+    Assume.assumeTrue("Couldn't write testdir context", cmdSucceeded(result));
+
+    getDevice().reboot();
+
+    // Test that the file was overlaid properly
+    result = getDevice().executeShellV2Command("[ $(cat /vendor/testdir/test) = overlay ]");
+    Assert.assertTrue("test file was not overlaid onto /vendor/", cmdSucceeded(result));
+    result = getDevice().executeShellV2Command("[ ! -d /vendor/noexist/test ]");
+    Assert.assertTrue("noexist dir shouldn't exist on /vendor", cmdSucceeded(result));
+    result = getDevice().executeShellV2Command("[ ! -d /vendor/diffcontext/test ]");
+    Assert.assertTrue("diffcontext dir shouldn't exist on /vendor", cmdSucceeded(result));
+  }
+
+  // Duplicate of fs_mgr_overlayfs_valid() logic
+  // Requires root
+  public boolean testConditionsMet() throws DeviceNotAvailableException {
+    if (cmdSucceeded(getDevice().executeShellV2Command(
+        "[ -e /sys/module/overlay/parameters/override_creds ]"))) {
+      return true;
+    }
+    if (cmdSucceeded(getDevice().executeShellV2Command("[ ! -e /sys/module/overlay ]"))) {
+      return false;
+    }
+    CommandResult result = getDevice().executeShellV2Command("awk '{ print $3 }' /proc/version");
+    Pattern kernelVersionPattern = Pattern.compile("([1-9])[.]([0-9]+).*");
+    Matcher kernelVersionMatcher = kernelVersionPattern.matcher(result.getStdout());
+    kernelVersionMatcher.find();
+    int majorKernelVersion;
+    int minorKernelVersion;
+    try {
+      majorKernelVersion = Integer.parseInt(kernelVersionMatcher.group(1));
+      minorKernelVersion = Integer.parseInt(kernelVersionMatcher.group(2));
+    } catch (Exception e) {
+      return false;
+    }
+    if (majorKernelVersion < 4) {
+      return true;
+    }
+    if (majorKernelVersion > 4) {
+      return false;
+    }
+    if (minorKernelVersion > 6) {
+      return false;
+    }
+    return true;
+  }
+
+  @After
+  public void tearDown() throws DeviceNotAvailableException {
+    if (getDevice().executeAdbCommand("enable-verity").contains("Now reboot your device")) {
+      getDevice().reboot();
+    }
+    if (!wasRoot) {
+      getDevice().disableAdbRoot();
+    }
+  }
+}
+
diff --git a/fs_mgr/tests/vendor-overlay-test.xml b/fs_mgr/tests/vendor-overlay-test.xml
new file mode 100644
index 0000000..0b5c8cc
--- /dev/null
+++ b/fs_mgr/tests/vendor-overlay-test.xml
@@ -0,0 +1,21 @@
+<?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 vendor overlay test cases">
+    <test class="com.android.tradefed.testtype.HostTest" >
+        <option name="jar" value="fs_mgr_vendor_overlay_test.jar" />
+    </test>
+</configuration>
+
diff --git a/init/first_stage_mount.cpp b/init/first_stage_mount.cpp
index 1b077bc..898e28e 100644
--- a/init/first_stage_mount.cpp
+++ b/init/first_stage_mount.cpp
@@ -47,6 +47,7 @@
 using android::base::Split;
 using android::base::Timer;
 using android::fs_mgr::AvbHandle;
+using android::fs_mgr::AvbHandleStatus;
 using android::fs_mgr::AvbHashtreeResult;
 using android::fs_mgr::AvbUniquePtr;
 using android::fs_mgr::BuildGsiSystemFstabEntry;
@@ -737,8 +738,17 @@
         hashtree_result =
                 avb_handle_->SetUpAvbHashtree(fstab_entry, false /* wait_for_verity_dev */);
     } else if (!fstab_entry->avb_key.empty()) {
-        hashtree_result =
-                AvbHandle::SetUpStandaloneAvbHashtree(fstab_entry, false /* wait_for_verity_dev */);
+        if (!InitAvbHandle()) return false;
+        // Checks if hashtree should be disabled from the top-level /vbmeta.
+        if (avb_handle_->status() == AvbHandleStatus::kHashtreeDisabled ||
+            avb_handle_->status() == AvbHandleStatus::kVerificationDisabled) {
+            LOG(ERROR) << "Top-level vbmeta is disabled, skip Hashtree setup for "
+                       << fstab_entry->mount_point;
+            return true;  // Returns true to mount the partition directly.
+        } else {
+            hashtree_result = AvbHandle::SetUpStandaloneAvbHashtree(
+                    fstab_entry, false /* wait_for_verity_dev */);
+        }
     } else {
         return true;  // No need AVB, returns true to mount the partition directly.
     }
@@ -754,8 +764,6 @@
         default:
             return false;
     }
-
-    return true;  // Returns true to mount the partition.
 }
 
 bool FirstStageMountVBootV2::InitAvbHandle() {
diff --git a/libasyncio/Android.bp b/libasyncio/Android.bp
index 4ab439d..0fd2a3a 100644
--- a/libasyncio/Android.bp
+++ b/libasyncio/Android.bp
@@ -27,6 +27,7 @@
     name: "libasyncio",
     defaults: ["libasyncio_defaults"],
     vendor_available: true,
+    double_loadable: true,
     recovery_available: true,
     host_supported: true,
     srcs: [
diff --git a/libbacktrace/BacktraceMap.cpp b/libbacktrace/BacktraceMap.cpp
index 6a967f7..781819a 100644
--- a/libbacktrace/BacktraceMap.cpp
+++ b/libbacktrace/BacktraceMap.cpp
@@ -46,8 +46,7 @@
   }
 }
 
-BacktraceMap::~BacktraceMap() {
-}
+BacktraceMap::~BacktraceMap() {}
 
 void BacktraceMap::FillIn(uint64_t addr, backtrace_map_t* map) {
   ScopedBacktraceMapIteratorLock lock(this);
@@ -68,12 +67,13 @@
   char permissions[5];
   int name_pos;
 
-// Mac OS vmmap(1) output:
-// __TEXT                 0009f000-000a1000 [    8K     8K] r-x/rwx SM=COW  /Volumes/android/dalvik-dev/out/host/darwin-x86/bin/libcorkscrew_test\n
-// 012345678901234567890123456789012345678901234567890123456789
-// 0         1         2         3         4         5
-  if (sscanf(line, "%*21c %" SCNx64 "-%" SCNx64 " [%*13c] %3c/%*3c SM=%*3c  %n",
-             &start, &end, permissions, &name_pos) != 3) {
+  // Mac OS vmmap(1) output:
+  // __TEXT                 0009f000-000a1000 [    8K     8K] r-x/rwx SM=COW
+  // /Volumes/android/dalvik-dev/out/host/darwin-x86/bin/libcorkscrew_test\n
+  // 012345678901234567890123456789012345678901234567890123456789
+  // 0         1         2         3         4         5
+  if (sscanf(line, "%*21c %" SCNx64 "-%" SCNx64 " [%*13c] %3c/%*3c SM=%*3c  %n", &start, &end,
+             permissions, &name_pos) != 3) {
     return false;
   }
 
@@ -90,21 +90,21 @@
     map->flags |= PROT_EXEC;
   }
 
-  map->name = line+name_pos;
-  if (!map->name.empty() && map->name[map->name.length()-1] == '\n') {
-    map->name.erase(map->name.length()-1);
+  map->name = line + name_pos;
+  if (!map->name.empty() && map->name[map->name.length() - 1] == '\n') {
+    map->name.erase(map->name.length() - 1);
   }
 
-  ALOGV("Parsed map: start=%p, end=%p, flags=%x, name=%s",
-        reinterpret_cast<void*>(map->start), reinterpret_cast<void*>(map->end),
-        map->flags, map->name.c_str());
+  ALOGV("Parsed map: start=%p, end=%p, flags=%x, name=%s", reinterpret_cast<void*>(map->start),
+        reinterpret_cast<void*>(map->end), map->flags, map->name.c_str());
   return true;
 }
 #endif  // defined(__APPLE__)
 
 bool BacktraceMap::Build() {
 #if defined(__APPLE__)
-  char cmd[sizeof(pid_t)*3 + sizeof("vmmap -w -resident -submap -allSplitLibs -interleaved ") + 1];
+  char
+      cmd[sizeof(pid_t) * 3 + sizeof("vmmap -w -resident -submap -allSplitLibs -interleaved ") + 1];
   char line[1024];
   // cmd is guaranteed to always be big enough to hold this string.
   snprintf(cmd, sizeof(cmd), "vmmap -w -resident -submap -allSplitLibs -interleaved %d", pid_);
@@ -113,7 +113,7 @@
     return false;
   }
 
-  while(fgets(line, sizeof(line), fp)) {
+  while (fgets(line, sizeof(line), fp)) {
     backtrace_map_t map;
     if (ParseLine(line, &map)) {
       maps_.push_back(map);
@@ -123,7 +123,7 @@
   return true;
 #else
   return android::procinfo::ReadProcessMaps(
-      pid_, [&](uint64_t start, uint64_t end, uint16_t flags, uint64_t, const char* name) {
+      pid_, [&](uint64_t start, uint64_t end, uint16_t flags, uint64_t, ino_t, const char* name) {
         maps_.resize(maps_.size() + 1);
         backtrace_map_t& map = maps_.back();
         map.start = start;
diff --git a/liblog/Android.bp b/liblog/Android.bp
index 1d4a0a0..ea9977b 100644
--- a/liblog/Android.bp
+++ b/liblog/Android.bp
@@ -46,6 +46,8 @@
     vendor_available: true,
     recovery_available: true,
     export_include_dirs: ["include"],
+    system_shared_libs: [],
+    stl: "none",
     target: {
         windows: {
             enabled: true,
diff --git a/liblog/logd_reader.cpp b/liblog/logd_reader.cpp
index 2f0af4a..b7ba782 100644
--- a/liblog/logd_reader.cpp
+++ b/liblog/logd_reader.cpp
@@ -100,148 +100,29 @@
   return -EBADF;
 }
 
-/* Private copy of ../libcutils/socket_local_client.c prevent library loops */
+// Connects to /dev/socket/<name> and returns the associated fd or returns -1 on error.
+// O_CLOEXEC is always set.
+static int socket_local_client(const std::string& name, int type) {
+  sockaddr_un addr = {.sun_family = AF_LOCAL};
 
-#if defined(_WIN32)
-
-LIBLOG_WEAK int socket_local_client(const char* name, int namespaceId, int type) {
-  errno = ENOSYS;
-  return -ENOSYS;
-}
-
-#else /* !_WIN32 */
-
-#include <sys/select.h>
-#include <sys/socket.h>
-#include <sys/types.h>
-#include <sys/un.h>
-
-/* Private copy of ../libcutils/socket_local.h prevent library loops */
-#define FILESYSTEM_SOCKET_PREFIX "/tmp/"
-#define ANDROID_RESERVED_SOCKET_PREFIX "/dev/socket/"
-/* End of ../libcutils/socket_local.h */
-
-#define LISTEN_BACKLOG 4
-
-/* Documented in header file. */
-LIBLOG_WEAK int socket_make_sockaddr_un(const char* name, int namespaceId,
-                                        struct sockaddr_un* p_addr, socklen_t* alen) {
-  memset(p_addr, 0, sizeof(*p_addr));
-  size_t namelen;
-
-  switch (namespaceId) {
-    case ANDROID_SOCKET_NAMESPACE_ABSTRACT:
-#if defined(__linux__)
-      namelen = strlen(name);
-
-      /* Test with length +1 for the *initial* '\0'. */
-      if ((namelen + 1) > sizeof(p_addr->sun_path)) {
-        goto error;
-      }
-
-      /*
-       * Note: The path in this case is *not* supposed to be
-       * '\0'-terminated. ("man 7 unix" for the gory details.)
-       */
-
-      p_addr->sun_path[0] = 0;
-      memcpy(p_addr->sun_path + 1, name, namelen);
-#else
-      /* this OS doesn't have the Linux abstract namespace */
-
-      namelen = strlen(name) + strlen(FILESYSTEM_SOCKET_PREFIX);
-      /* unix_path_max appears to be missing on linux */
-      if (namelen > sizeof(*p_addr) - offsetof(struct sockaddr_un, sun_path) - 1) {
-        goto error;
-      }
-
-      strcpy(p_addr->sun_path, FILESYSTEM_SOCKET_PREFIX);
-      strcat(p_addr->sun_path, name);
-#endif
-      break;
-
-    case ANDROID_SOCKET_NAMESPACE_RESERVED:
-      namelen = strlen(name) + strlen(ANDROID_RESERVED_SOCKET_PREFIX);
-      /* unix_path_max appears to be missing on linux */
-      if (namelen > sizeof(*p_addr) - offsetof(struct sockaddr_un, sun_path) - 1) {
-        goto error;
-      }
-
-      strcpy(p_addr->sun_path, ANDROID_RESERVED_SOCKET_PREFIX);
-      strcat(p_addr->sun_path, name);
-      break;
-
-    case ANDROID_SOCKET_NAMESPACE_FILESYSTEM:
-      namelen = strlen(name);
-      /* unix_path_max appears to be missing on linux */
-      if (namelen > sizeof(*p_addr) - offsetof(struct sockaddr_un, sun_path) - 1) {
-        goto error;
-      }
-
-      strcpy(p_addr->sun_path, name);
-      break;
-
-    default:
-      /* invalid namespace id */
-      return -1;
+  std::string path = "/dev/socket/" + name;
+  if (path.size() + 1 > sizeof(addr.sun_path)) {
+    return -1;
   }
+  strlcpy(addr.sun_path, path.c_str(), sizeof(addr.sun_path));
 
-  p_addr->sun_family = AF_LOCAL;
-  *alen = namelen + offsetof(struct sockaddr_un, sun_path) + 1;
-  return 0;
-error:
-  return -1;
-}
-
-/**
- * connect to peer named "name" on fd
- * returns same fd or -1 on error.
- * fd is not closed on error. that's your job.
- *
- * Used by AndroidSocketImpl
- */
-LIBLOG_WEAK int socket_local_client_connect(int fd, const char* name, int namespaceId,
-                                            int type __unused) {
-  struct sockaddr_un addr;
-  socklen_t alen;
-  int err;
-
-  err = socket_make_sockaddr_un(name, namespaceId, &addr, &alen);
-
-  if (err < 0) {
-    goto error;
-  }
-
-  if (connect(fd, (struct sockaddr*)&addr, alen) < 0) {
-    goto error;
-  }
-
-  return fd;
-
-error:
-  return -1;
-}
-
-/**
- * connect to peer named "name"
- * returns fd or -1 on error
- */
-LIBLOG_WEAK int socket_local_client(const char* name, int namespaceId, int type) {
-  int s;
-
-  s = socket(AF_LOCAL, type, 0);
-  if (s < 0) return -1;
-
-  if (0 > socket_local_client_connect(s, name, namespaceId, type)) {
-    close(s);
+  int fd = socket(AF_LOCAL, type | SOCK_CLOEXEC, 0);
+  if (fd == 0) {
     return -1;
   }
 
-  return s;
-}
+  if (connect(fd, reinterpret_cast<sockaddr*>(&addr), sizeof(addr)) == -1) {
+    close(fd);
+    return -1;
+  }
 
-#endif /* !_WIN32 */
-/* End of ../libcutils/socket_local_client.c */
+  return fd;
+}
 
 /* worker for sending the command to the logger */
 static ssize_t send_log_msg(struct android_log_logger* logger, const char* msg, char* buf,
@@ -250,7 +131,7 @@
   size_t len;
   char* cp;
   int errno_save = 0;
-  int sock = socket_local_client("logd", ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM);
+  int sock = socket_local_client("logd", SOCK_STREAM);
   if (sock < 0) {
     return sock;
   }
@@ -460,10 +341,10 @@
     return sock;
   }
 
-  sock = socket_local_client("logdr", ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_SEQPACKET);
+  sock = socket_local_client("logdr", SOCK_SEQPACKET);
   if (sock == 0) {
     /* Guarantee not file descriptor zero */
-    int newsock = socket_local_client("logdr", ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_SEQPACKET);
+    int newsock = socket_local_client("logdr", SOCK_SEQPACKET);
     close(sock);
     sock = newsock;
   }
diff --git a/liblog/tests/Android.bp b/liblog/tests/Android.bp
index 4ab2acb..50755ce 100644
--- a/liblog/tests/Android.bp
+++ b/liblog/tests/Android.bp
@@ -31,6 +31,7 @@
     shared_libs: [
         "libm",
         "libbase",
+        "libcutils",
     ],
     static_libs: ["liblog"],
     srcs: ["liblog_benchmark.cpp"],
diff --git a/liblog/tests/libc_test.cpp b/liblog/tests/libc_test.cpp
index 6d78ed6..3534eb8 100644
--- a/liblog/tests/libc_test.cpp
+++ b/liblog/tests/libc_test.cpp
@@ -23,7 +23,7 @@
 #ifdef __ANDROID__
 #ifndef NO_PSTORE
   FILE* fp;
-  ASSERT_TRUE(NULL != (fp = fopen("/dev/pmsg0", "a")));
+  ASSERT_TRUE(NULL != (fp = fopen("/dev/pmsg0", "ae")));
   static const char message[] = "libc.__pstore_append\n";
   ASSERT_EQ((size_t)1, fwrite(message, sizeof(message), 1, fp));
   int fflushReturn = fflush(fp);
diff --git a/liblog/tests/liblog_benchmark.cpp b/liblog/tests/liblog_benchmark.cpp
index c8ac321..7d11ccf 100644
--- a/liblog/tests/liblog_benchmark.cpp
+++ b/liblog/tests/liblog_benchmark.cpp
@@ -172,7 +172,7 @@
  * Measure the time it takes to submit the android logging data to pstore
  */
 static void BM_pmsg_short(benchmark::State& state) {
-  int pstore_fd = TEMP_FAILURE_RETRY(open("/dev/pmsg0", O_WRONLY));
+  int pstore_fd = TEMP_FAILURE_RETRY(open("/dev/pmsg0", O_WRONLY | O_CLOEXEC));
   if (pstore_fd < 0) {
     state.SkipWithError("/dev/pmsg0");
     return;
@@ -248,7 +248,7 @@
  * best case aligned single block.
  */
 static void BM_pmsg_short_aligned(benchmark::State& state) {
-  int pstore_fd = TEMP_FAILURE_RETRY(open("/dev/pmsg0", O_WRONLY));
+  int pstore_fd = TEMP_FAILURE_RETRY(open("/dev/pmsg0", O_WRONLY | O_CLOEXEC));
   if (pstore_fd < 0) {
     state.SkipWithError("/dev/pmsg0");
     return;
@@ -323,7 +323,7 @@
  * best case aligned single block.
  */
 static void BM_pmsg_short_unaligned1(benchmark::State& state) {
-  int pstore_fd = TEMP_FAILURE_RETRY(open("/dev/pmsg0", O_WRONLY));
+  int pstore_fd = TEMP_FAILURE_RETRY(open("/dev/pmsg0", O_WRONLY | O_CLOEXEC));
   if (pstore_fd < 0) {
     state.SkipWithError("/dev/pmsg0");
     return;
@@ -398,7 +398,7 @@
  * best case aligned single block.
  */
 static void BM_pmsg_long_aligned(benchmark::State& state) {
-  int pstore_fd = TEMP_FAILURE_RETRY(open("/dev/pmsg0", O_WRONLY));
+  int pstore_fd = TEMP_FAILURE_RETRY(open("/dev/pmsg0", O_WRONLY | O_CLOEXEC));
   if (pstore_fd < 0) {
     state.SkipWithError("/dev/pmsg0");
     return;
@@ -471,7 +471,7 @@
  * best case aligned single block.
  */
 static void BM_pmsg_long_unaligned1(benchmark::State& state) {
-  int pstore_fd = TEMP_FAILURE_RETRY(open("/dev/pmsg0", O_WRONLY));
+  int pstore_fd = TEMP_FAILURE_RETRY(open("/dev/pmsg0", O_WRONLY | O_CLOEXEC));
   if (pstore_fd < 0) {
     state.SkipWithError("/dev/pmsg0");
     return;
@@ -949,8 +949,8 @@
 
 // Must be functionally identical to liblog internal __send_log_msg.
 static void send_to_control(char* buf, size_t len) {
-  int sock = socket_local_client("logd", ANDROID_SOCKET_NAMESPACE_RESERVED,
-                                 SOCK_STREAM);
+  int sock =
+      socket_local_client("logd", ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM | SOCK_CLOEXEC);
   if (sock < 0) return;
   size_t writeLen = strlen(buf) + 1;
 
diff --git a/liblog/tests/liblog_test.cpp b/liblog/tests/liblog_test.cpp
index 83f0fa9..1f87b3e 100644
--- a/liblog/tests/liblog_test.cpp
+++ b/liblog/tests/liblog_test.cpp
@@ -93,7 +93,7 @@
 static std::string popenToString(const std::string& command) {
   std::string ret;
 
-  FILE* fp = popen(command.c_str(), "r");
+  FILE* fp = popen(command.c_str(), "re");
   if (fp) {
     if (!android::base::ReadFdToString(fileno(fp), &ret)) ret = "";
     pclose(fp);
@@ -645,7 +645,7 @@
   char buffer[512];
   snprintf(buffer, sizeof(buffer), "/proc/%u/stat", pid);
 
-  FILE* fp = fopen(buffer, "r");
+  FILE* fp = fopen(buffer, "re");
   if (!fp) {
     return;
   }
diff --git a/liblog/tests/log_radio_test.cpp b/liblog/tests/log_radio_test.cpp
index f202c67..fa1255e 100644
--- a/liblog/tests/log_radio_test.cpp
+++ b/liblog/tests/log_radio_test.cpp
@@ -91,7 +91,7 @@
       "logcat -b radio --pid=%u -d -s"
       " TEST__RLOGV TEST__RLOGD TEST__RLOGI TEST__RLOGW TEST__RLOGE",
       (unsigned)getpid());
-  FILE* fp = popen(buf.c_str(), "r");
+  FILE* fp = popen(buf.c_str(), "re");
   int count = 0;
   int count_false = 0;
   if (fp) {
diff --git a/liblog/tests/log_system_test.cpp b/liblog/tests/log_system_test.cpp
index 0656c0b..13f026d 100644
--- a/liblog/tests/log_system_test.cpp
+++ b/liblog/tests/log_system_test.cpp
@@ -91,7 +91,7 @@
       "logcat -b system --pid=%u -d -s"
       " TEST__SLOGV TEST__SLOGD TEST__SLOGI TEST__SLOGW TEST__SLOGE",
       (unsigned)getpid());
-  FILE* fp = popen(buf.c_str(), "r");
+  FILE* fp = popen(buf.c_str(), "re");
   int count = 0;
   int count_false = 0;
   if (fp) {
diff --git a/libmeminfo/libdmabufinfo/dmabufinfo.cpp b/libmeminfo/libdmabufinfo/dmabufinfo.cpp
index 439cf68..9fb22a1 100644
--- a/libmeminfo/libdmabufinfo/dmabufinfo.cpp
+++ b/libmeminfo/libdmabufinfo/dmabufinfo.cpp
@@ -150,18 +150,14 @@
         auto buf = std::find_if(dmabufs->begin(), dmabufs->end(),
                                 [&inode](const DmaBuffer& dbuf) { return dbuf.inode() == inode; });
         if (buf != dmabufs->end()) {
-            if (buf->name() == "" || buf->name() == "<unknown>")
-                buf->SetName(name);
-            if (buf->exporter() == "" || buf->exporter() == "<unknown>")
-                buf->SetExporter(exporter);
-            if (buf->count() == 0)
-                buf->SetCount(count);
+            if (buf->name() == "" || buf->name() == "<unknown>") buf->SetName(name);
+            if (buf->exporter() == "" || buf->exporter() == "<unknown>") buf->SetExporter(exporter);
+            if (buf->count() == 0) buf->SetCount(count);
             buf->AddFdRef(pid);
             continue;
         }
 
-        DmaBuffer& db =
-                dmabufs->emplace_back(sb.st_ino, sb.st_blocks * 512, count, exporter, name);
+        DmaBuffer& db = dmabufs->emplace_back(sb.st_ino, sb.st_blocks * 512, count, exporter, name);
         db.AddFdRef(pid);
     }
 
@@ -182,29 +178,12 @@
     // Process the map if it is dmabuf. Add map reference to existing object in 'dmabufs'
     // if it was already found. If it wasn't create a new one and append it to 'dmabufs'
     auto account_dmabuf = [&](uint64_t start, uint64_t end, uint16_t /* flags */,
-                              uint64_t /* pgoff */, const char* name) {
+                              uint64_t /* pgoff */, ino_t inode, const char* name) {
         // no need to look into this mapping if it is not dmabuf
         if (!FileIsDmaBuf(std::string(name))) {
             return;
         }
 
-        // TODO (b/123532375) : Add inode number to the callback of ReadMapFileContent.
-        //
-        // Workaround: we know 'name' points to the name at the end of 'line'.
-        // We use that to backtrack and pick up the inode number from the line as well.
-        // start    end      flag pgoff    mj:mn inode   name
-        // 00400000-00409000 r-xp 00000000 00:00 426998  /dmabuf (deleted)
-        const char* p = name;
-        p--;
-        // skip spaces
-        while (p != line && *p == ' ') {
-            p--;
-        }
-        // walk backwards to the beginning of inode number
-        while (p != line && isdigit(*p)) {
-            p--;
-        }
-        uint64_t inode = strtoull(p, nullptr, 10);
         auto buf = std::find_if(dmabufs->begin(), dmabufs->end(),
                                 [&inode](const DmaBuffer& dbuf) { return dbuf.inode() == inode; });
         if (buf != dmabufs->end()) {
diff --git a/libmeminfo/libdmabufinfo/tools/Android.bp b/libmeminfo/libdmabufinfo/tools/Android.bp
index 0af3c48..224b68e 100644
--- a/libmeminfo/libdmabufinfo/tools/Android.bp
+++ b/libmeminfo/libdmabufinfo/tools/Android.bp
@@ -26,5 +26,5 @@
     static_libs: [
         "libdmabufinfo",
     ],
-    soc_specific: true,
+    product_specific: true,
 }
\ No newline at end of file
diff --git a/libmeminfo/procmeminfo.cpp b/libmeminfo/procmeminfo.cpp
index 069b6b3..934d65c 100644
--- a/libmeminfo/procmeminfo.cpp
+++ b/libmeminfo/procmeminfo.cpp
@@ -246,7 +246,7 @@
     // parse and read /proc/<pid>/maps
     std::string maps_file = ::android::base::StringPrintf("/proc/%d/maps", pid_);
     if (!::android::procinfo::ReadMapFile(
-                maps_file, [&](uint64_t start, uint64_t end, uint16_t flags, uint64_t pgoff,
+                maps_file, [&](uint64_t start, uint64_t end, uint16_t flags, uint64_t pgoff, ino_t,
                                const char* name) {
                     maps_.emplace_back(Vma(start, end, pgoff, flags, name));
                 })) {
@@ -394,7 +394,7 @@
         // If it has, we are looking for the vma stats
         // 00400000-00409000 r-xp 00000000 fc:00 426998  /usr/lib/gvfs/gvfsd-http
         if (!::android::procinfo::ReadMapFileContent(
-                    line, [&](uint64_t start, uint64_t end, uint16_t flags, uint64_t pgoff,
+                    line, [&](uint64_t start, uint64_t end, uint16_t flags, uint64_t pgoff, ino_t,
                               const char* name) {
                         vma.start = start;
                         vma.end = end;
diff --git a/libmemtrack/Android.bp b/libmemtrack/Android.bp
index 4e4554a..320b851 100644
--- a/libmemtrack/Android.bp
+++ b/libmemtrack/Android.bp
@@ -6,6 +6,7 @@
     vndk: {
         enabled: true,
     },
+    double_loadable: true,
     srcs: ["memtrack.cpp"],
     export_include_dirs: ["include"],
     local_include_dirs: ["include"],
diff --git a/libmemunreachable/ProcessMappings.cpp b/libmemunreachable/ProcessMappings.cpp
index 701ce16..8e1be4c 100644
--- a/libmemunreachable/ProcessMappings.cpp
+++ b/libmemunreachable/ProcessMappings.cpp
@@ -18,6 +18,7 @@
 #include <fcntl.h>
 #include <inttypes.h>
 #include <string.h>
+#include <sys/types.h>
 #include <unistd.h>
 
 #include <android-base/unique_fd.h>
@@ -30,7 +31,8 @@
 struct ReadMapCallback {
   ReadMapCallback(allocator::vector<Mapping>& mappings) : mappings_(mappings) {}
 
-  void operator()(uint64_t start, uint64_t end, uint16_t flags, uint64_t, const char* name) const {
+  void operator()(uint64_t start, uint64_t end, uint16_t flags, uint64_t, ino_t,
+                  const char* name) const {
     mappings_.emplace_back(start, end, flags & PROT_READ, flags & PROT_WRITE, flags & PROT_EXEC,
                            name);
   }
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/OWNERS b/libnativebridge/OWNERS
index 6f0824b..daf87f4 100644
--- a/libnativebridge/OWNERS
+++ b/libnativebridge/OWNERS
@@ -1,2 +1,4 @@
 dimitry@google.com
 eaeltsin@google.com
+ngeoffray@google.com
+oth@google.com
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 1ec21e9..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,14 +25,6 @@
         "libnativebridge",
         "libbase",
     ],
-    cflags: [
-        "-Werror",
-        "-Wall",
-    ],
-    cppflags: [
-        "-fvisibility=hidden",
-    ],
-    export_include_dirs: ["include"],
     required: [
         "llndk.libraries.txt",
         "vndksp.libraries.txt",
@@ -29,9 +35,25 @@
     },
 }
 
+// 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-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 5394d7e..09998f0 100644
--- a/libnativeloader/native_loader.cpp
+++ b/libnativeloader/native_loader.cpp
@@ -137,6 +137,12 @@
 
 static constexpr const char* kApexPath = "/apex/";
 
+#if defined(__LP64__)
+static constexpr const char* kRuntimeApexLibPath = "/apex/com.android.runtime/lib64";
+#else
+static constexpr const char* kRuntimeApexLibPath = "/apex/com.android.runtime/lib";
+#endif
+
 static bool is_debuggable() {
   char debuggable[PROP_VALUE_MAX];
   property_get("ro.debuggable", debuggable, "0");
@@ -408,6 +414,14 @@
       }
     }
 
+    // Remove the public libs in the runtime namespace.
+    // These libs are listed in public.android.txt, but we don't want the rest of android
+    // in default namespace to dlopen the libs.
+    // For example, libicuuc.so is exposed to classloader namespace from runtime namespace.
+    // Unfortunately, it does not have stable C symbols, and default namespace should only use
+    // stable symbols in libandroidicu.so. http://b/120786417
+    removePublicLibsIfExistsInRuntimeApex(sonames);
+
     // android_init_namespaces() expects all the public libraries
     // to be loaded so that they can be found by soname alone.
     //
@@ -502,6 +516,27 @@
     }
   }
 
+  /**
+   * Remove the public libs in runtime namespace
+   */
+  void removePublicLibsIfExistsInRuntimeApex(std::vector<std::string>& sonames) {
+    for (const std::string& lib_name : kRuntimePublicLibraries) {
+      std::string path(kRuntimeApexLibPath);
+      path.append("/").append(lib_name);
+
+      struct stat s;
+      // Do nothing if the path in /apex does not exist.
+      // Runtime APEX must be mounted since libnativeloader is in the same APEX
+      if (stat(path.c_str(), &s) != 0) {
+        continue;
+      }
+
+      auto it = std::find(sonames.begin(), sonames.end(), lib_name);
+      if (it != sonames.end()) {
+        sonames.erase(it);
+      }
+    }
+  }
 
   bool ReadConfig(const std::string& configFile, std::vector<std::string>* sonames,
                   const std::function<bool(const std::string& /* soname */,
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/libpixelflinger/include/private/pixelflinger/ggl_fixed.h b/libpixelflinger/include/private/pixelflinger/ggl_fixed.h
index 7f39e9b..4217a89 100644
--- a/libpixelflinger/include/private/pixelflinger/ggl_fixed.h
+++ b/libpixelflinger/include/private/pixelflinger/ggl_fixed.h
@@ -107,7 +107,7 @@
 
 // inline ARM implementations
 inline GGLfixed gglMulx(GGLfixed x, GGLfixed y, int shift) CONST;
-inline GGLfixed gglMulx(GGLfixed x, GGLfixed y, int shift) {
+__attribute__((always_inline)) inline GGLfixed gglMulx(GGLfixed x, GGLfixed y, int shift) {
     GGLfixed result, t;
     if (__builtin_constant_p(shift)) {
     asm("smull  %[lo], %[hi], %[x], %[y]            \n"
@@ -130,7 +130,8 @@
 }
 
 inline GGLfixed gglMulAddx(GGLfixed x, GGLfixed y, GGLfixed a, int shift) CONST;
-inline GGLfixed gglMulAddx(GGLfixed x, GGLfixed y, GGLfixed a, int shift) {
+__attribute__((always_inline)) inline GGLfixed gglMulAddx(GGLfixed x, GGLfixed y, GGLfixed a,
+                                                          int shift) {
     GGLfixed result, t;
     if (__builtin_constant_p(shift)) {
     asm("smull  %[lo], %[hi], %[x], %[y]            \n"
diff --git a/libprocessgroup/cgroup_map.cpp b/libprocessgroup/cgroup_map.cpp
index cd8ef94..d094811 100644
--- a/libprocessgroup/cgroup_map.cpp
+++ b/libprocessgroup/cgroup_map.cpp
@@ -126,22 +126,26 @@
         return false;
     }
 
-    Json::Value cgroups = root["Cgroups"];
-    for (Json::Value::ArrayIndex i = 0; i < cgroups.size(); ++i) {
-        std::string name = cgroups[i]["Controller"].asString();
-        descriptors->emplace(std::make_pair(
-                name,
-                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())));
+    if (root.isMember("Cgroups")) {
+        const Json::Value& cgroups = root["Cgroups"];
+        for (Json::Value::ArrayIndex i = 0; i < cgroups.size(); ++i) {
+            std::string name = cgroups[i]["Controller"].asString();
+            descriptors->emplace(std::make_pair(
+                    name,
+                    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())));
+        }
     }
 
-    Json::Value cgroups2 = root["Cgroups2"];
-    descriptors->emplace(std::make_pair(
-            CGROUPV2_CONTROLLER_NAME,
-            CgroupDescriptor(2, CGROUPV2_CONTROLLER_NAME, cgroups2["Path"].asString(),
-                             std::strtoul(cgroups2["Mode"].asString().c_str(), 0, 8),
-                             cgroups2["UID"].asString(), cgroups2["GID"].asString())));
+    if (root.isMember("Cgroups2")) {
+        const Json::Value& cgroups2 = root["Cgroups2"];
+        descriptors->emplace(std::make_pair(
+                CGROUPV2_CONTROLLER_NAME,
+                CgroupDescriptor(2, CGROUPV2_CONTROLLER_NAME, cgroups2["Path"].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 447852d..b69103c 100644
--- a/libprocessgroup/task_profiles.cpp
+++ b/libprocessgroup/task_profiles.cpp
@@ -90,6 +90,10 @@
     if (sys_supports_timerslack) {
         auto file = StringPrintf("/proc/%d/timerslack_ns", tid);
         if (!WriteStringToFile(std::to_string(slack_), file)) {
+            if (errno == ENOENT) {
+                // This happens when process is already dead
+                return true;
+            }
             PLOG(ERROR) << "set_timerslack_ns write failed";
         }
     }
diff --git a/libprocinfo/Android.bp b/libprocinfo/Android.bp
index 15f03d0..27cda93 100644
--- a/libprocinfo/Android.bp
+++ b/libprocinfo/Android.bp
@@ -31,6 +31,7 @@
     vndk: {
         enabled: true,
     },
+    double_loadable: true,
     host_supported: true,
     srcs: [
         "process.cpp",
diff --git a/libprocinfo/include/procinfo/process_map.h b/libprocinfo/include/procinfo/process_map.h
index 981241e..b6ec3cb 100644
--- a/libprocinfo/include/procinfo/process_map.h
+++ b/libprocinfo/include/procinfo/process_map.h
@@ -36,6 +36,7 @@
   uint64_t end_addr;
   uint16_t flags;
   uint64_t pgoff;
+  ino_t inode;
   char* next_line = content;
   char* p;
 
@@ -124,18 +125,25 @@
       return false;
     }
     // inode
-    if (!pass_xdigit() || (*p != '\0' && !pass_space())) {
+    inode = strtoull(p, &end, 10);
+    if (end == p) {
       return false;
     }
+    p = end;
+
+    if (*p != '\0' && !pass_space()) {
+      return false;
+    }
+
     // filename
-    callback(start_addr, end_addr, flags, pgoff, p);
+    callback(start_addr, end_addr, flags, pgoff, inode, p);
   }
   return true;
 }
 
-inline bool ReadMapFile(
-    const std::string& map_file,
-    const std::function<void(uint64_t, uint64_t, uint16_t, uint64_t, const char*)>& callback) {
+inline bool ReadMapFile(const std::string& map_file,
+                        const std::function<void(uint64_t, uint64_t, uint16_t, uint64_t, ino_t,
+                                                 const char*)>& callback) {
   std::string content;
   if (!android::base::ReadFileToString(map_file, &content)) {
     return false;
@@ -143,9 +151,9 @@
   return ReadMapFileContent(&content[0], callback);
 }
 
-inline bool ReadProcessMaps(
-    pid_t pid,
-    const std::function<void(uint64_t, uint64_t, uint16_t, uint64_t, const char*)>& callback) {
+inline bool ReadProcessMaps(pid_t pid,
+                            const std::function<void(uint64_t, uint64_t, uint16_t, uint64_t, ino_t,
+                                                     const char*)>& callback) {
   return ReadMapFile("/proc/" + std::to_string(pid) + "/maps", callback);
 }
 
@@ -154,17 +162,18 @@
   uint64_t end;
   uint16_t flags;
   uint64_t pgoff;
+  ino_t inode;
   std::string name;
 
-  MapInfo(uint64_t start, uint64_t end, uint16_t flags, uint64_t pgoff, const char* name)
-      : start(start), end(end), flags(flags), pgoff(pgoff), name(name) {}
+  MapInfo(uint64_t start, uint64_t end, uint16_t flags, uint64_t pgoff, ino_t inode,
+          const char* name)
+      : start(start), end(end), flags(flags), pgoff(pgoff), inode(inode), name(name) {}
 };
 
 inline bool ReadProcessMaps(pid_t pid, std::vector<MapInfo>* maps) {
   return ReadProcessMaps(
-      pid, [&](uint64_t start, uint64_t end, uint16_t flags, uint64_t pgoff, const char* name) {
-        maps->emplace_back(start, end, flags, pgoff, name);
-      });
+      pid, [&](uint64_t start, uint64_t end, uint16_t flags, uint64_t pgoff, ino_t inode,
+               const char* name) { maps->emplace_back(start, end, flags, pgoff, inode, name); });
 }
 
 } /* namespace procinfo */
diff --git a/libprocinfo/process_map_benchmark.cpp b/libprocinfo/process_map_benchmark.cpp
index 04995d4..eba4fd0 100644
--- a/libprocinfo/process_map_benchmark.cpp
+++ b/libprocinfo/process_map_benchmark.cpp
@@ -17,6 +17,7 @@
 #include <procinfo/process_map.h>
 
 #include <string.h>
+#include <sys/types.h>
 
 #include <string>
 
@@ -31,9 +32,10 @@
   std::string map_file = android::base::GetExecutableDirectory() + "/testdata/maps";
   for (auto _ : state) {
     std::vector<android::procinfo::MapInfo> maps;
-    android::procinfo::ReadMapFile(
-        map_file, [&](uint64_t start, uint64_t end, uint16_t flags, uint64_t pgoff,
-                      const char* name) { maps.emplace_back(start, end, flags, pgoff, name); });
+    android::procinfo::ReadMapFile(map_file, [&](uint64_t start, uint64_t end, uint16_t flags,
+                                                 uint64_t pgoff, ino_t inode, const char* name) {
+      maps.emplace_back(start, end, flags, pgoff, inode, name);
+    });
     CHECK_EQ(maps.size(), 2043u);
   }
 }
diff --git a/libprocinfo/process_map_test.cpp b/libprocinfo/process_map_test.cpp
index 170a806..562d864 100644
--- a/libprocinfo/process_map_test.cpp
+++ b/libprocinfo/process_map_test.cpp
@@ -26,23 +26,27 @@
   std::string map_file = android::base::GetExecutableDirectory() + "/testdata/maps";
   std::vector<android::procinfo::MapInfo> maps;
   ASSERT_TRUE(android::procinfo::ReadMapFile(
-      map_file, [&](uint64_t start, uint64_t end, uint16_t flags, uint64_t pgoff,
-                    const char* name) { maps.emplace_back(start, end, flags, pgoff, name); }));
+      map_file,
+      [&](uint64_t start, uint64_t end, uint16_t flags, uint64_t pgoff, ino_t inode,
+          const char* name) { maps.emplace_back(start, end, flags, pgoff, inode, name); }));
   ASSERT_EQ(2043u, maps.size());
   ASSERT_EQ(maps[0].start, 0x12c00000ULL);
   ASSERT_EQ(maps[0].end, 0x2ac00000ULL);
   ASSERT_EQ(maps[0].flags, PROT_READ | PROT_WRITE);
   ASSERT_EQ(maps[0].pgoff, 0ULL);
+  ASSERT_EQ(maps[0].inode, 10267643UL);
   ASSERT_EQ(maps[0].name, "[anon:dalvik-main space (region space)]");
   ASSERT_EQ(maps[876].start, 0x70e6c4f000ULL);
   ASSERT_EQ(maps[876].end, 0x70e6c6b000ULL);
   ASSERT_EQ(maps[876].flags, PROT_READ | PROT_EXEC);
   ASSERT_EQ(maps[876].pgoff, 0ULL);
+  ASSERT_EQ(maps[876].inode, 2407UL);
   ASSERT_EQ(maps[876].name, "/system/lib64/libutils.so");
   ASSERT_EQ(maps[1260].start, 0x70e96fa000ULL);
   ASSERT_EQ(maps[1260].end, 0x70e96fb000ULL);
   ASSERT_EQ(maps[1260].flags, PROT_READ);
   ASSERT_EQ(maps[1260].pgoff, 0ULL);
+  ASSERT_EQ(maps[1260].inode, 10266154UL);
   ASSERT_EQ(maps[1260].name,
             "[anon:dalvik-classes.dex extracted in memory from "
             "/data/app/com.google.sample.tunnel-HGGRU03Gu1Mwkf_-RnFmvw==/base.apk]");
@@ -51,8 +55,9 @@
 TEST(process_map, ReadProcessMaps) {
   std::vector<android::procinfo::MapInfo> maps;
   ASSERT_TRUE(android::procinfo::ReadProcessMaps(
-      getpid(), [&](uint64_t start, uint64_t end, uint16_t flags, uint64_t pgoff,
-                    const char* name) { maps.emplace_back(start, end, flags, pgoff, name); }));
+      getpid(),
+      [&](uint64_t start, uint64_t end, uint16_t flags, uint64_t pgoff, ino_t inode,
+          const char* name) { maps.emplace_back(start, end, flags, pgoff, inode, name); }));
   ASSERT_GT(maps.size(), 0u);
   maps.clear();
   ASSERT_TRUE(android::procinfo::ReadProcessMaps(getpid(), &maps));
diff --git a/libsysutils/include/sysutils/OWNERS b/libsysutils/include/sysutils/OWNERS
index 645baf4..4c99361 100644
--- a/libsysutils/include/sysutils/OWNERS
+++ b/libsysutils/include/sysutils/OWNERS
@@ -1 +1,2 @@
-per-file OWNERS,Netlink* = ek@google.com,lorenzo@google.com
+include ../../src/OWNERS
+
diff --git a/libsysutils/src/OWNERS b/libsysutils/src/OWNERS
index 645baf4..c65a40d 100644
--- a/libsysutils/src/OWNERS
+++ b/libsysutils/src/OWNERS
@@ -1 +1,2 @@
-per-file OWNERS,Netlink* = ek@google.com,lorenzo@google.com
+per-file OWNERS,Netlink* = codewiz@google.com, jchalard@google.com, lorenzo@google.com, satk@google.com
+
diff --git a/libunwindstack/Maps.cpp b/libunwindstack/Maps.cpp
index c90e383..1e4f72e 100644
--- a/libunwindstack/Maps.cpp
+++ b/libunwindstack/Maps.cpp
@@ -62,7 +62,7 @@
 bool Maps::Parse() {
   return android::procinfo::ReadMapFile(
       GetMapsFile(),
-      [&](uint64_t start, uint64_t end, uint16_t flags, uint64_t pgoff, const char* name) {
+      [&](uint64_t start, uint64_t end, uint16_t flags, uint64_t pgoff, ino_t, const char* name) {
         // Mark a device map in /dev/ and not in /dev/ashmem/ specially.
         if (strncmp(name, "/dev/", 5) == 0 && strncmp(name + 5, "ashmem/", 7) != 0) {
           flags |= unwindstack::MAPS_FLAGS_DEVICE_MAP;
@@ -102,7 +102,7 @@
   std::string content(buffer_);
   return android::procinfo::ReadMapFileContent(
       &content[0],
-      [&](uint64_t start, uint64_t end, uint16_t flags, uint64_t pgoff, const char* name) {
+      [&](uint64_t start, uint64_t end, uint16_t flags, uint64_t pgoff, ino_t, const char* name) {
         // Mark a device map in /dev/ and not in /dev/ashmem/ specially.
         if (strncmp(name, "/dev/", 5) == 0 && strncmp(name + 5, "ashmem/", 7) != 0) {
           flags |= unwindstack::MAPS_FLAGS_DEVICE_MAP;
diff --git a/libusbhost/Android.bp b/libusbhost/Android.bp
index fc6f305..39bf3a5 100644
--- a/libusbhost/Android.bp
+++ b/libusbhost/Android.bp
@@ -20,6 +20,7 @@
     vndk: {
         enabled: true,
     },
+    double_loadable: true,
     host_supported: true,
     srcs: ["usbhost.c"],
     cflags: ["-Werror"],
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/include/vndksupport/linker.h b/libvndksupport/include/vndksupport/linker.h
index f509564..5f48c39 100644
--- a/libvndksupport/include/vndksupport/linker.h
+++ b/libvndksupport/include/vndksupport/linker.h
@@ -20,6 +20,16 @@
 extern "C" {
 #endif
 
+/*
+ * Returns whether the current process is a vendor process.
+ *
+ * Note that this is only checking what process is running and has nothing to
+ * do with what namespace the caller is loaded at.  For example, a VNDK-SP
+ * library loaded by SP-HAL calling this function may still get a 'false',
+ * because it is running in a system process.
+ */
+int android_is_in_vendor_process();
+
 void* android_load_sphal_library(const char* name, int flag);
 
 int android_unload_sphal_library(void* handle);
diff --git a/libvndksupport/libvndksupport.map.txt b/libvndksupport/libvndksupport.map.txt
index 16e38da..ac9a99c 100644
--- a/libvndksupport/libvndksupport.map.txt
+++ b/libvndksupport/libvndksupport.map.txt
@@ -1,7 +1,8 @@
 LIBVNDKSUPPORT {
   global:
-    android_load_sphal_library; # vndk
-    android_unload_sphal_library; # vndk
+    android_is_in_vendor_process; # vndk apex
+    android_load_sphal_library; # vndk apex
+    android_unload_sphal_library; # vndk apex
   local:
     *;
 };
diff --git a/libvndksupport/linker.c b/libvndksupport/linker.c
index bc5620b..821940a 100644
--- a/libvndksupport/linker.c
+++ b/libvndksupport/linker.c
@@ -45,6 +45,17 @@
     return vendor_namespace;
 }
 
+int android_is_in_vendor_process() {
+    if (android_get_exported_namespace == NULL) {
+        ALOGD("android_get_exported_namespace() not available. Assuming system process.");
+        return 0;
+    }
+
+    // In vendor process, 'vndk' namespace is not visible, whereas in system
+    // process, it is.
+    return android_get_exported_namespace("vndk") == NULL;
+}
+
 void* android_load_sphal_library(const char* name, int flag) {
     struct android_namespace_t* vendor_namespace = get_vendor_namespace();
     if (vendor_namespace != NULL) {
diff --git a/libziparchive/Android.bp b/libziparchive/Android.bp
index 9538bba..cbca1ce 100644
--- a/libziparchive/Android.bp
+++ b/libziparchive/Android.bp
@@ -126,6 +126,7 @@
         },
     },
     test_suites: ["device-tests"],
+    test_config: "ziparchive-tests.xml",  // TODO: Remove after b/117891984.
 }
 
 // Performance benchmarks.
diff --git a/libziparchive/ziparchive-tests.xml b/libziparchive/ziparchive-tests.xml
new file mode 100644
index 0000000..2be0a99
--- /dev/null
+++ b/libziparchive/ziparchive-tests.xml
@@ -0,0 +1,30 @@
+<?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.
+-->
+<!-- Derived from auto-generated config. b/117891984 & b/124515549. -->
+<configuration description="Runs ziparchive-tests.">
+    <option name="test-suite-tag" value="apct" />
+    <option name="test-suite-tag" value="apct-native" />
+    <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+        <option name="cleanup" value="true" />
+        <option name="push" value="ziparchive-tests->/data/local/tmp/ziparchive-tests/ziparchive-tests" />
+        <option name="push" value="testdata->/data/local/tmp/ziparchive-tests/testdata" />
+    </target_preparer>
+
+    <test class="com.android.tradefed.testtype.GTest" >
+        <option name="native-test-device-path" value="/data/local/tmp/ziparchive-tests" />
+        <option name="module-name" value="ziparchive-tests" />
+    </test>
+</configuration>
diff --git a/lmkd/include/lmkd.h b/lmkd/include/lmkd.h
index e72d159..59377dd 100644
--- a/lmkd/include/lmkd.h
+++ b/lmkd/include/lmkd.h
@@ -50,7 +50,7 @@
 typedef int LMKD_CTRL_PACKET[CTRL_PACKET_MAX_SIZE / sizeof(int)];
 
 /* Get LMKD packet command */
-inline enum lmk_cmd lmkd_pack_get_cmd(LMKD_CTRL_PACKET pack) {
+static inline enum lmk_cmd lmkd_pack_get_cmd(LMKD_CTRL_PACKET pack) {
     return (enum lmk_cmd)ntohl(pack[0]);
 }
 
@@ -64,8 +64,8 @@
  * For LMK_TARGET packet get target_idx-th payload.
  * Warning: no checks performed, caller should ensure valid parameters.
  */
-inline void lmkd_pack_get_target(LMKD_CTRL_PACKET packet,
-                                 int target_idx, struct lmk_target *target) {
+static inline void lmkd_pack_get_target(LMKD_CTRL_PACKET packet, int target_idx,
+                                        struct lmk_target* target) {
     target->minfree = ntohl(packet[target_idx * 2 + 1]);
     target->oom_adj_score = ntohl(packet[target_idx * 2 + 2]);
 }
@@ -74,9 +74,8 @@
  * Prepare LMK_TARGET packet and return packet size in bytes.
  * Warning: no checks performed, caller should ensure valid parameters.
  */
-inline size_t lmkd_pack_set_target(LMKD_CTRL_PACKET packet,
-                                   struct lmk_target *targets,
-                                   size_t target_cnt) {
+static inline size_t lmkd_pack_set_target(LMKD_CTRL_PACKET packet, struct lmk_target* targets,
+                                          size_t target_cnt) {
     int idx = 0;
     packet[idx++] = htonl(LMK_TARGET);
     while (target_cnt) {
@@ -99,8 +98,7 @@
  * For LMK_PROCPRIO packet get its payload.
  * Warning: no checks performed, caller should ensure valid parameters.
  */
-inline void lmkd_pack_get_procprio(LMKD_CTRL_PACKET packet,
-                                   struct lmk_procprio *params) {
+static inline void lmkd_pack_get_procprio(LMKD_CTRL_PACKET packet, struct lmk_procprio* params) {
     params->pid = (pid_t)ntohl(packet[1]);
     params->uid = (uid_t)ntohl(packet[2]);
     params->oomadj = ntohl(packet[3]);
@@ -110,8 +108,7 @@
  * Prepare LMK_PROCPRIO packet and return packet size in bytes.
  * Warning: no checks performed, caller should ensure valid parameters.
  */
-inline size_t lmkd_pack_set_procprio(LMKD_CTRL_PACKET packet,
-                                   struct lmk_procprio *params) {
+static inline size_t lmkd_pack_set_procprio(LMKD_CTRL_PACKET packet, struct lmk_procprio* params) {
     packet[0] = htonl(LMK_PROCPRIO);
     packet[1] = htonl(params->pid);
     packet[2] = htonl(params->uid);
@@ -128,8 +125,8 @@
  * For LMK_PROCREMOVE packet get its payload.
  * Warning: no checks performed, caller should ensure valid parameters.
  */
-inline void lmkd_pack_get_procremove(LMKD_CTRL_PACKET packet,
-                                   struct lmk_procremove *params) {
+static inline void lmkd_pack_get_procremove(LMKD_CTRL_PACKET packet,
+                                            struct lmk_procremove* params) {
     params->pid = (pid_t)ntohl(packet[1]);
 }
 
@@ -137,8 +134,8 @@
  * Prepare LMK_PROCREMOVE packet and return packet size in bytes.
  * Warning: no checks performed, caller should ensure valid parameters.
  */
-inline size_t lmkd_pack_set_procremove(LMKD_CTRL_PACKET packet,
-                                   struct lmk_procprio *params) {
+static inline size_t lmkd_pack_set_procremove(LMKD_CTRL_PACKET packet,
+                                              struct lmk_procprio* params) {
     packet[0] = htonl(LMK_PROCREMOVE);
     packet[1] = htonl(params->pid);
     return 2 * sizeof(int);
@@ -148,7 +145,7 @@
  * Prepare LMK_PROCPURGE packet and return packet size in bytes.
  * Warning: no checks performed, caller should ensure valid parameters.
  */
-inline size_t lmkd_pack_set_procpurge(LMKD_CTRL_PACKET packet) {
+static inline size_t lmkd_pack_set_procpurge(LMKD_CTRL_PACKET packet) {
     packet[0] = htonl(LMK_PROCPURGE);
     return sizeof(int);
 }
@@ -163,8 +160,8 @@
  * For LMK_GETKILLCNT packet get its payload.
  * Warning: no checks performed, caller should ensure valid parameters.
  */
-inline void lmkd_pack_get_getkillcnt(LMKD_CTRL_PACKET packet,
-                                   struct lmk_getkillcnt *params) {
+static inline void lmkd_pack_get_getkillcnt(LMKD_CTRL_PACKET packet,
+                                            struct lmk_getkillcnt* params) {
     params->min_oomadj = ntohl(packet[1]);
     params->max_oomadj = ntohl(packet[2]);
 }
@@ -173,8 +170,8 @@
  * Prepare LMK_GETKILLCNT packet and return packet size in bytes.
  * Warning: no checks performed, caller should ensure valid parameters.
  */
-inline size_t lmkd_pack_set_getkillcnt(LMKD_CTRL_PACKET packet,
-                                       struct lmk_getkillcnt *params) {
+static inline size_t lmkd_pack_set_getkillcnt(LMKD_CTRL_PACKET packet,
+                                              struct lmk_getkillcnt* params) {
     packet[0] = htonl(LMK_GETKILLCNT);
     packet[1] = htonl(params->min_oomadj);
     packet[2] = htonl(params->max_oomadj);
@@ -185,7 +182,7 @@
  * Prepare LMK_GETKILLCNT reply packet and return packet size in bytes.
  * Warning: no checks performed, caller should ensure valid parameters.
  */
-inline size_t lmkd_pack_set_getkillcnt_repl(LMKD_CTRL_PACKET packet, int kill_cnt) {
+static inline size_t lmkd_pack_set_getkillcnt_repl(LMKD_CTRL_PACKET packet, int kill_cnt) {
     packet[0] = htonl(LMK_GETKILLCNT);
     packet[1] = htonl(kill_cnt);
     return 2 * sizeof(int);
diff --git a/rootdir/Android.mk b/rootdir/Android.mk
index cbbc710..b5e5a71 100644
--- a/rootdir/Android.mk
+++ b/rootdir/Android.mk
@@ -42,6 +42,23 @@
 LOCAL_POST_INSTALL_CMD = mkdir -p $(TARGET_OUT)/usr && rm -rf $(TARGET_OUT)/usr/icu
 LOCAL_POST_INSTALL_CMD += ; ln -sf /apex/com.android.runtime/etc/icu $(TARGET_OUT)/usr/icu
 
+# TODO(b/124106384): Clean up compat symlinks for ART binaries.
+ART_BINARIES= \
+  dalvikvm32 \
+  dalvikvm64 \
+  dex2oat \
+  dexdiag \
+  dexdump \
+  dexlist \
+  dexoptanalyzer \
+  oatdump \
+  profman \
+
+$(foreach b,$(ART_BINARIES), \
+  $(eval LOCAL_POST_INSTALL_CMD += \
+    ; ln -sf /apex/com.android.runtime/bin/$(b) $(TARGET_OUT)/bin/$(b)) \
+)
+
 # End of runtime APEX compatibilty.
 
 include $(BUILD_PREBUILT)
@@ -58,6 +75,16 @@
 include $(BUILD_PREBUILT)
 
 #######################################
+# cgroups.json for recovery
+include $(CLEAR_VARS)
+LOCAL_MODULE := cgroups.recovery.json
+LOCAL_SRC_FILES := $(LOCAL_MODULE)
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_PATH := $(TARGET_RECOVERY_ROOT_OUT)/system/etc
+LOCAL_MODULE_STEM := cgroups.json
+include $(BUILD_PREBUILT)
+
+#######################################
 # task_profiles.json
 include $(CLEAR_VARS)
 
diff --git a/rootdir/cgroups.recovery.json b/rootdir/cgroups.recovery.json
new file mode 100644
index 0000000..f0bf5fd
--- /dev/null
+++ b/rootdir/cgroups.recovery.json
@@ -0,0 +1,9 @@
+{
+  "Cgroups": [
+    {
+      "Controller": "cpuacct",
+      "Path": "/acct",
+      "Mode": "0555"
+    }
+  ]
+}
diff --git a/rootdir/etc/TEST_MAPPING b/rootdir/etc/TEST_MAPPING
new file mode 100644
index 0000000..e4d3d5e
--- /dev/null
+++ b/rootdir/etc/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+  "presubmit": [
+    {
+      "name": "CtsBionicTestCases"
+    }
+  ]
+}
diff --git a/rootdir/etc/ld.config.legacy.txt b/rootdir/etc/ld.config.legacy.txt
index 48ca998..2d44bb6 100644
--- a/rootdir/etc/ld.config.legacy.txt
+++ b/rootdir/etc/ld.config.legacy.txt
@@ -54,6 +54,10 @@
 namespace.default.link.runtime.shared_libs += libnativebridge.so
 namespace.default.link.runtime.shared_libs += libnativehelper.so
 namespace.default.link.runtime.shared_libs += libnativeloader.so
+namespace.default.link.runtime.shared_libs += libandroidicu.so
+
+# TODO(b/122876336): Remove libpac.so once it's migrated to Webview
+namespace.default.link.runtime.shared_libs += libpac.so
 
 # When libnetd_resolv.so can't be found in the default namespace, search for it
 # in the resolv namespace. Don't allow any other libraries from the resolv namespace
@@ -126,6 +130,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..44b7035 100644
--- a/rootdir/etc/ld.config.txt
+++ b/rootdir/etc/ld.config.txt
@@ -20,13 +20,17 @@
 dir.vendor = /data/benchmarktest/vendor
 dir.vendor = /data/benchmarktest64/vendor
 
+dir.unrestricted = /data/nativetest/unrestricted
+dir.unrestricted = /data/nativetest64/unrestricted
+
+# TODO(b/123864775): Ensure tests are run from /data/nativetest{,64} or (if
+# necessary) the unrestricted subdirs above. Then clean this up.
+dir.unrestricted = /data/local/tmp
+
 dir.system = /data/nativetest
 dir.system = /data/nativetest64
 dir.system = /data/benchmarktest
 dir.system = /data/benchmarktest64
-# TODO(b/123864775): Ensure tests are run from one of the directories above and
-# remove this.
-dir.system = /data/local/tmp
 
 dir.postinstall = /postinstall
 
@@ -128,6 +132,10 @@
 namespace.default.link.runtime.shared_libs += libnativebridge.so
 namespace.default.link.runtime.shared_libs += libnativehelper.so
 namespace.default.link.runtime.shared_libs += libnativeloader.so
+namespace.default.link.runtime.shared_libs += libandroidicu.so
+
+# TODO(b/122876336): Remove libpac.so once it's migrated to Webview
+namespace.default.link.runtime.shared_libs += libpac.so
 
 # When libnetd_resolv.so can't be found in the default namespace, search for it
 # in the resolv namespace. Don't allow any other libraries from the resolv namespace
@@ -200,6 +208,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 +417,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.
@@ -476,6 +486,111 @@
 namespace.system.link.runtime.shared_libs += libnativehelper.so
 namespace.system.link.runtime.shared_libs += libnativeloader.so
 
+
+###############################################################################
+# Namespace config for native tests that need access to both system and vendor
+# libraries. This replicates the default linker config (done by
+# init_default_namespace_no_config in bionic/linker/linker.cpp), except that it
+# includes the requisite namespace setup for APEXes.
+###############################################################################
+[unrestricted]
+additional.namespaces = runtime,media,conscrypt,resolv
+
+namespace.default.search.paths  = /system/${LIB}
+namespace.default.search.paths += /odm/${LIB}
+namespace.default.search.paths += /vendor/${LIB}
+
+namespace.default.asan.search.paths  = /data/asan/system/${LIB}
+namespace.default.asan.search.paths +=           /system/${LIB}
+namespace.default.asan.search.paths += /data/asan/odm/${LIB}
+namespace.default.asan.search.paths +=           /odm/${LIB}
+namespace.default.asan.search.paths += /data/asan/vendor/${LIB}
+namespace.default.asan.search.paths +=           /vendor/${LIB}
+
+# Keep in sync with ld.config.txt in the com.android.runtime APEX.
+namespace.default.links = runtime,resolv
+namespace.default.visible = true
+
+namespace.default.link.runtime.shared_libs  = libart.so:libartd.so
+namespace.default.link.runtime.shared_libs += libdexfile_external.so
+namespace.default.link.runtime.shared_libs += libnativebridge.so
+namespace.default.link.runtime.shared_libs += libnativehelper.so
+namespace.default.link.runtime.shared_libs += libnativeloader.so
+namespace.default.link.runtime.shared_libs += libandroidicu.so
+
+# TODO(b/122876336): Remove libpac.so once it's migrated to Webview
+namespace.default.link.runtime.shared_libs += libpac.so
+
+namespace.default.link.resolv.shared_libs = libnetd_resolv.so
+
+###############################################################################
+# "runtime" APEX namespace
+#
+# This namespace exposes externally accessible libraries from the Runtime APEX.
+###############################################################################
+namespace.runtime.isolated = true
+namespace.runtime.visible = true
+
+# 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.
+namespace.runtime.link.default.allow_all_shared_libs = true
+
+###############################################################################
+# "media" APEX namespace
+#
+# This namespace is for libraries within the media APEX.
+###############################################################################
+namespace.media.isolated = true
+namespace.media.visible = true
+
+namespace.media.search.paths = /apex/com.android.media/${LIB}
+namespace.media.asan.search.paths = /apex/com.android.media/${LIB}
+
+namespace.media.links = default
+namespace.media.link.default.shared_libs  = %LLNDK_LIBRARIES%
+namespace.media.link.default.shared_libs += libandroid.so
+namespace.media.link.default.shared_libs += libbinder_ndk.so
+namespace.media.link.default.shared_libs += libmediametrics.so
+namespace.media.link.default.shared_libs += %SANITIZER_RUNTIME_LIBRARIES%
+
+###############################################################################
+# "conscrypt" APEX namespace
+#
+# This namespace is for libraries within the conscrypt APEX.
+###############################################################################
+namespace.conscrypt.isolated = true
+namespace.conscrypt.visible = true
+
+# Keep in sync with ld.config.txt in the com.android.runtime APEX.
+namespace.conscrypt.search.paths = /apex/com.android.conscrypt/${LIB}
+namespace.conscrypt.asan.search.paths = /apex/com.android.conscrypt/${LIB}
+namespace.conscrypt.links = runtime,default
+namespace.conscrypt.link.runtime.shared_libs  = libjavacore.so
+namespace.conscrypt.link.default.shared_libs  = libc.so
+namespace.conscrypt.link.default.shared_libs += libm.so
+namespace.conscrypt.link.default.shared_libs += libdl.so
+
+###############################################################################
+# "resolv" APEX namespace
+#
+# This namespace is for libraries within the resolv APEX.
+###############################################################################
+namespace.resolv.isolated = true
+namespace.resolv.visible = true
+
+namespace.resolv.search.paths = /apex/com.android.resolv/${LIB}
+namespace.resolv.asan.search.paths = /apex/com.android.resolv/${LIB}
+namespace.resolv.links = default
+namespace.resolv.link.default.shared_libs  = libc.so
+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 config for binaries under /postinstall.
 # Only default namespace is defined and default has no directories
diff --git a/rootdir/etc/ld.config.vndk_lite.txt b/rootdir/etc/ld.config.vndk_lite.txt
index 1904445..92f287c 100644
--- a/rootdir/etc/ld.config.vndk_lite.txt
+++ b/rootdir/etc/ld.config.vndk_lite.txt
@@ -72,6 +72,10 @@
 namespace.default.link.runtime.shared_libs += libnativebridge.so
 namespace.default.link.runtime.shared_libs += libnativehelper.so
 namespace.default.link.runtime.shared_libs += libnativeloader.so
+namespace.default.link.runtime.shared_libs += libandroidicu.so
+
+# TODO(b/122876336): Remove libpac.so once it's migrated to Webview
+namespace.default.link.runtime.shared_libs += libpac.so
 
 # When libnetd_resolv.so can't be found in the default namespace, search for it
 # in the resolv namespace. Don't allow any other libraries from the resolv namespace
@@ -145,6 +149,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 +310,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 +328,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 +336,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 +354,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.environ.rc.in b/rootdir/init.environ.rc.in
index d10f7c1..d5665f2 100644
--- a/rootdir/init.environ.rc.in
+++ b/rootdir/init.environ.rc.in
@@ -1,5 +1,5 @@
 # set up the global environment
-on init
+on early-init
     export ANDROID_BOOTLOGO 1
     export ANDROID_ROOT /system
     export ANDROID_ASSETS /system/app
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 57032bc..8bd7c4c 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -538,7 +538,7 @@
     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
+    mkdir /data/pkg_staging 0750 system system
 
     # NFC: create data/nfc for nv storage
     mkdir /data/nfc 0770 nfc nfc