Merge "vts test for /proc/<pid>/smaps_rollup"
diff --git a/base/mapped_file.cpp b/base/mapped_file.cpp
index f7901af..faa845d 100644
--- a/base/mapped_file.cpp
+++ b/base/mapped_file.cpp
@@ -16,6 +16,8 @@
 
 #include "android-base/mapped_file.h"
 
+#include <errno.h>
+
 namespace android {
 namespace base {
 
@@ -50,7 +52,14 @@
       new MappedFile{static_cast<char*>(base), length, slop, handle});
 #else
   void* base = mmap(nullptr, file_length, prot, MAP_SHARED, fd, file_offset);
-  if (base == MAP_FAILED) return nullptr;
+  if (base == MAP_FAILED) {
+    // http://b/119818070 "app crashes when reading asset of zero length".
+    // mmap fails with EINVAL for a zero length region.
+    if (errno == EINVAL && length == 0) {
+      return std::unique_ptr<MappedFile>(new MappedFile{nullptr, 0, 0});
+    }
+    return nullptr;
+  }
   return std::unique_ptr<MappedFile>(new MappedFile{static_cast<char*>(base), length, slop});
 #endif
 }
diff --git a/base/mapped_file_test.cpp b/base/mapped_file_test.cpp
index 7e89723..cfde73c 100644
--- a/base/mapped_file_test.cpp
+++ b/base/mapped_file_test.cpp
@@ -25,7 +25,6 @@
 #include <string>
 
 #include "android-base/file.h"
-#include "android-base/unique_fd.h"
 
 TEST(mapped_file, smoke) {
   TemporaryFile tf;
@@ -37,3 +36,13 @@
   ASSERT_EQ('l', m->data()[0]);
   ASSERT_EQ('o', m->data()[1]);
 }
+
+TEST(mapped_file, zero_length_mapping) {
+  // http://b/119818070 "app crashes when reading asset of zero length".
+  // mmap fails with EINVAL for a zero length region.
+  TemporaryFile tf;
+  ASSERT_TRUE(tf.fd != -1);
+
+  auto m = android::base::MappedFile::FromFd(tf.fd, 4096, 0, PROT_READ);
+  ASSERT_EQ(0u, m->size());
+}
diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp
index c878b21..e684293 100644
--- a/fs_mgr/fs_mgr.cpp
+++ b/fs_mgr/fs_mgr.cpp
@@ -378,7 +378,7 @@
 // Set the number of reserved filesystem blocks if needed.
 static void tune_reserved_size(const std::string& blk_device, const FstabEntry& entry,
                                const struct ext4_super_block* sb, int* fs_stat) {
-    if (!entry.fs_mgr_flags.reserved_size) {
+    if (entry.reserved_size != 0) {
         return;
     }
 
@@ -551,7 +551,7 @@
     }
 
     if (is_extfs(entry.fs_type) &&
-        (entry.fs_mgr_flags.reserved_size || entry.fs_mgr_flags.file_encryption ||
+        (entry.reserved_size != 0 || entry.fs_mgr_flags.file_encryption ||
          entry.fs_mgr_flags.fs_verity)) {
         struct ext4_super_block sb;
 
@@ -806,7 +806,7 @@
 }
 
 static bool should_use_metadata_encryption(const FstabEntry& entry) {
-    return entry.fs_mgr_flags.key_directory &&
+    return !entry.key_dir.empty() &&
            (entry.fs_mgr_flags.file_encryption || entry.fs_mgr_flags.force_fde_or_fbe);
 }
 
@@ -1374,18 +1374,6 @@
     return FS_MGR_DOMNT_FAILED;
 }
 
-int fs_mgr_do_mount(fstab* fstab, const char* n_name, char* n_blk_device, char* tmp_mount_point) {
-    auto new_fstab = LegacyFstabToFstab(fstab);
-    return fs_mgr_do_mount_helper(&new_fstab, n_name, n_blk_device, tmp_mount_point, -1);
-}
-
-int fs_mgr_do_mount(fstab* fstab, const char* n_name, char* n_blk_device, char* tmp_mount_point,
-                    bool needs_checkpoint) {
-    auto new_fstab = LegacyFstabToFstab(fstab);
-    return fs_mgr_do_mount_helper(&new_fstab, n_name, n_blk_device, tmp_mount_point,
-                                  needs_checkpoint);
-}
-
 int fs_mgr_do_mount(Fstab* fstab, const char* n_name, char* n_blk_device, char* tmp_mount_point) {
     return fs_mgr_do_mount_helper(fstab, n_name, n_blk_device, tmp_mount_point, -1);
 }
@@ -1556,48 +1544,6 @@
     return ret;
 }
 
-struct fstab_rec const* fs_mgr_get_crypt_entry(fstab const* fstab) {
-    int i;
-
-    if (!fstab) {
-        return NULL;
-    }
-
-    /* Look for the encryptable partition to find the data */
-    for (i = 0; i < fstab->num_entries; i++) {
-        /* Don't deal with vold managed enryptable partitions here */
-        if (!(fstab->recs[i].fs_mgr_flags & MF_VOLDMANAGED) &&
-            (fstab->recs[i].fs_mgr_flags &
-             (MF_CRYPT | MF_FORCECRYPT | MF_FORCEFDEORFBE | MF_FILEENCRYPTION))) {
-            return &fstab->recs[i];
-        }
-    }
-    return NULL;
-}
-
-/*
- * key_loc must be at least PROPERTY_VALUE_MAX bytes long
- *
- * real_blk_device must be at least PROPERTY_VALUE_MAX bytes long
- */
-void fs_mgr_get_crypt_info(fstab* fstab, char* key_loc, char* real_blk_device, size_t size) {
-    struct fstab_rec const* rec = fs_mgr_get_crypt_entry(fstab);
-    if (key_loc) {
-        if (rec) {
-            strlcpy(key_loc, rec->key_loc, size);
-        } else {
-            *key_loc = '\0';
-        }
-    }
-    if (real_blk_device) {
-        if (rec) {
-            strlcpy(real_blk_device, rec->blk_device, size);
-        } else {
-            *real_blk_device = '\0';
-        }
-    }
-}
-
 bool fs_mgr_load_verity_state(int* mode) {
     /* return the default mode, unless any of the verified partitions are in
      * logging mode, in which case return that */
diff --git a/fs_mgr/fs_mgr_fstab.cpp b/fs_mgr/fs_mgr_fstab.cpp
index ee88e0d..4d44fcf 100644
--- a/fs_mgr/fs_mgr_fstab.cpp
+++ b/fs_mgr/fs_mgr_fstab.cpp
@@ -175,8 +175,8 @@
 }
 
 void ParseFsMgrFlags(const std::string& flags, FstabEntry* entry) {
-    entry->fs_mgr_flags.val = 0U;
     for (const auto& flag : Split(flags, ",")) {
+        if (flag.empty() || flag == "defaults") continue;
         std::string arg;
         if (auto equal_sign = flag.find('='); equal_sign != std::string::npos) {
             arg = flag.substr(equal_sign + 1);
@@ -239,18 +239,14 @@
             }
         } else if (StartsWith(flag, "length=")) {
             // The length flag is followed by an = and the size of the partition.
-            entry->fs_mgr_flags.length = true;
             if (!ParseInt(arg, &entry->length)) {
                 LWARNING << "Warning: length= flag malformed: " << arg;
             }
         } else if (StartsWith(flag, "swapprio=")) {
-            entry->fs_mgr_flags.swap_prio = true;
             if (!ParseInt(arg, &entry->swap_prio)) {
                 LWARNING << "Warning: length= flag malformed: " << arg;
             }
         } else if (StartsWith(flag, "zramsize=")) {
-            entry->fs_mgr_flags.zram_size = true;
-
             if (!arg.empty() && arg.back() == '%') {
                 arg.pop_back();
                 int val;
@@ -282,13 +278,11 @@
             entry->file_contents_mode = "aes-256-xts";
             entry->file_names_mode = "aes-256-cts";
         } else if (StartsWith(flag, "max_comp_streams=")) {
-            entry->fs_mgr_flags.max_comp_streams = true;
             if (!ParseInt(arg, &entry->max_comp_streams)) {
                 LWARNING << "Warning: max_comp_streams= flag malformed: " << arg;
             }
         } else if (StartsWith(flag, "reservedsize=")) {
             // The reserved flag is followed by an = and the reserved size of the partition.
-            entry->fs_mgr_flags.reserved_size = true;
             uint64_t size;
             if (!ParseByteCount(arg, &size)) {
                 LWARNING << "Warning: reservedsize= flag malformed: " << arg;
@@ -298,7 +292,6 @@
         } else if (StartsWith(flag, "eraseblk=")) {
             // The erase block size flag is followed by an = and the flash erase block size. Get it,
             // check that it is a power of 2 and at least 4096, and return it.
-            entry->fs_mgr_flags.erase_blk_size = true;
             off64_t val;
             if (!ParseInt(arg, &val) || val < 4096 || (val & (val - 1)) != 0) {
                 LWARNING << "Warning: eraseblk= flag malformed: " << arg;
@@ -308,7 +301,6 @@
         } else if (StartsWith(flag, "logicalblk=")) {
             // The logical block size flag is followed by an = and the flash logical block size. Get
             // it, check that it is a power of 2 and at least 4096, and return it.
-            entry->fs_mgr_flags.logical_blk_size = true;
             off64_t val;
             if (!ParseInt(arg, &val) || val < 4096 || (val & (val - 1)) != 0) {
                 LWARNING << "Warning: logicalblk= flag malformed: " << arg;
@@ -320,23 +312,18 @@
             entry->vbmeta_partition = arg;
         } else if (StartsWith(flag, "keydirectory=")) {
             // The metadata flag is followed by an = and the directory for the keys.
-            entry->fs_mgr_flags.key_directory = true;
             entry->key_dir = arg;
         } else if (StartsWith(flag, "sysfs_path=")) {
             // The path to trigger device gc by idle-maint of vold.
-            entry->fs_mgr_flags.sysfs = true;
             entry->sysfs_path = arg;
         } else if (StartsWith(flag, "zram_loopback_path=")) {
             // The path to use loopback for zram.
-            entry->fs_mgr_flags.zram_loopback_path = true;
             entry->zram_loopback_path = arg;
         } else if (StartsWith(flag, "zram_loopback_size=")) {
-            entry->fs_mgr_flags.zram_loopback_size = true;
             if (!ParseByteCount(arg, &entry->zram_loopback_size)) {
                 LWARNING << "Warning: zram_loopback_size= flag malformed: " << arg;
             }
         } else if (StartsWith(flag, "zram_backing_dev_path=")) {
-            entry->fs_mgr_flags.zram_backing_dev_path = true;
             entry->zram_backing_dev_path = arg;
         } else if (StartsWith(flag, "avb_key=")) {
             entry->avb_key = arg;
@@ -778,214 +765,3 @@
 
     return false;
 }
-
-// Everything from here down is deprecated and will be removed shortly.
-
-using android::fs_mgr::Fstab;
-using android::fs_mgr::FstabEntry;
-using android::fs_mgr::ReadDefaultFstab;
-using android::fs_mgr::ReadFstabFromFile;
-
-struct fstab* fs_mgr_read_fstab(const char* fstab_path) {
-    Fstab fstab;
-    if (!ReadFstabFromFile(fstab_path, &fstab)) {
-        return nullptr;
-    }
-
-    return FstabToLegacyFstab(fstab);
-}
-
-struct fstab* fs_mgr_read_fstab_default() {
-    Fstab fstab;
-    if (!ReadDefaultFstab(&fstab)) {
-        return nullptr;
-    }
-
-    return FstabToLegacyFstab(fstab);
-}
-
-void fs_mgr_free_fstab(struct fstab *fstab)
-{
-    int i;
-
-    if (!fstab) {
-        return;
-    }
-
-    for (i = 0; i < fstab->num_entries; i++) {
-        /* Free the pointers return by strdup(3) */
-        free(fstab->recs[i].blk_device);
-        free(fstab->recs[i].logical_partition_name);
-        free(fstab->recs[i].mount_point);
-        free(fstab->recs[i].fs_type);
-        free(fstab->recs[i].fs_options);
-        free(fstab->recs[i].key_loc);
-        free(fstab->recs[i].key_dir);
-        free(fstab->recs[i].label);
-        free(fstab->recs[i].file_contents_mode);
-        free(fstab->recs[i].file_names_mode);
-        free(fstab->recs[i].sysfs_path);
-        free(fstab->recs[i].zram_loopback_path);
-        free(fstab->recs[i].zram_backing_dev_path);
-    }
-
-    /* Free the fstab_recs array created by calloc(3) */
-    free(fstab->recs);
-
-    /* Free fstab */
-    free(fstab);
-}
-
-struct fstab_rec* fs_mgr_get_entry_for_mount_point(struct fstab* fstab, const std::string& path) {
-    if (!fstab) {
-        return nullptr;
-    }
-    for (int i = 0; i < fstab->num_entries; i++) {
-        if (fstab->recs[i].mount_point && path == fstab->recs[i].mount_point) {
-            return &fstab->recs[i];
-        }
-    }
-    return nullptr;
-}
-
-FstabEntry FstabRecToFstabEntry(const fstab_rec* fstab_rec) {
-    FstabEntry entry;
-    entry.blk_device = fstab_rec->blk_device;
-    entry.logical_partition_name = fstab_rec->logical_partition_name;
-    entry.mount_point = fstab_rec->mount_point;
-    entry.fs_type = fstab_rec->fs_type;
-    entry.flags = fstab_rec->flags;
-    entry.fs_options = fstab_rec->fs_options;
-    entry.fs_mgr_flags.val = fstab_rec->fs_mgr_flags;
-    entry.key_loc = fstab_rec->key_loc;
-    entry.key_dir = fstab_rec->key_dir;
-    entry.verity_loc = fstab_rec->verity_loc;
-    entry.length = fstab_rec->length;
-    entry.label = fstab_rec->label;
-    entry.partnum = fstab_rec->partnum;
-    entry.swap_prio = fstab_rec->swap_prio;
-    entry.max_comp_streams = fstab_rec->max_comp_streams;
-    entry.zram_size = fstab_rec->zram_size;
-    entry.reserved_size = fstab_rec->reserved_size;
-    entry.file_contents_mode = fstab_rec->file_contents_mode;
-    entry.file_names_mode = fstab_rec->file_names_mode;
-    entry.erase_blk_size = fstab_rec->erase_blk_size;
-    entry.logical_blk_size = fstab_rec->logical_blk_size;
-    entry.sysfs_path = fstab_rec->sysfs_path;
-    entry.zram_loopback_path = fstab_rec->zram_loopback_path;
-    entry.zram_loopback_size = fstab_rec->zram_loopback_size;
-    entry.zram_backing_dev_path = fstab_rec->zram_backing_dev_path;
-
-    return entry;
-}
-
-Fstab LegacyFstabToFstab(const struct fstab* legacy_fstab) {
-    Fstab fstab;
-    for (int i = 0; i < legacy_fstab->num_entries; i++) {
-        fstab.emplace_back(FstabRecToFstabEntry(&legacy_fstab->recs[i]));
-    }
-
-    return fstab;
-}
-
-fstab* FstabToLegacyFstab(const Fstab& fstab) {
-    struct fstab* legacy_fstab = static_cast<struct fstab*>(calloc(1, sizeof(struct fstab)));
-    legacy_fstab->num_entries = fstab.size();
-    legacy_fstab->recs =
-            static_cast<fstab_rec*>(calloc(legacy_fstab->num_entries, sizeof(fstab_rec)));
-
-    for (int i = 0; i < legacy_fstab->num_entries; i++) {
-        legacy_fstab->recs[i].blk_device = strdup(fstab[i].blk_device.c_str());
-        legacy_fstab->recs[i].logical_partition_name =
-                strdup(fstab[i].logical_partition_name.c_str());
-        legacy_fstab->recs[i].mount_point = strdup(fstab[i].mount_point.c_str());
-        legacy_fstab->recs[i].fs_type = strdup(fstab[i].fs_type.c_str());
-        legacy_fstab->recs[i].flags = fstab[i].flags;
-        legacy_fstab->recs[i].fs_options = strdup(fstab[i].fs_options.c_str());
-        legacy_fstab->recs[i].fs_mgr_flags = fstab[i].fs_mgr_flags.val;
-        legacy_fstab->recs[i].key_loc = strdup(fstab[i].key_loc.c_str());
-        legacy_fstab->recs[i].key_dir = strdup(fstab[i].key_dir.c_str());
-        legacy_fstab->recs[i].verity_loc = strdup(fstab[i].verity_loc.c_str());
-        legacy_fstab->recs[i].length = fstab[i].length;
-        legacy_fstab->recs[i].label = strdup(fstab[i].label.c_str());
-        legacy_fstab->recs[i].partnum = fstab[i].partnum;
-        legacy_fstab->recs[i].swap_prio = fstab[i].swap_prio;
-        legacy_fstab->recs[i].max_comp_streams = fstab[i].max_comp_streams;
-        legacy_fstab->recs[i].zram_size = fstab[i].zram_size;
-        legacy_fstab->recs[i].reserved_size = fstab[i].reserved_size;
-        legacy_fstab->recs[i].file_contents_mode = strdup(fstab[i].file_contents_mode.c_str());
-        legacy_fstab->recs[i].file_names_mode = strdup(fstab[i].file_names_mode.c_str());
-        legacy_fstab->recs[i].erase_blk_size = fstab[i].erase_blk_size;
-        legacy_fstab->recs[i].logical_blk_size = fstab[i].logical_blk_size;
-        legacy_fstab->recs[i].sysfs_path = strdup(fstab[i].sysfs_path.c_str());
-        legacy_fstab->recs[i].zram_loopback_path = strdup(fstab[i].zram_loopback_path.c_str());
-        legacy_fstab->recs[i].zram_loopback_size = fstab[i].zram_loopback_size;
-        legacy_fstab->recs[i].zram_backing_dev_path = strdup(fstab[i].zram_backing_dev_path.c_str());
-    }
-    return legacy_fstab;
-}
-
-int fs_mgr_is_voldmanaged(const struct fstab_rec *fstab)
-{
-    return fstab->fs_mgr_flags & MF_VOLDMANAGED;
-}
-
-int fs_mgr_is_nonremovable(const struct fstab_rec *fstab)
-{
-    return fstab->fs_mgr_flags & MF_NONREMOVABLE;
-}
-
-int fs_mgr_is_verified(const struct fstab_rec *fstab)
-{
-    return fstab->fs_mgr_flags & MF_VERIFY;
-}
-
-int fs_mgr_is_encryptable(const struct fstab_rec *fstab)
-{
-    return fstab->fs_mgr_flags & (MF_CRYPT | MF_FORCECRYPT | MF_FORCEFDEORFBE);
-}
-
-void fs_mgr_get_file_encryption_modes(const struct fstab_rec* fstab, const char** contents_mode_ret,
-                                      const char** filenames_mode_ret) {
-    *contents_mode_ret = fstab->file_contents_mode;
-    *filenames_mode_ret = fstab->file_names_mode;
-}
-
-int fs_mgr_is_convertible_to_fbe(const struct fstab_rec *fstab)
-{
-    return fstab->fs_mgr_flags & MF_FORCEFDEORFBE;
-}
-
-int fs_mgr_is_noemulatedsd(const struct fstab_rec *fstab)
-{
-    return fstab->fs_mgr_flags & MF_NOEMULATEDSD;
-}
-
-int fs_mgr_is_notrim(const struct fstab_rec* fstab) {
-    return fstab->fs_mgr_flags & MF_NOTRIM;
-}
-
-int fs_mgr_is_quota(const struct fstab_rec* fstab) {
-    return fstab->fs_mgr_flags & MF_QUOTA;
-}
-
-int fs_mgr_has_sysfs_path(const struct fstab_rec *fstab)
-{
-    return fstab->fs_mgr_flags & MF_SYSFS;
-}
-
-int fs_mgr_is_logical(const struct fstab_rec* fstab) {
-    return fstab->fs_mgr_flags & MF_LOGICAL;
-}
-
-int fs_mgr_is_checkpoint(const struct fstab_rec* fstab) {
-    return fstab->fs_mgr_flags & (MF_CHECKPOINT_FS | MF_CHECKPOINT_BLK);
-}
-
-int fs_mgr_is_checkpoint_fs(const struct fstab_rec* fstab) {
-    return fstab->fs_mgr_flags & MF_CHECKPOINT_FS;
-}
-
-int fs_mgr_is_checkpoint_blk(const struct fstab_rec* fstab) {
-    return fstab->fs_mgr_flags & MF_CHECKPOINT_BLK;
-}
diff --git a/fs_mgr/fs_mgr_overlayfs.cpp b/fs_mgr/fs_mgr_overlayfs.cpp
index c7d2cb9..b508b56 100644
--- a/fs_mgr/fs_mgr_overlayfs.cpp
+++ b/fs_mgr/fs_mgr_overlayfs.cpp
@@ -67,6 +67,13 @@
     return ret;
 }
 
+// determine if a filesystem is available
+bool fs_mgr_overlayfs_filesystem_available(const std::string& filesystem) {
+    std::string filesystems;
+    if (!android::base::ReadFileToString("/proc/filesystems", &filesystems)) return false;
+    return filesystems.find("\t" + filesystem + "\n") != std::string::npos;
+}
+
 }  // namespace
 
 #if ALLOW_ADBD_DISABLE_VERITY == 0  // If we are a user build, provide stubs
@@ -321,6 +328,7 @@
 bool fs_mgr_overlayfs_setup_one(const std::string& overlay, const std::string& mount_point,
                                 bool* change) {
     auto ret = true;
+    if (fs_mgr_overlayfs_already_mounted(mount_point)) return ret;
     auto fsrec_mount_point = overlay + "/" + android::base::Basename(mount_point) + "/";
 
     if (setfscreatecon(kOverlayfsFileContext)) {
@@ -531,7 +539,10 @@
     std::vector<std::string> mounts;
     auto verity = fs_mgr_overlayfs_verity_enabled_list();
     for (auto& entry : *fstab) {
-        if (!fs_mgr_wants_overlayfs(&entry)) continue;
+        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;
         if (std::find(verity.begin(), verity.end(), android::base::Basename(new_mount_point)) !=
@@ -625,8 +636,12 @@
 
 // Only a suggestion for _first_ try during mounting
 std::string fs_mgr_overlayfs_scratch_mount_type() {
-    if (!access(kMkF2fs.c_str(), X_OK) && fs_mgr_access("/sys/fs/f2fs")) return "f2fs";
-    if (!access(kMkExt4.c_str(), X_OK) && fs_mgr_access("/sys/fs/ext4")) return "ext4";
+    if (!access(kMkF2fs.c_str(), X_OK) && fs_mgr_overlayfs_filesystem_available("f2fs")) {
+        return "f2fs";
+    }
+    if (!access(kMkExt4.c_str(), X_OK) && fs_mgr_overlayfs_filesystem_available("ext4")) {
+        return "ext4";
+    }
     return "auto";
 }
 
@@ -657,7 +672,7 @@
     if (mnt_type == "f2fs") {
         command = kMkF2fs + " -w 4096 -f -d1 -l" + android::base::Basename(kScratchMountPoint);
     } else if (mnt_type == "ext4") {
-        command = kMkExt4 + " -b 4096 -t ext4 -m 0 -O has_journal -M " + kScratchMountPoint;
+        command = kMkExt4 + " -F -b 4096 -t ext4 -m 0 -O has_journal -M " + kScratchMountPoint;
     } else {
         errno = ESRCH;
         LERROR << mnt_type << " has no mkfs cookbook";
@@ -821,7 +836,10 @@
 
     auto scratch_can_be_mounted = true;
     for (const auto& mount_point : fs_mgr_candidate_list(fstab)) {
-        if (fs_mgr_overlayfs_already_mounted(mount_point)) continue;
+        if (fs_mgr_overlayfs_already_mounted(mount_point)) {
+            ret = true;
+            continue;
+        }
         if (scratch_can_be_mounted) {
             scratch_can_be_mounted = false;
             auto scratch_device = fs_mgr_overlayfs_scratch_device();
@@ -1002,7 +1020,7 @@
     if (fs_mgr_access("/sys/module/overlay/parameters/override_creds")) {
         return OverlayfsValidResult::kOverrideCredsRequired;
     }
-    if (!fs_mgr_access("/sys/module/overlay")) {
+    if (!fs_mgr_overlayfs_filesystem_available("overlay")) {
         return OverlayfsValidResult::kNotSupported;
     }
     struct utsname uts;
diff --git a/fs_mgr/fs_mgr_priv.h b/fs_mgr/fs_mgr_priv.h
index 83e5d7b..166c32b 100644
--- a/fs_mgr/fs_mgr_priv.h
+++ b/fs_mgr/fs_mgr_priv.h
@@ -14,8 +14,7 @@
  * limitations under the License.
  */
 
-#ifndef __CORE_FS_MGR_PRIV_H
-#define __CORE_FS_MGR_PRIV_H
+#pragma once
 
 #include <chrono>
 #include <string>
@@ -85,53 +84,6 @@
  *
  */
 
-// clang-format off
-#define MF_WAIT                  0x1
-#define MF_CHECK                 0x2
-#define MF_CRYPT                 0x4
-#define MF_NONREMOVABLE          0x8
-#define MF_VOLDMANAGED          0x10
-#define MF_LENGTH               0x20
-#define MF_RECOVERYONLY         0x40
-#define MF_SWAPPRIO             0x80
-#define MF_ZRAMSIZE            0x100
-#define MF_VERIFY              0x200
-#define MF_FORCECRYPT          0x400
-#define MF_NOEMULATEDSD        0x800 /* no emulated sdcard daemon, sd card is the only
-                                        external storage */
-#define MF_NOTRIM             0x1000
-#define MF_FILEENCRYPTION     0x2000
-#define MF_FORMATTABLE        0x4000
-#define MF_SLOTSELECT         0x8000
-#define MF_FORCEFDEORFBE     0x10000
-#define MF_LATEMOUNT         0x20000
-#define MF_NOFAIL            0x40000
-#define MF_VERIFYATBOOT      0x80000
-#define MF_MAX_COMP_STREAMS 0x100000
-#define MF_RESERVEDSIZE     0x200000
-#define MF_QUOTA            0x400000
-#define MF_ERASEBLKSIZE     0x800000
-#define MF_LOGICALBLKSIZE  0X1000000
-#define MF_AVB             0X2000000
-#define MF_KEYDIRECTORY    0X4000000
-#define MF_SYSFS           0X8000000
-#define MF_LOGICAL        0x10000000
-#define MF_CHECKPOINT_BLK 0x20000000
-#define MF_CHECKPOINT_FS  0x40000000
-#define MF_FIRST_STAGE_MOUNT \
-                          0x80000000
-#define MF_SLOTSELECT_OTHER  \
-                         0x100000000
-#define MF_ZRAM_LOOPBACK_PATH    \
-                         0x200000000
-#define MF_ZRAM_LOOPBACK_SIZE    \
-                         0x400000000
-#define MF_ZRAM_BACKING_DEV_PATH \
-                         0x800000000
-#define MF_FS_VERITY  \
-                         0x1000000000
-// clang-format on
-
 #define DM_BUF_SIZE 4096
 
 using namespace std::chrono_literals;
@@ -148,5 +100,3 @@
 const std::string& get_android_dt_dir();
 bool is_dt_compatible();
 int load_verity_state(const android::fs_mgr::FstabEntry& entry, int* mode);
-
-#endif /* __CORE_FS_MGR_PRIV_H */
diff --git a/fs_mgr/include/fs_mgr.h b/fs_mgr/include/fs_mgr.h
index 6e9f1b0..8af80a7 100644
--- a/fs_mgr/include/fs_mgr.h
+++ b/fs_mgr/include/fs_mgr.h
@@ -65,9 +65,6 @@
 #define FS_MGR_DOMNT_FAILED (-1)
 #define FS_MGR_DOMNT_BUSY (-2)
 #define FS_MGR_DOMNT_SUCCESS 0
-int fs_mgr_do_mount(fstab* fstab, const char* n_name, char* n_blk_device, char* tmp_mount_point);
-int fs_mgr_do_mount(fstab* fstab, const char* n_name, char* n_blk_device, char* tmp_mount_point,
-                    bool needs_checkpoint);
 int fs_mgr_do_mount(android::fs_mgr::Fstab* fstab, const char* n_name, char* n_blk_device,
                     char* tmp_mount_point);
 int fs_mgr_do_mount(android::fs_mgr::Fstab* fstab, const char* n_name, char* n_blk_device,
@@ -75,8 +72,6 @@
 int fs_mgr_do_mount_one(const android::fs_mgr::FstabEntry& entry,
                         const std::string& mount_point = "");
 int fs_mgr_do_tmpfs_mount(const char *n_name);
-fstab_rec const* fs_mgr_get_crypt_entry(fstab const* fstab);
-void fs_mgr_get_crypt_info(fstab* fstab, char* key_loc, char* real_blk_device, size_t size);
 bool fs_mgr_load_verity_state(int* mode);
 bool fs_mgr_update_verity_state(
         std::function<void(const std::string& mount_point, int mode)> callback);
diff --git a/fs_mgr/include_fstab/fstab/fstab.h b/fs_mgr/include_fstab/fstab/fstab.h
index a942d43..a3d9fdd 100644
--- a/fs_mgr/include_fstab/fstab/fstab.h
+++ b/fs_mgr/include_fstab/fstab/fstab.h
@@ -16,75 +16,13 @@
 
 #pragma once
 
-#include <linux/dm-ioctl.h>
-#include <stdbool.h>
 #include <stdint.h>
-#include <stdio.h>
 #include <sys/types.h>
 
 #include <set>
 #include <string>
 #include <vector>
 
-/*
- * The entries must be kept in the same order as they were seen in the fstab.
- * Unless explicitly requested, a lookup on mount point should always
- * return the 1st one.
- */
-struct fstab {
-    int num_entries;
-    struct fstab_rec* recs;
-};
-
-struct fstab_rec {
-    char* blk_device;
-    char* logical_partition_name;
-    char* mount_point;
-    char* fs_type;
-    unsigned long flags;
-    char* fs_options;
-    uint64_t fs_mgr_flags;
-    char* key_loc;
-    char* key_dir;
-    char* verity_loc;
-    off64_t length;
-    char* label;
-    int partnum;
-    int swap_prio;
-    int max_comp_streams;
-    off64_t zram_size;
-    off64_t reserved_size;
-    char* file_contents_mode;
-    char* file_names_mode;
-    off64_t erase_blk_size;
-    off64_t logical_blk_size;
-    char* sysfs_path;
-    char* zram_loopback_path;
-    uint64_t zram_loopback_size;
-    char* zram_backing_dev_path;
-};
-
-struct fstab* fs_mgr_read_fstab_default();
-struct fstab* fs_mgr_read_fstab(const char* fstab_path);
-void fs_mgr_free_fstab(struct fstab* fstab);
-
-struct fstab_rec* fs_mgr_get_entry_for_mount_point(struct fstab* fstab, const std::string& path);
-int fs_mgr_is_voldmanaged(const struct fstab_rec* fstab);
-int fs_mgr_is_nonremovable(const struct fstab_rec* fstab);
-int fs_mgr_is_verified(const struct fstab_rec* fstab);
-int fs_mgr_is_encryptable(const struct fstab_rec* fstab);
-void fs_mgr_get_file_encryption_modes(const struct fstab_rec* fstab, const char** contents_mode_ret,
-                                      const char** filenames_mode_ret);
-int fs_mgr_is_convertible_to_fbe(const struct fstab_rec* fstab);
-int fs_mgr_is_noemulatedsd(const struct fstab_rec* fstab);
-int fs_mgr_is_notrim(const struct fstab_rec* fstab);
-int fs_mgr_is_quota(const struct fstab_rec* fstab);
-int fs_mgr_is_logical(const struct fstab_rec* fstab);
-int fs_mgr_is_checkpoint(const struct fstab_rec* fstab);
-int fs_mgr_is_checkpoint_fs(const struct fstab_rec* fstab);
-int fs_mgr_is_checkpoint_blk(const struct fstab_rec* fstab);
-int fs_mgr_has_sysfs_path(const struct fstab_rec* fstab);
-
 std::string fs_mgr_get_slot_suffix();
 std::string fs_mgr_get_other_slot_suffix();
 
@@ -119,60 +57,34 @@
     std::string zram_backing_dev_path;
     std::string avb_key;
 
-    // TODO: Remove this union once fstab_rec is deprecated. It only serves as a
-    // convenient way to convert between fstab_rec::fs_mgr_flags and these bools.
-    union FsMgrFlags {
-        uint64_t val;
-        struct {
-            // bit 0
-            bool wait : 1;
-            bool check : 1;
-            bool crypt : 1;
-            bool nonremovable : 1;
-            bool vold_managed : 1;
-            bool length : 1;
-            bool recovery_only : 1;
-            bool swap_prio : 1;
-
-            // bit 8
-            bool zram_size : 1;
-            bool verify : 1;
-            bool force_crypt : 1;
-            bool no_emulated_sd : 1;  // No emulated sdcard daemon; sd card is the only external
-                                      // storage.
-            bool no_trim : 1;
-            bool file_encryption : 1;
-            bool formattable : 1;
-            bool slot_select : 1;
-
-            // bit 16
-            bool force_fde_or_fbe : 1;
-            bool late_mount : 1;
-            bool no_fail : 1;
-            bool verify_at_boot : 1;
-            bool max_comp_streams : 1;
-            bool reserved_size : 1;
-            bool quota : 1;
-            bool erase_blk_size : 1;
-
-            // bit 24
-            bool logical_blk_size : 1;
-            bool avb : 1;
-            bool key_directory : 1;
-            bool sysfs : 1;
-            bool logical : 1;
-            bool checkpoint_blk : 1;
-            bool checkpoint_fs : 1;
-            bool first_stage_mount : 1;
-
-            // bit 32
-            bool slot_select_other : 1;
-            bool zram_loopback_path : 1;
-            bool zram_loopback_size : 1;
-            bool zram_backing_dev_path : 1;
-            bool fs_verity : 1;
-        };
-    } fs_mgr_flags;
+    struct FsMgrFlags {
+        bool wait : 1;
+        bool check : 1;
+        bool crypt : 1;
+        bool nonremovable : 1;
+        bool vold_managed : 1;
+        bool recovery_only : 1;
+        bool verify : 1;
+        bool force_crypt : 1;
+        bool no_emulated_sd : 1;  // No emulated sdcard daemon; sd card is the only external
+                                  // storage.
+        bool no_trim : 1;
+        bool file_encryption : 1;
+        bool formattable : 1;
+        bool slot_select : 1;
+        bool force_fde_or_fbe : 1;
+        bool late_mount : 1;
+        bool no_fail : 1;
+        bool verify_at_boot : 1;
+        bool quota : 1;
+        bool avb : 1;
+        bool logical : 1;
+        bool checkpoint_blk : 1;
+        bool checkpoint_fs : 1;
+        bool first_stage_mount : 1;
+        bool slot_select_other : 1;
+        bool fs_verity : 1;
+    } fs_mgr_flags = {};
 
     bool is_encryptable() const {
         return fs_mgr_flags.crypt || fs_mgr_flags.force_crypt || fs_mgr_flags.force_fde_or_fbe;
@@ -180,6 +92,8 @@
 };
 
 // An Fstab is a collection of FstabEntry structs.
+// The entries must be kept in the same order as they were seen in the fstab.
+// Unless explicitly requested, a lookup on mount point should always return the 1st one.
 using Fstab = std::vector<FstabEntry>;
 
 bool ReadFstabFromFile(const std::string& path, Fstab* fstab);
@@ -195,8 +109,3 @@
 
 }  // namespace fs_mgr
 }  // namespace android
-
-// Temporary conversion functions.
-android::fs_mgr::FstabEntry FstabRecToFstabEntry(const fstab_rec* fstab_rec);
-android::fs_mgr::Fstab LegacyFstabToFstab(const struct fstab* legacy_fstab);
-fstab* FstabToLegacyFstab(const android::fs_mgr::Fstab& fstab);
diff --git a/fs_mgr/libfs_avb/TEST_MAPPING b/fs_mgr/libfs_avb/TEST_MAPPING
index dc23827..b0f36d4 100644
--- a/fs_mgr/libfs_avb/TEST_MAPPING
+++ b/fs_mgr/libfs_avb/TEST_MAPPING
@@ -1,5 +1,5 @@
 {
-  "presubmit": [
+  "postsubmit": [
     {
       "name": "libfs_avb_test",
       "host": true
diff --git a/fs_mgr/tests/adb-remount-test.sh b/fs_mgr/tests/adb-remount-test.sh
index 4d9bc61..8298bf2 100755
--- a/fs_mgr/tests/adb-remount-test.sh
+++ b/fs_mgr/tests/adb-remount-test.sh
@@ -1,4 +1,15 @@
 #! /bin/bash
+#
+# Divided into four section:
+#
+##  USAGE
+##  Helper Variables
+##  Helper Functions
+##  MAINLINE
+
+##
+##  USAGE
+##
 
 USAGE="USAGE: `basename ${0}` [-s <SerialNumber>]
 
@@ -17,20 +28,26 @@
   exit 0
 fi
 
-# Helper Variables
+##
+##  Helper Variables
+##
 
 SPACE=" "
 # A _real_ embedded tab character
 TAB="`echo | tr '\n' '\t'`"
 # A _real_ embedded escape character
 ESCAPE="`echo | tr '\n' '\033'`"
+# A _real_ embedded carriage return character
+CR="`echo | tr '\n' '\r'`"
 GREEN="${ESCAPE}[38;5;40m"
 RED="${ESCAPE}[38;5;196m"
 ORANGE="${ESCAPE}[38;5;255:165:0m"
 BLUE="${ESCAPE}[35m"
 NORMAL="${ESCAPE}[0m"
 
-# Helper functions
+##
+##  Helper Functions
+##
 
 [ "USAGE: inFastboot
 
@@ -68,6 +85,8 @@
       args="${args}${i}"
     elif [ X"${i}" != X"${i#* }" ]; then
       args="${args}'${i}'"
+    elif [ X"${i}" != X"${i#*${TAB}}" ]; then
+      args="${args}'${i}'"
     else
       args="${args}${i}"
     fi
@@ -130,16 +149,62 @@
 
 Returns: true if the reboot command succeeded" ]
 adb_reboot() {
-  adb reboot remount-test &&
+  adb reboot remount-test || true
   sleep 2
 }
 
+[ "USAGE: format_duration [<seconds>|<seconds>s|<minutes>m|<hours>h|<days>d]
+
+human readable output whole seconds, whole minutes or mm:ss" ]
+format_duration() {
+  if [ -z "${1}" ]; then
+    echo unknown
+    return
+  fi
+  duration="${1}"
+  if [ X"${duration}" != X"${duration%s}" ]; then
+    duration=${duration%s}
+  elif [ X"${duration}" != X"${duration%m}" ]; then
+    duration=`expr ${duration%m} \* 60`
+  elif [ X"${duration}" != X"${duration%h}" ]; then
+    duration=`expr ${duration%h} \* 3600`
+  elif [ X"${duration}" != X"${duration%d}" ]; then
+    duration=`expr ${duration%d} \* 86400`
+  fi
+  seconds=`expr ${duration} % 60`
+  minutes=`expr \( ${duration} / 60 \) % 60`
+  hours=`expr ${duration} / 3600`
+  if [ 0 -eq ${minutes} -a 0 -eq ${hours} ]; then
+    if [ 1 -eq ${duration} ]; then
+      echo 1 second
+      return
+    fi
+    echo ${duration} seconds
+    return
+  elif [ 60 -eq ${duration} ]; then
+    echo 1 minute
+    return
+  elif [ 0 -eq ${seconds} -a 0 -eq ${hours} ]; then
+    echo ${minutes} minutes
+    return
+  fi
+  if [ 0 -eq ${hours} ]; then
+    echo ${minutes}:`expr ${seconds} / 10``expr ${seconds} % 10`
+    return
+  fi
+  echo ${hours}:`expr ${minutes} / 10``expr ${minutes} % 10`:`expr ${seconds} / 10``expr ${seconds} % 10`
+}
+
 [ "USAGE: adb_wait [timeout]
 
 Returns: waits until the device has returned for adb or optional timeout" ]
 adb_wait() {
   if [ -n "${1}" ]; then
+    echo -n ". . . waiting `format_duration ${1}`" ${ANDROID_SERIAL} ${USB_ADDRESS} "${CR}"
     timeout --preserve-status --signal=KILL ${1} adb wait-for-device
+    retval=${?}
+    echo -n "                                                                             ${CR}"
+    return ${retval}
   else
     adb wait-for-device
   fi
@@ -152,10 +217,14 @@
   # fastboot has no wait-for-device, but it does an automatic
   # wait and requires (even a nonsensical) command to do so.
   if [ -n "${1}" ]; then
-    timeout --preserve-status --signal=KILL ${1} fastboot wait-for-device
+    echo -n ". . . waiting `format_duration ${1}`" ${ANDROID_SERIAL} ${USB_ADDRESS} "${CR}"
+    timeout --preserve-status --signal=KILL ${1} fastboot wait-for-device >/dev/null 2>/dev/null
+    retval=${?}
+    echo -n "                                                                             ${CR}"
+    ( exit ${retval} )
   else
-    fastboot wait-for-device >/dev/null
-  fi >/dev/null 2>/dev/null ||
+    fastboot wait-for-device >/dev/null 2>/dev/null
+  fi ||
     inFastboot
 }
 
@@ -310,9 +379,14 @@
     -e "^\(overlay\|tmpfs\|none\|sysfs\|proc\|selinuxfs\|debugfs\) " \
     -e "^\(bpf\|cg2_bpf\|pstore\|tracefs\|adb\|mtp\|ptp\|devpts\) " \
     -e "^\(/data/media\|/dev/block/loop[0-9]*\) " \
+    -e "^rootfs / rootfs rw," \
     -e " /\(cache\|mnt/scratch\|mnt/vendor/persist\|persist\|metadata\) "
 }
 
+##
+##  MAINLINE
+##
+
 if [ X"-s" = X"${1}" -a -n "${2}" ]; then
   export ANDROID_SERIAL="${2}"
   shift 2
@@ -320,7 +394,7 @@
 
 inFastboot && die "device in fastboot mode"
 if ! inAdb; then
-  echo "${ORANGE}[  WARNING ]${NORMAL} device not in adb mode ... waiting 2 minutes"
+  echo "${ORANGE}[  WARNING ]${NORMAL} device not in adb mode"
   adb_wait 2m
 fi
 inAdb || die "specified device not in adb mode"
@@ -331,19 +405,38 @@
   enforcing=false
 fi
 
-# Do something
+# Do something.
 
 D=`get_property ro.serialno`
 [ -n "${D}" ] || D=`get_property ro.boot.serialno`
 [ -z "${D}" ] || ANDROID_SERIAL=${D}
+USB_SERIAL=
+[ -z "${ANDROID_SERIAL}" ] || USB_SERIAL=`find /sys/devices -name serial |
+                                          grep usb |
+                                          xargs grep -l ${ANDROID_SERIAL}`
+USB_ADDRESS=
+if [ -n "${USB_SERIAL}" ]; then
+  USB_ADDRESS=${USB_SERIAL%/serial}
+  USB_ADDRESS=usb${USB_ADDRESS##*/}
+fi
+[ -z "${ANDROID_SERIAL}${USB_ADDRESS}" ] ||
+  echo "${BLUE}[     INFO ]${NORMAL}" ${ANDROID_SERIAL} ${USB_ADDRESS} >&2
 BUILD_DESCRIPTION=`get_property ro.build.description`
-echo "${BLUE}[     INFO ]${NORMAL} ${ANDROID_SERIAL} ${BUILD_DESCRIPTION}" >&2
+[ -z "${BUILD_DESCRIPTION}" ] ||
+  echo "${BLUE}[     INFO ]${NORMAL} ${BUILD_DESCRIPTION}" >&2
+
+VERITY_WAS_ENABLED=false
+if [ "orange" = "`get_property ro.boot.verifiedbootstate`" -a \
+     "2" = "`get_property partition.system.verified`" ]; then
+  VERITY_WAS_ENABLED=true
+fi
 
 echo "${GREEN}[ RUN      ]${NORMAL} Testing kernel support for overlayfs" >&2
 
 overlayfs_supported=true;
 adb_wait || die "wait for device failed"
-adb_sh ls -d /sys/module/overlay </dev/null >/dev/null &&
+adb_sh ls -d /sys/module/overlay </dev/null >/dev/null 2>/dev/null ||
+  adb_sh grep "nodev${TAB}overlay" /proc/filesystems </dev/null >/dev/null 2>/dev/null &&
   echo "${GREEN}[       OK ]${NORMAL} overlay module present" >&2 ||
   (
     echo "${ORANGE}[  WARNING ]${NORMAL} overlay module not present" >&2 &&
@@ -391,9 +484,9 @@
   echo "${ORANGE}[  WARNING ]${NORMAL} rebooting before test" >&2
   adb_reboot &&
     adb_wait 2m ||
-    die "lost device after reboot after wipe"
+    die "lost device after reboot after wipe (USB stack broken?)"
   adb_root ||
-    die "lost device after elevation to root after wipe"
+    die "lost device after elevation to root after wipe (USB stack broken?)"
 fi
 D=`adb_sh df -k </dev/null` &&
   H=`echo "${D}" | head -1` &&
@@ -455,9 +548,9 @@
   L=`adb_logcat -b all -v nsec -t ${T} 2>&1`
   adb_reboot &&
     adb_wait 2m ||
-    die "lost device after reboot requested"
+    die "lost device after reboot requested (USB stack broken?)"
   adb_root ||
-    die "lost device after elevation to root"
+    die "lost device after elevation to root (USB stack broken?)"
   rebooted=true
   # re-disable verity to see the setup remarks expected
   T=`adb_date`
@@ -544,7 +637,7 @@
     echo "${D}" | grep "^overlay .* /system\$" >/dev/null ||
     die  "overlay takeover after remount"
   !(adb_sh grep "^overlay " /proc/mounts </dev/null |
-    grep -v "^overlay /\(vendor\|system\)/..* overlay ro," |
+    grep -v "^overlay /\(vendor\|system\|bionic\)/..* overlay ro," |
     grep " overlay ro,") &&
     !(adb_sh grep " rw," /proc/mounts </dev/null |
       skip_administrative_mounts data) ||
@@ -555,7 +648,7 @@
   fi
 fi
 
-# Check something
+# Check something.
 
 echo "${GREEN}[ RUN      ]${NORMAL} push content to /system and /vendor" >&2
 
@@ -569,17 +662,22 @@
   die "vendor hello"
 check_eq "${A}" "${B}" /vendor before reboot
 
-# download libc.so, append some gargage, push back, and check if the file is updated.
+# Download libc.so, append some gargage, push back, and check if the file
+# is updated.
 tempdir="`mktemp -d`"
 cleanup() {
   rm -rf ${tempdir}
 }
-adb pull /system/lib/bootstrap/libc.so ${tempdir} || die "pull libc.so from device"
+adb pull /system/lib/bootstrap/libc.so ${tempdir} >/dev/null ||
+  die "pull libc.so from device"
 garbage="`hexdump -n 16 -e '4/4 "%08X" 1 "\n"' /dev/random`"
 echo ${garbage} >> ${tempdir}/libc.so
-adb push ${tempdir}/libc.so /system/lib/bootstrap/libc.so || die "push libc.so to device"
-adb pull /system/lib/bootstrap/libc.so ${tempdir}/libc.so.fromdevice || die "pull libc.so from device"
-diff ${tempdir}/libc.so ${tempdir}/libc.so.fromdevice > /dev/null || die "libc.so differ"
+adb push ${tempdir}/libc.so /system/lib/bootstrap/libc.so >/dev/null ||
+  die "push libc.so to device"
+adb pull /system/lib/bootstrap/libc.so ${tempdir}/libc.so.fromdevice >/dev/null ||
+  die "pull libc.so from device"
+diff ${tempdir}/libc.so ${tempdir}/libc.so.fromdevice > /dev/null ||
+  die "libc.so differ"
 
 echo "${GREEN}[ RUN      ]${NORMAL} reboot to confirm content persistent" >&2
 
@@ -605,7 +703,7 @@
   die "re-read /system/hello after reboot"
 check_eq "${A}" "${B}" /system after reboot
 echo "${GREEN}[       OK ]${NORMAL} /system content remains after reboot" >&2
-# Only root can read vendor if sepolicy permissions are as expected
+# Only root can read vendor if sepolicy permissions are as expected.
 if ${enforcing}; then
   adb_unroot
   B="`adb_cat /vendor/hello`" &&
@@ -619,9 +717,9 @@
 check_eq "${A}" "${B}" vendor after reboot
 echo "${GREEN}[       OK ]${NORMAL} /vendor content remains after reboot" >&2
 
-# check if the updated libc.so is persistent after reboot
+# Check if the updated libc.so is persistent after reboot.
 adb_root &&
-  adb pull /system/lib/bootstrap/libc.so ${tempdir}/libc.so.fromdevice ||
+  adb pull /system/lib/bootstrap/libc.so ${tempdir}/libc.so.fromdevice >/dev/null ||
   die "pull libc.so from device"
 diff ${tempdir}/libc.so ${tempdir}/libc.so.fromdevice > /dev/null || die "libc.so differ"
 rm -r ${tempdir}
@@ -677,7 +775,7 @@
   fi
   fastboot reboot ||
     die "can not reboot out of fastboot"
-  echo "${ORANGE}[  WARNING ]${NORMAL} adb after fastboot ... waiting 2 minutes"
+  echo "${ORANGE}[  WARNING ]${NORMAL} adb after fastboot"
   adb_wait 2m ||
     die "did not reboot after flash"
   if ${overlayfs_needed}; then
@@ -719,9 +817,26 @@
 echo "${GREEN}[ RUN      ]${NORMAL} remove test content (cleanup)" >&2
 
 T=`adb_date`
-adb remount &&
+H=`adb remount 2>&1`
+err=${?}
+L=
+D="${H%?Now reboot your device for settings to take effect}"
+if [ X"${H}" != X"${D}" ]; then
+  echo "${ORANGE}[  WARNING ]${NORMAL} adb remount requires a reboot after partial flash (legacy avb)"
+  L=`adb_logcat -b all -v nsec -t ${T} 2>&1`
+  adb_reboot &&
+    adb_wait 2m &&
+    adb_root ||
+    die "failed to reboot"
+  T=`adb_date`
+  H=`adb remount 2>&1`
+  err=${?}
+fi
+echo "${H}"
+[ ${err} = 0 ] &&
   ( adb_sh rm /vendor/hello </dev/null 2>/dev/null || true ) &&
   adb_sh rm /system/hello </dev/null ||
+  ( [ -n "${L}" ] && echo "${L}" && false ) ||
   die -t ${T} "cleanup hello"
 B="`adb_cat /system/hello`" &&
   die "re-read /system/hello after rm"
@@ -768,12 +883,12 @@
     die -t ${T} "setup for overlayfs"
 fi
 
-echo "${GREEN}[ RUN      ]${NORMAL} test raw remount command" >&2
+echo "${GREEN}[ RUN      ]${NORMAL} test raw remount commands" >&2
 
-# prerequisite is a prepped device from above
+# Prerequisite is a prepped device from above.
 adb_reboot &&
   adb_wait 2m ||
-  die "lost device after reboot to ro state"
+  die "lost device after reboot to ro state (USB stack broken?)"
 adb_sh grep " /vendor .* rw," /proc/mounts >/dev/null &&
   die "/vendor is not read-only"
 adb_su mount -o rw,remount /vendor ||
@@ -782,4 +897,12 @@
   die "/vendor is not read-write"
 echo "${GREEN}[       OK ]${NORMAL} mount -o rw,remount command works" >&2
 
+if $VERITY_WAS_ENABLED && $overlayfs_supported; then
+  adb_root &&
+    adb enable-verity &&
+    adb_reboot &&
+    adb_wait 2m ||
+    die "failed to restore verity" >&2
+fi
+
 echo "${GREEN}[  PASSED  ]${NORMAL} adb remount" >&2
diff --git a/fs_mgr/tests/fs_mgr_test.cpp b/fs_mgr/tests/fs_mgr_test.cpp
index 870c98c..1815a38 100644
--- a/fs_mgr/tests/fs_mgr_test.cpp
+++ b/fs_mgr/tests/fs_mgr_test.cpp
@@ -256,6 +256,36 @@
     EXPECT_EQ("", fstab[10].fs_options);
 }
 
+static bool CompareFlags(FstabEntry::FsMgrFlags& lhs, FstabEntry::FsMgrFlags& rhs) {
+    // clang-format off
+    return lhs.wait == rhs.wait &&
+           lhs.check == rhs.check &&
+           lhs.crypt == rhs.crypt &&
+           lhs.nonremovable == rhs.nonremovable &&
+           lhs.vold_managed == rhs.vold_managed &&
+           lhs.recovery_only == rhs.recovery_only &&
+           lhs.verify == rhs.verify &&
+           lhs.force_crypt == rhs.force_crypt &&
+           lhs.no_emulated_sd == rhs.no_emulated_sd &&
+           lhs.no_trim == rhs.no_trim &&
+           lhs.file_encryption == rhs.file_encryption &&
+           lhs.formattable == rhs.formattable &&
+           lhs.slot_select == rhs.slot_select &&
+           lhs.force_fde_or_fbe == rhs.force_fde_or_fbe &&
+           lhs.late_mount == rhs.late_mount &&
+           lhs.no_fail == rhs.no_fail &&
+           lhs.verify_at_boot == rhs.verify_at_boot &&
+           lhs.quota == rhs.quota &&
+           lhs.avb == rhs.avb &&
+           lhs.logical == rhs.logical &&
+           lhs.checkpoint_blk == rhs.checkpoint_blk &&
+           lhs.checkpoint_fs == rhs.checkpoint_fs &&
+           lhs.first_stage_mount == rhs.first_stage_mount &&
+           lhs.slot_select_other == rhs.slot_select_other &&
+           lhs.fs_verity == rhs.fs_verity;
+    // clang-format on
+}
+
 TEST(fs_mgr, ReadFstabFromFile_FsMgrFlags) {
     TemporaryFile tf;
     ASSERT_TRUE(tf.fd != -1);
@@ -276,62 +306,62 @@
     auto entry = fstab.begin();
     EXPECT_EQ("none0", entry->mount_point);
     {
-        FstabEntry::FsMgrFlags flags = {0};
+        FstabEntry::FsMgrFlags flags = {};
         flags.wait = true;
         flags.check = true;
         flags.nonremovable = true;
         flags.recovery_only = true;
         flags.verify_at_boot = true;
         flags.verify = true;
-        EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+        EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
     }
     entry++;
 
     EXPECT_EQ("none1", entry->mount_point);
     {
-        FstabEntry::FsMgrFlags flags = {0};
+        FstabEntry::FsMgrFlags flags = {};
         flags.avb = true;
         flags.no_emulated_sd = true;
         flags.no_trim = true;
         flags.formattable = true;
         flags.slot_select = true;
         flags.no_fail = true;
-        EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+        EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
     }
     entry++;
 
     EXPECT_EQ("none2", entry->mount_point);
     {
-        FstabEntry::FsMgrFlags flags = {0};
+        FstabEntry::FsMgrFlags flags = {};
         flags.first_stage_mount = true;
         flags.late_mount = true;
         flags.quota = true;
         flags.logical = true;
         flags.slot_select_other = true;
-        EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+        EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
     }
     entry++;
 
     EXPECT_EQ("none3", entry->mount_point);
     {
-        FstabEntry::FsMgrFlags flags = {0};
+        FstabEntry::FsMgrFlags flags = {};
         flags.checkpoint_blk = true;
-        EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+        EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
     }
     entry++;
 
     EXPECT_EQ("none4", entry->mount_point);
     {
-        FstabEntry::FsMgrFlags flags = {0};
+        FstabEntry::FsMgrFlags flags = {};
         flags.checkpoint_fs = true;
-        EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+        EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
     }
     entry++;
 
     EXPECT_EQ("none5", entry->mount_point);
     {
-        FstabEntry::FsMgrFlags flags = {0};
-        EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+        FstabEntry::FsMgrFlags flags = {};
+        EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
     }
 }
 
@@ -355,8 +385,8 @@
     auto entry = fstab.begin();
     EXPECT_EQ("none0", entry->mount_point);
     {
-        FstabEntry::FsMgrFlags flags = {0};
-        EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+        FstabEntry::FsMgrFlags flags = {};
+        EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
     }
     EXPECT_EQ("", entry->key_loc);
     EXPECT_EQ("", entry->key_dir);
@@ -380,25 +410,13 @@
 
     EXPECT_EQ("none1", entry->mount_point);
     {
-        FstabEntry::FsMgrFlags flags = {0};
+        FstabEntry::FsMgrFlags flags = {};
         flags.crypt = true;
         flags.force_crypt = true;
         flags.file_encryption = true;
-        flags.key_directory = true;
-        flags.length = true;
-        flags.swap_prio = true;
-        flags.zram_size = true;
-        flags.max_comp_streams = true;
         flags.verify = true;
         flags.avb = true;
-        flags.reserved_size = true;
-        flags.erase_blk_size = true;
-        flags.logical_blk_size = true;
-        flags.sysfs = true;
-        flags.zram_loopback_path = true;
-        flags.zram_loopback_size = true;
-        flags.zram_backing_dev_path = true;
-        EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+        EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
     }
     EXPECT_EQ("", entry->key_loc);
     EXPECT_EQ("", entry->key_dir);
@@ -423,9 +441,9 @@
     // forcefdeorfbe sets file_contents_mode and file_names_mode by default, so test it separately.
     EXPECT_EQ("none2", entry->mount_point);
     {
-        FstabEntry::FsMgrFlags flags = {0};
+        FstabEntry::FsMgrFlags flags = {};
         flags.force_fde_or_fbe = true;
-        EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+        EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
     }
     EXPECT_EQ("aes-256-xts", entry->file_contents_mode);
     EXPECT_EQ("aes-256-cts", entry->file_names_mode);
@@ -444,12 +462,12 @@
     EXPECT_TRUE(ReadFstabFromFile(tf.path, &fstab));
     ASSERT_EQ(1U, fstab.size());
 
-    FstabEntry::FsMgrFlags flags = {0};
+    FstabEntry::FsMgrFlags flags = {};
     flags.crypt = true;
 
     auto entry = fstab.begin();
     EXPECT_EQ("none0", entry->mount_point);
-    EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+    EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
     EXPECT_EQ("/dir/key", entry->key_loc);
 }
 
@@ -468,30 +486,30 @@
     EXPECT_TRUE(ReadFstabFromFile(tf.path, &fstab));
     ASSERT_EQ(4U, fstab.size());
 
-    FstabEntry::FsMgrFlags flags = {0};
+    FstabEntry::FsMgrFlags flags = {};
     flags.vold_managed = true;
 
     auto entry = fstab.begin();
     EXPECT_EQ("none0", entry->mount_point);
-    EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+    EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
     EXPECT_TRUE(entry->label.empty());
     EXPECT_EQ(-1, entry->partnum);
     entry++;
 
     EXPECT_EQ("none1", entry->mount_point);
-    EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+    EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
     EXPECT_TRUE(entry->label.empty());
     EXPECT_EQ(-1, entry->partnum);
     entry++;
 
     EXPECT_EQ("none2", entry->mount_point);
-    EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+    EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
     EXPECT_EQ("sdcard", entry->label);
     EXPECT_EQ(3, entry->partnum);
     entry++;
 
     EXPECT_EQ("none3", entry->mount_point);
-    EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+    EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
     EXPECT_EQ("sdcard", entry->label);
     EXPECT_EQ(-1, entry->partnum);
 }
@@ -509,17 +527,16 @@
     EXPECT_TRUE(ReadFstabFromFile(tf.path, &fstab));
     ASSERT_EQ(2U, fstab.size());
 
-    FstabEntry::FsMgrFlags flags = {0};
-    flags.length = true;
+    FstabEntry::FsMgrFlags flags = {};
 
     auto entry = fstab.begin();
     EXPECT_EQ("none0", entry->mount_point);
-    EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+    EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
     EXPECT_EQ(0, entry->length);
     entry++;
 
     EXPECT_EQ("none1", entry->mount_point);
-    EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+    EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
     EXPECT_EQ(123456, entry->length);
 }
 
@@ -536,17 +553,16 @@
     EXPECT_TRUE(ReadFstabFromFile(tf.path, &fstab));
     ASSERT_EQ(2U, fstab.size());
 
-    FstabEntry::FsMgrFlags flags = {0};
-    flags.swap_prio = true;
+    FstabEntry::FsMgrFlags flags = {};
 
     auto entry = fstab.begin();
     EXPECT_EQ("none0", entry->mount_point);
-    EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+    EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
     EXPECT_EQ(-1, entry->swap_prio);
     entry++;
 
     EXPECT_EQ("none1", entry->mount_point);
-    EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+    EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
     EXPECT_EQ(123456, entry->swap_prio);
 }
 
@@ -567,37 +583,36 @@
     EXPECT_TRUE(ReadFstabFromFile(tf.path, &fstab));
     ASSERT_EQ(6U, fstab.size());
 
-    FstabEntry::FsMgrFlags flags = {0};
-    flags.zram_size = true;
+    FstabEntry::FsMgrFlags flags = {};
 
     auto entry = fstab.begin();
     EXPECT_EQ("none0", entry->mount_point);
-    EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+    EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
     EXPECT_EQ(0, entry->zram_size);
     entry++;
 
     EXPECT_EQ("none1", entry->mount_point);
-    EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+    EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
     EXPECT_EQ(123456, entry->zram_size);
     entry++;
 
     EXPECT_EQ("none2", entry->mount_point);
-    EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+    EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
     EXPECT_EQ(0, entry->zram_size);
     entry++;
 
     EXPECT_EQ("none3", entry->mount_point);
-    EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+    EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
     EXPECT_NE(0, entry->zram_size);
     entry++;
 
     EXPECT_EQ("none4", entry->mount_point);
-    EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+    EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
     EXPECT_EQ(0, entry->zram_size);
     entry++;
 
     EXPECT_EQ("none5", entry->mount_point);
-    EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+    EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
     EXPECT_EQ(0, entry->zram_size);
 }
 
@@ -617,9 +632,9 @@
     auto entry = fstab.begin();
     EXPECT_EQ("none0", entry->mount_point);
 
-    FstabEntry::FsMgrFlags flags = {0};
+    FstabEntry::FsMgrFlags flags = {};
     flags.verify = true;
-    EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+    EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
 
     EXPECT_EQ("/dir/key", entry->verity_loc);
 }
@@ -640,9 +655,9 @@
     auto entry = fstab.begin();
     EXPECT_EQ("none0", entry->mount_point);
 
-    FstabEntry::FsMgrFlags flags = {0};
+    FstabEntry::FsMgrFlags flags = {};
     flags.force_crypt = true;
-    EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+    EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
 
     EXPECT_EQ("/dir/key", entry->key_loc);
 }
@@ -663,9 +678,9 @@
     auto entry = fstab.begin();
     EXPECT_EQ("none0", entry->mount_point);
 
-    FstabEntry::FsMgrFlags flags = {0};
+    FstabEntry::FsMgrFlags flags = {};
     flags.force_fde_or_fbe = true;
-    EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+    EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
 
     EXPECT_EQ("/dir/key", entry->key_loc);
     EXPECT_EQ("aes-256-xts", entry->file_contents_mode);
@@ -695,72 +710,72 @@
     EXPECT_TRUE(ReadFstabFromFile(tf.path, &fstab));
     ASSERT_EQ(11U, fstab.size());
 
-    FstabEntry::FsMgrFlags flags = {0};
+    FstabEntry::FsMgrFlags flags = {};
     flags.file_encryption = true;
 
     auto entry = fstab.begin();
     EXPECT_EQ("none0", entry->mount_point);
-    EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+    EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
     EXPECT_EQ("", entry->file_contents_mode);
     EXPECT_EQ("", entry->file_names_mode);
 
     entry++;
     EXPECT_EQ("none1", entry->mount_point);
-    EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+    EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
     EXPECT_EQ("aes-256-xts", entry->file_contents_mode);
     EXPECT_EQ("aes-256-cts", entry->file_names_mode);
 
     entry++;
     EXPECT_EQ("none2", entry->mount_point);
-    EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+    EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
     EXPECT_EQ("aes-256-xts", entry->file_contents_mode);
     EXPECT_EQ("aes-256-cts", entry->file_names_mode);
 
     entry++;
     EXPECT_EQ("none3", entry->mount_point);
-    EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+    EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
     EXPECT_EQ("adiantum", entry->file_contents_mode);
     EXPECT_EQ("adiantum", entry->file_names_mode);
 
     entry++;
     EXPECT_EQ("none4", entry->mount_point);
-    EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+    EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
     EXPECT_EQ("adiantum", entry->file_contents_mode);
     EXPECT_EQ("aes-256-heh", entry->file_names_mode);
 
     entry++;
     EXPECT_EQ("none5", entry->mount_point);
-    EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+    EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
     EXPECT_EQ("ice", entry->file_contents_mode);
     EXPECT_EQ("aes-256-cts", entry->file_names_mode);
 
     entry++;
     EXPECT_EQ("none6", entry->mount_point);
-    EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+    EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
     EXPECT_EQ("ice", entry->file_contents_mode);
     EXPECT_EQ("", entry->file_names_mode);
 
     entry++;
     EXPECT_EQ("none7", entry->mount_point);
-    EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+    EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
     EXPECT_EQ("ice", entry->file_contents_mode);
     EXPECT_EQ("aes-256-cts", entry->file_names_mode);
 
     entry++;
     EXPECT_EQ("none8", entry->mount_point);
-    EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+    EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
     EXPECT_EQ("ice", entry->file_contents_mode);
     EXPECT_EQ("aes-256-heh", entry->file_names_mode);
 
     entry++;
     EXPECT_EQ("none9", entry->mount_point);
-    EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+    EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
     EXPECT_EQ("ice", entry->file_contents_mode);
     EXPECT_EQ("adiantum", entry->file_names_mode);
 
     entry++;
     EXPECT_EQ("none10", entry->mount_point);
-    EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+    EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
     EXPECT_EQ("", entry->file_contents_mode);
     EXPECT_EQ("", entry->file_names_mode);
 }
@@ -778,17 +793,16 @@
     EXPECT_TRUE(ReadFstabFromFile(tf.path, &fstab));
     ASSERT_EQ(2U, fstab.size());
 
-    FstabEntry::FsMgrFlags flags = {0};
-    flags.max_comp_streams = true;
+    FstabEntry::FsMgrFlags flags = {};
 
     auto entry = fstab.begin();
     EXPECT_EQ("none0", entry->mount_point);
-    EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+    EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
     EXPECT_EQ(0, entry->max_comp_streams);
     entry++;
 
     EXPECT_EQ("none1", entry->mount_point);
-    EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+    EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
     EXPECT_EQ(123456, entry->max_comp_streams);
 }
 
@@ -807,27 +821,26 @@
     EXPECT_TRUE(ReadFstabFromFile(tf.path, &fstab));
     ASSERT_EQ(4U, fstab.size());
 
-    FstabEntry::FsMgrFlags flags = {0};
-    flags.reserved_size = true;
+    FstabEntry::FsMgrFlags flags = {};
 
     auto entry = fstab.begin();
     EXPECT_EQ("none0", entry->mount_point);
-    EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+    EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
     EXPECT_EQ(0, entry->reserved_size);
     entry++;
 
     EXPECT_EQ("none1", entry->mount_point);
-    EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+    EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
     EXPECT_EQ(2, entry->reserved_size);
     entry++;
 
     EXPECT_EQ("none2", entry->mount_point);
-    EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+    EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
     EXPECT_EQ(1024, entry->reserved_size);
     entry++;
 
     EXPECT_EQ("none3", entry->mount_point);
-    EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+    EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
     EXPECT_EQ(2 * 1024 * 1024, entry->reserved_size);
 }
 
@@ -846,27 +859,26 @@
     EXPECT_TRUE(ReadFstabFromFile(tf.path, &fstab));
     ASSERT_EQ(4U, fstab.size());
 
-    FstabEntry::FsMgrFlags flags = {0};
-    flags.erase_blk_size = true;
+    FstabEntry::FsMgrFlags flags = {};
 
     auto entry = fstab.begin();
     EXPECT_EQ("none0", entry->mount_point);
-    EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+    EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
     EXPECT_EQ(0, entry->erase_blk_size);
     entry++;
 
     EXPECT_EQ("none1", entry->mount_point);
-    EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+    EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
     EXPECT_EQ(0, entry->erase_blk_size);
     entry++;
 
     EXPECT_EQ("none2", entry->mount_point);
-    EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+    EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
     EXPECT_EQ(0, entry->erase_blk_size);
     entry++;
 
     EXPECT_EQ("none3", entry->mount_point);
-    EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+    EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
     EXPECT_EQ(8192, entry->erase_blk_size);
 }
 
@@ -885,27 +897,26 @@
     EXPECT_TRUE(ReadFstabFromFile(tf.path, &fstab));
     ASSERT_EQ(4U, fstab.size());
 
-    FstabEntry::FsMgrFlags flags = {0};
-    flags.logical_blk_size = true;
+    FstabEntry::FsMgrFlags flags = {};
 
     auto entry = fstab.begin();
     EXPECT_EQ("none0", entry->mount_point);
-    EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+    EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
     EXPECT_EQ(0, entry->logical_blk_size);
     entry++;
 
     EXPECT_EQ("none1", entry->mount_point);
-    EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+    EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
     EXPECT_EQ(0, entry->logical_blk_size);
     entry++;
 
     EXPECT_EQ("none2", entry->mount_point);
-    EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+    EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
     EXPECT_EQ(0, entry->logical_blk_size);
     entry++;
 
     EXPECT_EQ("none3", entry->mount_point);
-    EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+    EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
     EXPECT_EQ(8192, entry->logical_blk_size);
 }
 
@@ -925,9 +936,9 @@
     auto entry = fstab.begin();
     EXPECT_EQ("none0", entry->mount_point);
 
-    FstabEntry::FsMgrFlags flags = {0};
+    FstabEntry::FsMgrFlags flags = {};
     flags.avb = true;
-    EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+    EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
 
     EXPECT_EQ("vbmeta_partition", entry->vbmeta_partition);
 }
@@ -948,9 +959,8 @@
     auto entry = fstab.begin();
     EXPECT_EQ("none0", entry->mount_point);
 
-    FstabEntry::FsMgrFlags flags = {0};
-    flags.key_directory = true;
-    EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+    FstabEntry::FsMgrFlags flags = {};
+    EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
 
     EXPECT_EQ("/dir/key", entry->key_dir);
 }
@@ -971,9 +981,8 @@
     auto entry = fstab.begin();
     EXPECT_EQ("none0", entry->mount_point);
 
-    FstabEntry::FsMgrFlags flags = {0};
-    flags.sysfs = true;
-    EXPECT_EQ(flags.val, entry->fs_mgr_flags.val);
+    FstabEntry::FsMgrFlags flags = {};
+    EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
 
     EXPECT_EQ("/sys/device", entry->sysfs_path);
 }
diff --git a/init/README.md b/init/README.md
index 3a7c71c..f0e5d55 100644
--- a/init/README.md
+++ b/init/README.md
@@ -161,11 +161,13 @@
 Options are modifiers to services.  They affect how and when init
 runs the service.
 
-`capabilities <capability> [ <capability>\* ]`
+`capabilities [ <capability>\* ]`
 > Set capabilities when exec'ing this service. 'capability' should be a Linux
   capability without the "CAP\_" prefix, like "NET\_ADMIN" or "SETPCAP". See
   http://man7.org/linux/man-pages/man7/capabilities.7.html for a list of Linux
   capabilities.
+  If no capabilities are provided, then all capabilities are removed from this service, even if it
+  runs as root.
 
 `class <name> [ <name>\* ]`
 > Specify class names for the service.  All services in a
diff --git a/init/init.cpp b/init/init.cpp
index 5a3cc15..a8924f2 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -192,7 +192,8 @@
 
     if (waiting_for_prop) {
         if (wait_prop_name == name && wait_prop_value == value) {
-            LOG(INFO) << "Wait for property took " << *waiting_for_prop;
+            LOG(INFO) << "Wait for property '" << wait_prop_name << "=" << wait_prop_value
+                      << "' took " << *waiting_for_prop;
             ResetWaitForProp();
         }
     }
diff --git a/init/service.cpp b/init/service.cpp
index 84cb2d8..2186a85 100644
--- a/init/service.cpp
+++ b/init/service.cpp
@@ -218,12 +218,12 @@
 
 Service::Service(const std::string& name, Subcontext* subcontext_for_restart_commands,
                  const std::vector<std::string>& args)
-    : Service(name, 0, 0, 0, {}, 0, 0, "", subcontext_for_restart_commands, args) {}
+    : Service(name, 0, 0, 0, {}, 0, "", subcontext_for_restart_commands, args) {}
 
 Service::Service(const std::string& name, unsigned flags, uid_t uid, gid_t gid,
-                 const std::vector<gid_t>& supp_gids, const CapSet& capabilities,
-                 unsigned namespace_flags, const std::string& seclabel,
-                 Subcontext* subcontext_for_restart_commands, const std::vector<std::string>& args)
+                 const std::vector<gid_t>& supp_gids, unsigned namespace_flags,
+                 const std::string& seclabel, Subcontext* subcontext_for_restart_commands,
+                 const std::vector<std::string>& args)
     : name_(name),
       classnames_({"default"}),
       flags_(flags),
@@ -232,7 +232,6 @@
       uid_(uid),
       gid_(gid),
       supp_gids_(supp_gids),
-      capabilities_(capabilities),
       namespace_flags_(namespace_flags),
       seclabel_(seclabel),
       onrestart_(false, subcontext_for_restart_commands, "<Service '" + name + "' onrestart>", 0,
@@ -289,7 +288,7 @@
         }
     }
     // Keep capabilites on uid change.
-    if (capabilities_.any() && uid_) {
+    if (capabilities_ && uid_) {
         // If Android is running in a container, some securebits might already
         // be locked, so don't change those.
         unsigned long securebits = prctl(PR_GET_SECUREBITS);
@@ -328,8 +327,8 @@
             PLOG(FATAL) << "setpriority failed for " << name_;
         }
     }
-    if (capabilities_.any()) {
-        if (!SetCapsForExec(capabilities_)) {
+    if (capabilities_) {
+        if (!SetCapsForExec(*capabilities_)) {
             LOG(FATAL) << "cannot set capabilities for " << name_;
         }
     } else if (uid_) {
@@ -375,7 +374,7 @@
 
     // If we crash > 4 times in 4 minutes, reboot into bootloader or set crashing property
     boot_clock::time_point now = boot_clock::now();
-    if (((flags_ & SVC_CRITICAL) || classnames_.count("updatable")) && !(flags_ & SVC_RESTART)) {
+    if (((flags_ & SVC_CRITICAL) || !pre_apexd_) && !(flags_ & SVC_RESTART)) {
         if (now < time_crashed_ + 4min) {
             if (++crash_count_ > 4) {
                 if (flags_ & SVC_CRITICAL) {
@@ -420,7 +419,7 @@
     }
 
     unsigned int last_valid_cap = GetLastValidCap();
-    if (last_valid_cap >= capabilities_.size()) {
+    if (last_valid_cap >= capabilities_->size()) {
         LOG(WARNING) << "last valid run-time capability is larger than CAP_LAST_CAP";
     }
 
@@ -435,7 +434,7 @@
             return Error() << StringPrintf("capability '%s' not supported by the kernel",
                                            arg.c_str());
         }
-        capabilities_[cap] = true;
+        (*capabilities_)[cap] = true;
     }
     return Success();
 }
@@ -796,7 +795,7 @@
     // clang-format off
     static const Map option_parsers = {
         {"capabilities",
-                        {1,     kMax, &Service::ParseCapabilities}},
+                        {0,     kMax, &Service::ParseCapabilities}},
         {"class",       {1,     kMax, &Service::ParseClass}},
         {"console",     {0,     1,    &Service::ParseConsole}},
         {"critical",    {0,     0,    &Service::ParseCritical}},
@@ -1268,7 +1267,6 @@
     std::string name = "exec " + std::to_string(exec_count) + " (" + Join(str_args, " ") + ")";
 
     unsigned flags = SVC_ONESHOT | SVC_TEMPORARY;
-    CapSet no_capabilities;
     unsigned namespace_flags = 0;
 
     std::string seclabel = "";
@@ -1303,8 +1301,8 @@
         }
     }
 
-    return std::make_unique<Service>(name, flags, *uid, *gid, supp_gids, no_capabilities,
-                                     namespace_flags, seclabel, nullptr, str_args);
+    return std::make_unique<Service>(name, flags, *uid, *gid, supp_gids, namespace_flags, seclabel,
+                                     nullptr, str_args);
 }
 
 // Shutdown services in the opposite order that they were started.
diff --git a/init/service.h b/init/service.h
index c29723a..c42a5a3 100644
--- a/init/service.h
+++ b/init/service.h
@@ -68,9 +68,9 @@
             const std::vector<std::string>& args);
 
     Service(const std::string& name, unsigned flags, uid_t uid, gid_t gid,
-            const std::vector<gid_t>& supp_gids, const CapSet& capabilities,
-            unsigned namespace_flags, const std::string& seclabel,
-            Subcontext* subcontext_for_restart_commands, const std::vector<std::string>& args);
+            const std::vector<gid_t>& supp_gids, unsigned namespace_flags,
+            const std::string& seclabel, Subcontext* subcontext_for_restart_commands,
+            const std::vector<std::string>& args);
 
     static std::unique_ptr<Service> MakeTemporaryOneshotService(const std::vector<std::string>& args);
 
@@ -192,7 +192,7 @@
     uid_t uid_;
     gid_t gid_;
     std::vector<gid_t> supp_gids_;
-    CapSet capabilities_;
+    std::optional<CapSet> capabilities_;
     unsigned namespace_flags_;
     // Pair of namespace type, path to namespace.
     std::vector<std::pair<int, std::string>> namespaces_to_enter_;
diff --git a/init/service_test.cpp b/init/service_test.cpp
index 194aa2b..4bfaa6b 100644
--- a/init/service_test.cpp
+++ b/init/service_test.cpp
@@ -57,7 +57,7 @@
     }
 
     Service* service_in_old_memory2 = new (old_memory) Service(
-        "test_old_memory", 0U, 0U, 0U, std::vector<gid_t>(), CapSet(), 0U, "", nullptr, dummy_args);
+            "test_old_memory", 0U, 0U, 0U, std::vector<gid_t>(), 0U, "", nullptr, dummy_args);
 
     EXPECT_EQ(0U, service_in_old_memory2->flags());
     EXPECT_EQ(0, service_in_old_memory2->pid());
diff --git a/libcutils/Android.bp b/libcutils/Android.bp
index 0dbbc3f..fab4b4e 100644
--- a/libcutils/Android.bp
+++ b/libcutils/Android.bp
@@ -172,7 +172,10 @@
         }
     },
 
-    shared_libs: ["liblog"],
+    shared_libs: [
+        "liblog",
+        "libbase",
+    ],
     header_libs: [
         "libbase_headers",
         "libcutils_headers",
diff --git a/libcutils/ashmem-dev.cpp b/libcutils/ashmem-dev.cpp
index 0cc4fc0..e35b91a 100644
--- a/libcutils/ashmem-dev.cpp
+++ b/libcutils/ashmem-dev.cpp
@@ -23,20 +23,40 @@
  */
 #define LOG_TAG "ashmem"
 
+#ifndef __ANDROID_VNDK__
+#include <dlfcn.h>
+#endif
 #include <errno.h>
 #include <fcntl.h>
 #include <linux/ashmem.h>
+#include <linux/memfd.h>
+#include <log/log.h>
 #include <pthread.h>
+#include <stdio.h>
 #include <string.h>
 #include <sys/ioctl.h>
+#include <sys/mman.h>
 #include <sys/stat.h>
+#include <sys/syscall.h>
 #include <sys/sysmacros.h>
 #include <sys/types.h>
 #include <unistd.h>
-#include <log/log.h>
+
+#include <android-base/properties.h>
+#include <android-base/unique_fd.h>
 
 #define ASHMEM_DEVICE "/dev/ashmem"
 
+/* Will be added to UAPI once upstream change is merged */
+#define F_SEAL_FUTURE_WRITE 0x0010
+
+/*
+ * The minimum vendor API level at and after which it is safe to use memfd.
+ * This is to facilitate deprecation of ashmem.
+ */
+#define MIN_MEMFD_VENDOR_API_LEVEL 29
+#define MIN_MEMFD_VENDOR_API_LEVEL_CHAR 'Q'
+
 /* ashmem identity */
 static dev_t __ashmem_rdev;
 /*
@@ -45,13 +65,170 @@
  */
 static pthread_mutex_t __ashmem_lock = PTHREAD_MUTEX_INITIALIZER;
 
+/*
+ * We use ashmemd to enforce that apps don't open /dev/ashmem directly. Vendor
+ * code can't access system aidl services per Treble requirements. So we limit
+ * ashmemd access to the system variant of libcutils.
+ */
+#ifndef __ANDROID_VNDK__
+using openFdType = int (*)();
+
+openFdType initOpenAshmemFd() {
+    openFdType openFd = nullptr;
+    void* handle = dlopen("libashmemd_client.so", RTLD_NOW);
+    if (!handle) {
+        ALOGE("Failed to dlopen() libashmemd_client.so: %s", dlerror());
+        return openFd;
+    }
+
+    openFd = reinterpret_cast<openFdType>(dlsym(handle, "openAshmemdFd"));
+    if (!openFd) {
+        ALOGE("Failed to dlsym() openAshmemdFd() function: %s", dlerror());
+    }
+    return openFd;
+}
+#endif
+
+/*
+ * has_memfd_support() determines if the device can use memfd. memfd support
+ * has been there for long time, but certain things in it may be missing.  We
+ * check for needed support in it. Also we check if the VNDK version of
+ * libcutils being used is new enough, if its not, then we cannot use memfd
+ * since the older copies may be using ashmem so we just use ashmem. Once all
+ * Android devices that are getting updates are new enough (ex, they were
+ * originally shipped with Android release > P), then we can just use memfd and
+ * delete all ashmem code from libcutils (while preserving the interface).
+ *
+ * NOTE:
+ * The sys.use_memfd property is set by default to false in Android
+ * to temporarily disable memfd, till vendor and apps are ready for it.
+ * The main issue: either apps or vendor processes can directly make ashmem
+ * IOCTLs on FDs they receive by assuming they are ashmem, without going
+ * through libcutils. Such fds could have very well be originally created with
+ * libcutils hence they could be memfd. Thus the IOCTLs will break.
+ *
+ * Set default value of sys.use_memfd property to true once the issue is
+ * resolved, so that the code can then self-detect if kernel support is present
+ * on the device. The property can also set to true from adb shell, for
+ * debugging.
+ */
+
+static bool debug_log = false;            /* set to true for verbose logging and other debug  */
+static bool pin_deprecation_warn = true; /* Log the pin deprecation warning only once */
+
+/* Determine if vendor processes would be ok with memfd in the system:
+ *
+ * If VNDK is using older libcutils, don't use memfd. This is so that the
+ * same shared memory mechanism is used across binder transactions between
+ * vendor partition processes and system partition processes.
+ */
+static bool check_vendor_memfd_allowed() {
+    std::string vndk_version = android::base::GetProperty("ro.vndk.version", "");
+
+    if (vndk_version == "") {
+        ALOGE("memfd: ro.vndk.version not defined or invalid (%s), this is mandated since P.\n",
+              vndk_version.c_str());
+        return false;
+    }
+
+    /* No issues if vendor is targetting current Dessert */
+    if (vndk_version == "current") {
+        return false;
+    }
+
+    /* Check if VNDK version is a number and act on it */
+    char* p;
+    long int vers = strtol(vndk_version.c_str(), &p, 10);
+    if (*p == 0) {
+        if (vers < MIN_MEMFD_VENDOR_API_LEVEL) {
+            ALOGI("memfd: device VNDK version (%s) is < Q so using ashmem.\n",
+                  vndk_version.c_str());
+            return false;
+        }
+
+        return true;
+    }
+
+    /* If its not a number, assume string, but check if its a sane string */
+    if (tolower(vndk_version[0]) < 'a' || tolower(vndk_version[0]) > 'z') {
+        ALOGE("memfd: ro.vndk.version not defined or invalid (%s), this is mandated since P.\n",
+              vndk_version.c_str());
+        return false;
+    }
+
+    if (tolower(vndk_version[0]) < tolower(MIN_MEMFD_VENDOR_API_LEVEL_CHAR)) {
+        ALOGI("memfd: device is using VNDK version (%s) which is less than Q. Use ashmem only.\n",
+              vndk_version.c_str());
+        return false;
+    }
+
+    return true;
+}
+
+
+/* Determine if memfd can be supported. This is just one-time hardwork
+ * which will be cached by the caller.
+ */
+static bool __has_memfd_support() {
+    if (check_vendor_memfd_allowed() == false) {
+        return false;
+    }
+
+    /* Used to turn on/off the detection at runtime, in the future this
+     * property will be removed once we switch everything over to ashmem.
+     * Currently it is used only for debugging to switch the system over.
+     */
+    if (!android::base::GetBoolProperty("sys.use_memfd", false)) {
+        if (debug_log) {
+            ALOGD("sys.use_memfd=false so memfd disabled\n");
+        }
+        return false;
+    }
+
+    /* Check if kernel support exists, otherwise fall back to ashmem */
+    android::base::unique_fd fd(
+            syscall(__NR_memfd_create, "test_android_memfd", MFD_ALLOW_SEALING));
+    if (fd == -1) {
+        ALOGE("memfd_create failed: %s, no memfd support.\n", strerror(errno));
+        return false;
+    }
+
+    if (fcntl(fd, F_ADD_SEALS, F_SEAL_FUTURE_WRITE) == -1) {
+        ALOGE("fcntl(F_ADD_SEALS) failed: %s, no memfd support.\n", strerror(errno));
+        return false;
+    }
+
+    if (debug_log) {
+        ALOGD("memfd: device has memfd support, using it\n");
+    }
+    return true;
+}
+
+static bool has_memfd_support() {
+    /* memfd_supported is the initial global per-process state of what is known
+     * about memfd.
+     */
+    static bool memfd_supported = __has_memfd_support();
+
+    return memfd_supported;
+}
+
 /* logistics of getting file descriptor for ashmem */
 static int __ashmem_open_locked()
 {
     int ret;
     struct stat st;
 
-    int fd = TEMP_FAILURE_RETRY(open(ASHMEM_DEVICE, O_RDWR | O_CLOEXEC));
+    int fd = -1;
+#ifndef __ANDROID_VNDK__
+    static auto openFd = initOpenAshmemFd();
+    if (openFd) {
+        fd = openFd();
+    }
+#endif
+    if (fd < 0) {
+        fd = TEMP_FAILURE_RETRY(open(ASHMEM_DEVICE, O_RDWR | O_CLOEXEC));
+    }
     if (fd < 0) {
         return fd;
     }
@@ -141,11 +318,49 @@
     return result;
 }
 
+static bool memfd_is_ashmem(int fd) {
+    static bool fd_check_error_once = false;
+
+    if (__ashmem_is_ashmem(fd, 0) == 0) {
+        if (!fd_check_error_once) {
+            ALOGE("memfd: memfd expected but ashmem fd used - please use libcutils.\n");
+            fd_check_error_once = true;
+        }
+
+        return true;
+    }
+
+    return false;
+}
+
 int ashmem_valid(int fd)
 {
+    if (has_memfd_support() && !memfd_is_ashmem(fd)) {
+        return 1;
+    }
+
     return __ashmem_is_ashmem(fd, 0) >= 0;
 }
 
+static int memfd_create_region(const char* name, size_t size) {
+    android::base::unique_fd fd(syscall(__NR_memfd_create, name, MFD_ALLOW_SEALING));
+
+    if (fd == -1) {
+        ALOGE("memfd_create(%s, %zd) failed: %s\n", name, size, strerror(errno));
+        return -1;
+    }
+
+    if (ftruncate(fd, size) == -1) {
+        ALOGE("ftruncate(%s, %zd) failed for memfd creation: %s\n", name, size, strerror(errno));
+        return -1;
+    }
+
+    if (debug_log) {
+        ALOGE("memfd_create(%s, %zd) success. fd=%d\n", name, size, fd.get());
+    }
+    return fd.release();
+}
+
 /*
  * ashmem_create_region - creates a new ashmem region and returns the file
  * descriptor, or <0 on error
@@ -157,6 +372,10 @@
 {
     int ret, save_errno;
 
+    if (has_memfd_support()) {
+        return memfd_create_region(name ? name : "none", size);
+    }
+
     int fd = __ashmem_open();
     if (fd < 0) {
         return fd;
@@ -186,28 +405,78 @@
     return ret;
 }
 
+static int memfd_set_prot_region(int fd, int prot) {
+    /* Only proceed if an fd needs to be write-protected */
+    if (prot & PROT_WRITE) {
+        return 0;
+    }
+
+    if (fcntl(fd, F_ADD_SEALS, F_SEAL_FUTURE_WRITE) == -1) {
+        ALOGE("memfd_set_prot_region(%d, %d): F_SEAL_FUTURE_WRITE seal failed: %s\n", fd, prot,
+              strerror(errno));
+        return -1;
+    }
+
+    return 0;
+}
+
 int ashmem_set_prot_region(int fd, int prot)
 {
+    if (has_memfd_support() && !memfd_is_ashmem(fd)) {
+        return memfd_set_prot_region(fd, prot);
+    }
+
     return __ashmem_check_failure(fd, TEMP_FAILURE_RETRY(ioctl(fd, ASHMEM_SET_PROT_MASK, prot)));
 }
 
 int ashmem_pin_region(int fd, size_t offset, size_t len)
 {
+    if (!pin_deprecation_warn || debug_log) {
+        ALOGE("Pinning is deprecated since Android Q. Please use trim or other methods.\n");
+        pin_deprecation_warn = true;
+    }
+
+    if (has_memfd_support() && !memfd_is_ashmem(fd)) {
+        return 0;
+    }
+
     // TODO: should LP64 reject too-large offset/len?
     ashmem_pin pin = { static_cast<uint32_t>(offset), static_cast<uint32_t>(len) };
-
     return __ashmem_check_failure(fd, TEMP_FAILURE_RETRY(ioctl(fd, ASHMEM_PIN, &pin)));
 }
 
 int ashmem_unpin_region(int fd, size_t offset, size_t len)
 {
+    if (!pin_deprecation_warn || debug_log) {
+        ALOGE("Pinning is deprecated since Android Q. Please use trim or other methods.\n");
+        pin_deprecation_warn = true;
+    }
+
+    if (has_memfd_support() && !memfd_is_ashmem(fd)) {
+        return 0;
+    }
+
     // TODO: should LP64 reject too-large offset/len?
     ashmem_pin pin = { static_cast<uint32_t>(offset), static_cast<uint32_t>(len) };
-
     return __ashmem_check_failure(fd, TEMP_FAILURE_RETRY(ioctl(fd, ASHMEM_UNPIN, &pin)));
 }
 
 int ashmem_get_size_region(int fd)
 {
+    if (has_memfd_support() && !memfd_is_ashmem(fd)) {
+        struct stat sb;
+
+        if (fstat(fd, &sb) == -1) {
+            ALOGE("ashmem_get_size_region(%d): fstat failed: %s\n", fd, strerror(errno));
+            return -1;
+        }
+
+        if (debug_log) {
+            ALOGD("ashmem_get_size_region(%d): %d\n", fd, static_cast<int>(sb.st_size));
+        }
+
+        return sb.st_size;
+    }
+
     return __ashmem_check_failure(fd, TEMP_FAILURE_RETRY(ioctl(fd, ASHMEM_GET_SIZE, NULL)));
 }
diff --git a/libcutils/fs_config.cpp b/libcutils/fs_config.cpp
index 59cbbc5..c95868d 100644
--- a/libcutils/fs_config.cpp
+++ b/libcutils/fs_config.cpp
@@ -88,6 +88,9 @@
     { 00755, AID_ROOT,         AID_ROOT,         0, "system/etc/ppp" },
     { 00755, AID_ROOT,         AID_SHELL,        0, "system/vendor" },
     { 00751, AID_ROOT,         AID_SHELL,        0, "system/xbin" },
+    // TODO(b/123743953): eliminate the APEX name with better pattern matching
+    { 00755, AID_ROOT,         AID_SHELL,        0, "system/apex/com.android.runtime.debug/bin" },
+    { 00755, AID_ROOT,         AID_SHELL,        0, "system/apex/com.android.runtime.release/bin" },
     { 00751, AID_ROOT,         AID_SHELL,        0, "vendor/bin" },
     { 00755, AID_ROOT,         AID_SHELL,        0, "vendor" },
     { 00755, AID_ROOT,         AID_ROOT,         0, 0 },
@@ -214,6 +217,9 @@
     { 00755, AID_ROOT,      AID_ROOT,      0, "system/lib/valgrind/*" },
     { 00755, AID_ROOT,      AID_ROOT,      0, "system/lib64/valgrind/*" },
     { 00755, AID_ROOT,      AID_SHELL,     0, "system/xbin/*" },
+    // TODO(b/123743953): eliminate the APEX name with better pattern matching
+    { 00755, AID_ROOT,      AID_SHELL,     0, "system/apex/com.android.runtime.debug/bin/*" },
+    { 00755, AID_ROOT,      AID_SHELL,     0, "system/apex/com.android.runtime.release/bin/*" },
     { 00755, AID_ROOT,      AID_SHELL,     0, "vendor/bin/*" },
     { 00755, AID_ROOT,      AID_SHELL,     0, "vendor/xbin/*" },
     { 00644, AID_ROOT,      AID_ROOT,      0, 0 },
diff --git a/libmeminfo/libdmabufinfo/dmabufinfo.cpp b/libmeminfo/libdmabufinfo/dmabufinfo.cpp
index b4ad667..0212cd2 100644
--- a/libmeminfo/libdmabufinfo/dmabufinfo.cpp
+++ b/libmeminfo/libdmabufinfo/dmabufinfo.cpp
@@ -130,7 +130,7 @@
             if (buf->count() == 0)
                 buf->SetCount(count);
             buf->AddFdRef(pid);
-            return true;
+            continue;
         }
 
         DmaBuffer& db =
diff --git a/libmeminfo/libdmabufinfo/include/dmabufinfo/dmabufinfo.h b/libmeminfo/libdmabufinfo/include/dmabufinfo/dmabufinfo.h
index e3be320..a16c3fd 100644
--- a/libmeminfo/libdmabufinfo/include/dmabufinfo/dmabufinfo.h
+++ b/libmeminfo/libdmabufinfo/include/dmabufinfo/dmabufinfo.h
@@ -30,17 +30,21 @@
   public:
     DmaBuffer(ino_t inode, uint64_t size, uint64_t count, const std::string& exporter,
               const std::string& name)
-        : inode_(inode), size_(size), count_(count), exporter_(exporter), name_(name) {}
+        : inode_(inode), size_(size), count_(count), exporter_(exporter), name_(name) {
+        total_refs_ = 0;
+    }
     ~DmaBuffer() = default;
 
     // Adds one file descriptor reference for the given pid
     void AddFdRef(pid_t pid) {
         AddRefToPidMap(pid, &fdrefs_);
+        total_refs_++;
     }
 
     // Adds one map reference for the given pid
     void AddMapRef(pid_t pid) {
         AddRefToPidMap(pid, &maprefs_);
+        total_refs_++;
     }
 
     // Getters for each property
@@ -48,7 +52,7 @@
     const std::unordered_map<pid_t, int>& fdrefs() const { return fdrefs_; }
     const std::unordered_map<pid_t, int>& maprefs() const { return maprefs_; }
     ino_t inode() const { return inode_; }
-    uint64_t total_refs() const { return fdrefs_.size() + maprefs_.size(); }
+    uint64_t total_refs() const { return total_refs_; }
     uint64_t count() const { return count_; };
     const std::string& name() const { return name_; }
     const std::string& exporter() const { return exporter_; }
@@ -65,6 +69,7 @@
     ino_t inode_;
     uint64_t size_;
     uint64_t count_;
+    uint64_t total_refs_;
     std::string exporter_;
     std::string name_;
     std::unordered_map<pid_t, int> fdrefs_;
@@ -81,7 +86,6 @@
 // Read and return current dma buf objects from
 // DEBUGFS/dma_buf/bufinfo. The references to each dma buffer are not
 // populated here and will return an empty vector.
-//
 // Returns false if something went wrong with the function, true otherwise.
 bool ReadDmaBufInfo(std::vector<DmaBuffer>* dmabufs,
                     const std::string& path = "/sys/kernel/debug/dma_buf/bufinfo");
@@ -89,13 +93,13 @@
 
 // Read and return dmabuf objects for a given process without the help
 // of DEBUGFS
-//
 // Returns false if something went wrong with the function, true otherwise.
 bool ReadDmaBufInfo(pid_t pid, std::vector<DmaBuffer>* dmabufs);
 
-// Append dmabuf objects for a given process without the help
-// of DEBUGFS to an existing vector
-//
+// Append new dmabuf objects from a given process to an existing vector.
+// When the vector contains an existing element with a matching inode,
+// the reference counts will be updated.
+// Does not depend on DEBUGFS.
 // Returns false if something went wrong with the function, true otherwise.
 bool AppendDmaBufInfo(pid_t pid, std::vector<DmaBuffer>* dmabufs);
 
diff --git a/libnativebridge/include/nativebridge/native_bridge.h b/libnativebridge/include/nativebridge/native_bridge.h
index 5aea967..e9c9500 100644
--- a/libnativebridge/include/nativebridge/native_bridge.h
+++ b/libnativebridge/include/nativebridge/native_bridge.h
@@ -164,8 +164,9 @@
 void* NativeBridgeLoadLibraryExt(const char* libpath, int flag,
                                  struct native_bridge_namespace_t* ns);
 
-// Returns vendor namespace if it is enabled for the device and null otherwise
-struct native_bridge_namespace_t* NativeBridgeGetVendorNamespace();
+// Returns exported namespace by the name. This is a reflection of
+// android_get_exported_namespace function. Introduced in v5.
+struct native_bridge_namespace_t* NativeBridgeGetExportedNamespace(const char* name);
 
 // Native bridge interfaces to runtime.
 struct NativeBridgeCallbacks {
@@ -362,7 +363,17 @@
   //
   // Returns:
   //   vendor namespace or null if it was not set up for the device
+  //
+  // Starting with v5 (Android Q) this function is no longer used.
+  // Use getExportedNamespace() below.
   struct native_bridge_namespace_t* (*getVendorNamespace)();
+
+  // Get native bridge version of exported namespace. Peer of
+  // android_get_exported_namespace(const char*) function.
+  //
+  // Returns:
+  //   exported namespace or null if it was not set up for the device
+  struct native_bridge_namespace_t* (*getExportedNamespace)(const char* name);
 };
 
 // Runtime interfaces to native bridge.
diff --git a/libnativebridge/libnativebridge.map.txt b/libnativebridge/libnativebridge.map.txt
index a616b85..a6841a3 100644
--- a/libnativebridge/libnativebridge.map.txt
+++ b/libnativebridge/libnativebridge.map.txt
@@ -24,7 +24,7 @@
     NativeBridgeGetError;
     NativeBridgeIsPathSupported;
     NativeBridgeCreateNamespace;
-    NativeBridgeGetVendorNamespace;
+    NativeBridgeGetExportedNamespace;
     NativeBridgeLinkNamespaces;
     NativeBridgeLoadLibraryExt;
     NativeBridgeInitAnonymousNamespace;
diff --git a/libnativebridge/native_bridge.cc b/libnativebridge/native_bridge.cc
index a2d8d81..9adba9a 100644
--- a/libnativebridge/native_bridge.cc
+++ b/libnativebridge/native_bridge.cc
@@ -101,6 +101,8 @@
   NAMESPACE_VERSION = 3,
   // The version with vendor namespaces
   VENDOR_NAMESPACE_VERSION = 4,
+  // The version with runtime namespaces
+  RUNTIME_NAMESPACE_VERSION = 5,
 };
 
 // Whether we had an error at some point.
@@ -610,12 +612,22 @@
   return false;
 }
 
-native_bridge_namespace_t* NativeBridgeGetVendorNamespace() {
-  if (!NativeBridgeInitialized() || !isCompatibleWith(VENDOR_NAMESPACE_VERSION)) {
+native_bridge_namespace_t* NativeBridgeGetExportedNamespace(const char* name) {
+  if (!NativeBridgeInitialized()) {
     return nullptr;
   }
 
-  return callbacks->getVendorNamespace();
+  if (isCompatibleWith(RUNTIME_NAMESPACE_VERSION)) {
+    return callbacks->getExportedNamespace(name);
+  }
+
+  // sphal is vendor namespace name -> use v4 callback in the case NB callbacks
+  // are not compatible with v5
+  if (isCompatibleWith(VENDOR_NAMESPACE_VERSION) && name != nullptr && strcmp("sphal", name) == 0) {
+    return callbacks->getVendorNamespace();
+  }
+
+  return nullptr;
 }
 
 void* NativeBridgeLoadLibraryExt(const char* libpath, int flag, native_bridge_namespace_t* ns) {
diff --git a/libnativeloader/native_loader.cpp b/libnativeloader/native_loader.cpp
index ad967db..5394d7e 100644
--- a/libnativeloader/native_loader.cpp
+++ b/libnativeloader/native_loader.cpp
@@ -103,6 +103,11 @@
 static constexpr const char kVndkspNativeLibrariesSystemConfigPathFromRoot[] =
     "/etc/vndksp.libraries.txt";
 
+static const std::vector<const std::string> kRuntimePublicLibraries = {
+    "libicuuc.so",
+    "libicui18n.so",
+};
+
 // The device may be configured to have the vendor libraries loaded to a separate namespace.
 // For historical reasons this namespace was named sphal but effectively it is intended
 // to use to load vendor libraries to separate namespace with controlled interface between
@@ -111,7 +116,18 @@
 
 static constexpr const char* kVndkNamespaceName = "vndk";
 
+static constexpr const char* kRuntimeNamespaceName = "runtime";
+
+// classloader-namespace is a linker namespace that is created for the loaded
+// app. To be specific, it is created for the app classloader. When
+// System.load() is called from a Java class that is loaded from the
+// classloader, the classloader-namespace namespace associated with that
+// classloader is selected for dlopen. The namespace is configured so that its
+// search path is set to the app-local JNI directory and it is linked to the
+// default namespace with the names of libs listed in the public.libraries.txt.
+// This way an app can only load its own JNI libraries along with the public libs.
 static constexpr const char* kClassloaderNamespaceName = "classloader-namespace";
+// Same thing for vendor APKs.
 static constexpr const char* kVendorClassloaderNamespaceName = "vendor-classloader-namespace";
 
 // (http://b/27588281) This is a workaround for apps using custom classloaders and calling
@@ -245,6 +261,8 @@
       }
     }
 
+    std::string runtime_exposed_libraries = base::Join(kRuntimePublicLibraries, ":");
+
     NativeLoaderNamespace native_loader_ns;
     if (!is_native_bridge) {
       android_namespace_t* android_parent_ns =
@@ -265,11 +283,21 @@
       // which is expected behavior in this case.
       android_namespace_t* vendor_ns = android_get_exported_namespace(kVendorNamespaceName);
 
+      android_namespace_t* runtime_ns = android_get_exported_namespace(kRuntimeNamespaceName);
+
       if (!android_link_namespaces(ns, nullptr, system_exposed_libraries.c_str())) {
         *error_msg = dlerror();
         return nullptr;
       }
 
+      // Runtime apex does not exist in host, and under certain build conditions.
+      if (runtime_ns != nullptr) {
+        if (!android_link_namespaces(ns, runtime_ns, runtime_exposed_libraries.c_str())) {
+          *error_msg = dlerror();
+          return nullptr;
+        }
+      }
+
       if (vndk_ns != nullptr && !system_vndksp_libraries_.empty()) {
         // vendor apks are allowed to use VNDK-SP libraries.
         if (!android_link_namespaces(ns, vndk_ns, system_vndksp_libraries_.c_str())) {
@@ -300,13 +328,22 @@
         return nullptr;
       }
 
-      native_bridge_namespace_t* vendor_ns = NativeBridgeGetVendorNamespace();
+      native_bridge_namespace_t* vendor_ns = NativeBridgeGetExportedNamespace(kVendorNamespaceName);
+      native_bridge_namespace_t* runtime_ns =
+          NativeBridgeGetExportedNamespace(kRuntimeNamespaceName);
 
       if (!NativeBridgeLinkNamespaces(ns, nullptr, system_exposed_libraries.c_str())) {
         *error_msg = NativeBridgeGetError();
         return nullptr;
       }
 
+      // Runtime apex does not exist in host, and under certain build conditions.
+      if (runtime_ns != nullptr) {
+        if (!NativeBridgeLinkNamespaces(ns, runtime_ns, runtime_exposed_libraries.c_str())) {
+          *error_msg = NativeBridgeGetError();
+          return nullptr;
+        }
+      }
       if (!vendor_public_libraries_.empty()) {
         if (!NativeBridgeLinkNamespaces(ns, vendor_ns, vendor_public_libraries_.c_str())) {
           *error_msg = NativeBridgeGetError();
diff --git a/libpixelflinger/tests/Android.bp b/libpixelflinger/tests/Android.bp
index 820a84d..e20dd93 100644
--- a/libpixelflinger/tests/Android.bp
+++ b/libpixelflinger/tests/Android.bp
@@ -8,6 +8,7 @@
 
     header_libs: ["libpixelflinger_internal"],
     static_libs: [
+        "libbase",
         "libcutils",
         "liblog",
         "libpixelflinger",
diff --git a/libprocessgroup/cgroup_map.cpp b/libprocessgroup/cgroup_map.cpp
index 12cfb7e..cd8ef94 100644
--- a/libprocessgroup/cgroup_map.cpp
+++ b/libprocessgroup/cgroup_map.cpp
@@ -19,6 +19,7 @@
 
 #include <errno.h>
 #include <fcntl.h>
+#include <grp.h>
 #include <pwd.h>
 #include <sys/mman.h>
 #include <sys/mount.h>
@@ -72,26 +73,28 @@
         }
     }
 
-    passwd* uid_pwd = nullptr;
-    passwd* gid_pwd = nullptr;
-
-    if (!uid.empty()) {
-        uid_pwd = getpwnam(uid.c_str());
-        if (!uid_pwd) {
-            PLOG(ERROR) << "Unable to decode UID for '" << uid << "'";
-            return false;
-        }
-
-        if (!gid.empty()) {
-            gid_pwd = getpwnam(gid.c_str());
-            if (!gid_pwd) {
-                PLOG(ERROR) << "Unable to decode GID for '" << gid << "'";
-                return false;
-            }
-        }
+    if (uid.empty()) {
+        return true;
     }
 
-    if (uid_pwd && lchown(path.c_str(), uid_pwd->pw_uid, gid_pwd ? gid_pwd->pw_uid : -1) < 0) {
+    passwd* uid_pwd = getpwnam(uid.c_str());
+    if (!uid_pwd) {
+        PLOG(ERROR) << "Unable to decode UID for '" << uid << "'";
+        return false;
+    }
+
+    uid_t pw_uid = uid_pwd->pw_uid;
+    gid_t gr_gid = -1;
+    if (!gid.empty()) {
+        group* gid_pwd = getgrnam(gid.c_str());
+        if (!gid_pwd) {
+            PLOG(ERROR) << "Unable to decode GID for '" << gid << "'";
+            return false;
+        }
+        gr_gid = gid_pwd->gr_gid;
+    }
+
+    if (lchown(path.c_str(), pw_uid, gr_gid) < 0) {
         PLOG(ERROR) << "lchown() failed for " << path;
         return false;
     }
@@ -128,7 +131,8 @@
         std::string name = cgroups[i]["Controller"].asString();
         descriptors->emplace(std::make_pair(
                 name,
-                CgroupDescriptor(1, name, cgroups[i]["Path"].asString(), cgroups[i]["Mode"].asInt(),
+                CgroupDescriptor(1, name, cgroups[i]["Path"].asString(),
+                                 std::strtoul(cgroups[i]["Mode"].asString().c_str(), 0, 8),
                                  cgroups[i]["UID"].asString(), cgroups[i]["GID"].asString())));
     }
 
@@ -136,8 +140,8 @@
     descriptors->emplace(std::make_pair(
             CGROUPV2_CONTROLLER_NAME,
             CgroupDescriptor(2, CGROUPV2_CONTROLLER_NAME, cgroups2["Path"].asString(),
-                             cgroups2["Mode"].asInt(), cgroups2["UID"].asString(),
-                             cgroups2["GID"].asString())));
+                             std::strtoul(cgroups2["Mode"].asString().c_str(), 0, 8),
+                             cgroups2["UID"].asString(), cgroups2["GID"].asString())));
 
     return true;
 }
diff --git a/libprocessgroup/task_profiles.cpp b/libprocessgroup/task_profiles.cpp
index ec6cbbc..447852d 100644
--- a/libprocessgroup/task_profiles.cpp
+++ b/libprocessgroup/task_profiles.cpp
@@ -132,6 +132,7 @@
 
 SetCgroupAction::SetCgroupAction(const CgroupController* c, const std::string& p)
     : controller_(c), path_(p) {
+#ifdef CACHE_FILE_DESCRIPTORS
     // cache file descriptor only if path is app independent
     if (IsAppDependentPath(path_)) {
         // file descriptor is not cached
@@ -155,6 +156,7 @@
     }
 
     fd_ = std::move(fd);
+#endif
 }
 
 bool SetCgroupAction::AddTidToCgroup(int tid, int fd) {
@@ -176,6 +178,7 @@
 }
 
 bool SetCgroupAction::ExecuteForProcess(uid_t uid, pid_t pid) const {
+#ifdef CACHE_FILE_DESCRIPTORS
     if (fd_ >= 0) {
         // fd is cached, reuse it
         if (!AddTidToCgroup(pid, fd_)) {
@@ -203,9 +206,24 @@
     }
 
     return true;
+#else
+    std::string procs_path = controller_->GetProcsFilePath(path_.c_str(), uid, pid);
+    unique_fd tmp_fd(TEMP_FAILURE_RETRY(open(procs_path.c_str(), O_WRONLY | O_CLOEXEC)));
+    if (tmp_fd < 0) {
+        // no permissions to access the file, ignore
+        return true;
+    }
+    if (!AddTidToCgroup(pid, tmp_fd)) {
+        PLOG(ERROR) << "Failed to add task into cgroup";
+        return false;
+    }
+
+    return true;
+#endif
 }
 
 bool SetCgroupAction::ExecuteForTask(int tid) const {
+#ifdef CACHE_FILE_DESCRIPTORS
     if (fd_ >= 0) {
         // fd is cached, reuse it
         if (!AddTidToCgroup(tid, fd_)) {
@@ -223,6 +241,20 @@
     // application-dependent path can't be used with tid
     PLOG(ERROR) << "Application profile can't be applied to a thread";
     return false;
+#else
+    std::string tasks_path = controller_->GetTasksFilePath(path_.c_str());
+    unique_fd tmp_fd(TEMP_FAILURE_RETRY(open(tasks_path.c_str(), O_WRONLY | O_CLOEXEC)));
+    if (tmp_fd < 0) {
+        // no permissions to access the file, ignore
+        return true;
+    }
+    if (!AddTidToCgroup(tid, tmp_fd)) {
+        PLOG(ERROR) << "Failed to add task into cgroup";
+        return false;
+    }
+
+    return true;
+#endif
 }
 
 bool TaskProfile::ExecuteForProcess(uid_t uid, pid_t pid) const {
diff --git a/libprocessgroup/task_profiles.h b/libprocessgroup/task_profiles.h
index 886ead1..b2e39f9 100644
--- a/libprocessgroup/task_profiles.h
+++ b/libprocessgroup/task_profiles.h
@@ -46,8 +46,8 @@
     virtual ~ProfileAction() {}
 
     // Default implementations will fail
-    virtual bool ExecuteForProcess(uid_t, pid_t) const { return -1; };
-    virtual bool ExecuteForTask(int) const { return -1; };
+    virtual bool ExecuteForProcess(uid_t, pid_t) const { return false; };
+    virtual bool ExecuteForTask(int) const { return false; };
 };
 
 // Profile actions
@@ -117,7 +117,9 @@
   private:
     const CgroupController* controller_;
     std::string path_;
+#ifdef CACHE_FILE_DESCRIPTORS
     android::base::unique_fd fd_;
+#endif
 
     static bool IsAppDependentPath(const std::string& path);
     static bool AddTidToCgroup(int tid, int fd);
diff --git a/libsystem/OWNERS b/libsystem/OWNERS
index aeb160c..fdea804 100644
--- a/libsystem/OWNERS
+++ b/libsystem/OWNERS
@@ -1,2 +1,9 @@
-jessehall@google.com
-olv@google.com
+# graphics/composer
+adyabr@google.com
+lpy@google.com
+marissaw@google.com
+stoza@google.com
+vhau@google.com
+
+# camera
+etalvala@google.com
diff --git a/libutils/FileMap.cpp b/libutils/FileMap.cpp
index 5feb2aa..1202c15 100644
--- a/libutils/FileMap.cpp
+++ b/libutils/FileMap.cpp
@@ -174,12 +174,6 @@
         return false;
     }
 #else // !defined(__MINGW32__)
-    int     prot, flags, adjust;
-    off64_t adjOffset;
-    size_t  adjLength;
-
-    void* ptr;
-
     assert(fd >= 0);
     assert(offset >= 0);
     assert(length > 0);
@@ -193,20 +187,23 @@
         }
     }
 
-    adjust = offset % mPageSize;
-    adjOffset = offset - adjust;
-    adjLength = length + adjust;
+    int adjust = offset % mPageSize;
+    off64_t adjOffset = offset - adjust;
+    size_t adjLength = length + adjust;
 
-    flags = MAP_SHARED;
-    prot = PROT_READ;
-    if (!readOnly)
-        prot |= PROT_WRITE;
+    int flags = MAP_SHARED;
+    int prot = PROT_READ;
+    if (!readOnly) prot |= PROT_WRITE;
 
-    ptr = mmap(nullptr, adjLength, prot, flags, fd, adjOffset);
+    void* ptr = mmap(nullptr, adjLength, prot, flags, fd, adjOffset);
     if (ptr == MAP_FAILED) {
-        ALOGE("mmap(%lld,%zu) failed: %s\n",
-            (long long)adjOffset, adjLength, strerror(errno));
-        return false;
+        if (errno == EINVAL && length == 0) {
+            ptr = nullptr;
+            adjust = 0;
+        } else {
+            ALOGE("mmap(%lld,%zu) failed: %s\n", (long long)adjOffset, adjLength, strerror(errno));
+            return false;
+        }
     }
     mBasePtr = ptr;
 #endif // !defined(__MINGW32__)
@@ -217,8 +214,6 @@
     mDataPtr = (char*) mBasePtr + adjust;
     mDataLength = length;
 
-    assert(mBasePtr != NULL);
-
     ALOGV("MAP: base %p/%zu data %p/%zu\n",
         mBasePtr, mBaseLength, mDataPtr, mDataLength);
 
diff --git a/libutils/tests/Android.bp b/libutils/tests/Android.bp
index 1390552..62f5acb 100644
--- a/libutils/tests/Android.bp
+++ b/libutils/tests/Android.bp
@@ -22,6 +22,7 @@
 
     srcs: [
         "BitSet_test.cpp",
+        "FileMap_test.cpp",
         "LruCache_test.cpp",
         "Mutex_test.cpp",
         "Singleton_test.cpp",
diff --git a/libutils/tests/FileMap_test.cpp b/libutils/tests/FileMap_test.cpp
new file mode 100644
index 0000000..576d89b
--- /dev/null
+++ b/libutils/tests/FileMap_test.cpp
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "utils/FileMap.h"
+
+#include <gtest/gtest.h>
+
+#include "android-base/file.h"
+
+TEST(FileMap, zero_length_mapping) {
+    // http://b/119818070 "app crashes when reading asset of zero length".
+    // mmap fails with EINVAL for a zero length region.
+    TemporaryFile tf;
+    ASSERT_TRUE(tf.fd != -1);
+
+    android::FileMap m;
+    ASSERT_TRUE(m.create("test", tf.fd, 4096, 0, true));
+    ASSERT_STREQ("test", m.getFileName());
+    ASSERT_EQ(0u, m.getDataLength());
+    ASSERT_EQ(4096, m.getDataOffset());
+}
diff --git a/lmkd/lmkd.c b/lmkd/lmkd.c
index 6cb059e..562e578 100644
--- a/lmkd/lmkd.c
+++ b/lmkd/lmkd.c
@@ -1969,11 +1969,9 @@
 
             clock_gettime(CLOCK_MONOTONIC_COARSE, &curr_tm);
             if (get_time_diff_ms(&last_report_tm, &curr_tm) >= PSI_POLL_PERIOD_MS) {
-                if (polling) {
-                    polling--;
-                    poll_handler->handler(poll_handler->data, 0);
-                    last_report_tm = curr_tm;
-                }
+                polling--;
+                poll_handler->handler(poll_handler->data, 0);
+                last_report_tm = curr_tm;
             }
         } else {
             /* Wait for events with no timeout */
diff --git a/rootdir/cgroups.json b/rootdir/cgroups.json
index 6eb88c9..aa71956 100644
--- a/rootdir/cgroups.json
+++ b/rootdir/cgroups.json
@@ -3,40 +3,40 @@
     {
       "Controller": "cpu",
       "Path": "/dev/cpuctl",
-      "Mode": 0755,
+      "Mode": "0755",
       "UID": "system",
       "GID": "system"
     },
     {
       "Controller": "cpuacct",
       "Path": "/acct",
-      "Mode": 0555
+      "Mode": "0555"
     },
     {
       "Controller": "cpuset",
       "Path": "/dev/cpuset",
-      "Mode": 0755,
+      "Mode": "0755",
       "UID": "system",
       "GID": "system"
     },
     {
       "Controller": "memory",
       "Path": "/dev/memcg",
-      "Mode": 0700,
+      "Mode": "0700",
       "UID": "root",
       "GID": "system"
     },
     {
       "Controller": "schedtune",
       "Path": "/dev/stune",
-      "Mode": 0755,
+      "Mode": "0755",
       "UID": "system",
       "GID": "system"
     }
   ],
   "Cgroups2": {
     "Path": "/dev/cg2_bpf",
-    "Mode": 0600,
+    "Mode": "0600",
     "UID": "root",
     "GID": "root"
   }
diff --git a/rootdir/etc/ld.config.txt b/rootdir/etc/ld.config.txt
index 9bf9058..7aa097d 100644
--- a/rootdir/etc/ld.config.txt
+++ b/rootdir/etc/ld.config.txt
@@ -24,6 +24,9 @@
 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
 
@@ -78,9 +81,9 @@
 
 namespace.default.asan.search.paths  = /data/asan/system/${LIB}
 namespace.default.asan.search.paths +=           /system/${LIB}
-namespace.default.asan.search.paths += /data/asan/product/${LIB}
+namespace.default.asan.search.paths += /data/asan/%PRODUCT%/${LIB}
 namespace.default.asan.search.paths +=           /%PRODUCT%/${LIB}
-namespace.default.asan.search.paths += /data/asan/product_services/${LIB}
+namespace.default.asan.search.paths += /data/asan/%PRODUCT_SERVICES%/${LIB}
 namespace.default.asan.search.paths +=           /%PRODUCT_SERVICES%/${LIB}
 
 namespace.default.asan.permitted.paths  = /data
diff --git a/rootdir/etc/ld.config.vndk_lite.txt b/rootdir/etc/ld.config.vndk_lite.txt
index ca180c0..1904445 100644
--- a/rootdir/etc/ld.config.vndk_lite.txt
+++ b/rootdir/etc/ld.config.vndk_lite.txt
@@ -50,9 +50,9 @@
 namespace.default.asan.search.paths +=           /odm/${LIB}
 namespace.default.asan.search.paths += /data/asan/vendor/${LIB}
 namespace.default.asan.search.paths +=           /vendor/${LIB}
-namespace.default.asan.search.paths += /data/asan/product/${LIB}
+namespace.default.asan.search.paths += /data/asan/%PRODUCT%/${LIB}
 namespace.default.asan.search.paths +=           /%PRODUCT%/${LIB}
-namespace.default.asan.search.paths += /data/asan/product_services/${LIB}
+namespace.default.asan.search.paths += /data/asan/%PRODUCT_SERVICES%/${LIB}
 namespace.default.asan.search.paths +=           /%PRODUCT_SERVICES%/${LIB}
 
 # Keep in sync with the platform namespace in the com.android.runtime APEX
diff --git a/rootdir/init.rc b/rootdir/init.rc
index c6e2116..370bc1c 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -531,6 +531,9 @@
     mkdir /data/anr 0775 system system
 
     mkdir /data/apex 0750 root system
+    mkdir /data/apex/active 0750 root system
+    mkdir /data/apex/backup 0700 root system
+    mkdir /data/apex/sessions 0700 root system
     mkdir /data/staging 0750 system system
 
     # NFC: create data/nfc for nv storage
@@ -590,6 +593,11 @@
     # Set indication (checked by vold) that we have finished this action
     #setprop vold.post_fs_data_done 1
 
+    # sys.memfd_use set to false by default, which keeps it disabled
+    # until it is confirmed that apps and vendor processes don't make
+    # IOCTLs on ashmem fds any more.
+    setprop sys.use_memfd false
+
 # It is recommended to put unnecessary data/ initialization from post-fs-data
 # to start-zygote in device's init.rc to unblock zygote start.
 on zygote-start && property:ro.crypto.state=unencrypted
diff --git a/rootdir/update_and_install_ld_config.mk b/rootdir/update_and_install_ld_config.mk
index 450be66..852e234 100644
--- a/rootdir/update_and_install_ld_config.mk
+++ b/rootdir/update_and_install_ld_config.mk
@@ -118,7 +118,12 @@
 	$(hide) sed -i.bak -e "s?%SANITIZER_RUNTIME_LIBRARIES%?$(PRIVATE_SANITIZER_RUNTIME_LIBRARIES)?g" $@
 	$(hide) sed -i.bak -e "s?%VNDK_VER%?$(PRIVATE_VNDK_VERSION_SUFFIX)?g" $@
 	$(hide) sed -i.bak -e "s?%PRODUCT%?$(TARGET_COPY_OUT_PRODUCT)?g" $@
+ifeq ($(TARGET_COPY_OUT_PRODUCT),$(TARGET_COPY_OUT_PRODUCT_SERVICES))
+	# Remove lines containing %PRODUCT_SERVICES% (identical to the %PRODUCT% ones)
+	$(hide) sed -i.bak -e "\?%PRODUCT_SERVICES%?d" $@
+else
 	$(hide) sed -i.bak -e "s?%PRODUCT_SERVICES%?$(TARGET_COPY_OUT_PRODUCT_SERVICES)?g" $@
+endif
 	$(hide) sed -i.bak -e "s?^$(PRIVATE_VNDK_VERSION_TAG)??g" $@
 	$(hide) sed -i.bak "/^\#VNDK[0-9]\{2\}\#.*$$/d" $@
 	$(hide) rm -f $@.bak