Merge "Fix flaky signal tests."
diff --git a/adb/client/line_printer.cpp b/adb/client/line_printer.cpp
index 4dc2d28..50c03e8 100644
--- a/adb/client/line_printer.cpp
+++ b/adb/client/line_printer.cpp
@@ -31,6 +31,8 @@
 // Stuff from ninja's util.h that's needed below.
 #include <vector>
 using namespace std;
+// This does not account for multiple UTF-8 bytes corresponding to a single Unicode code point, or
+// multiple code points corresponding to a single grapheme cluster (user-perceived character).
 string ElideMiddle(const string& str, size_t width) {
   const int kMargin = 3;  // Space for "...".
   string result = str;
@@ -85,9 +87,10 @@
     CONSOLE_SCREEN_BUFFER_INFO csbi;
     GetConsoleScreenBufferInfo(console_, &csbi);
 
-    // TODO: std::wstring to_print_wide; if (!android::base::UTF8ToWide(to_print, &to_print_wide)...
-    // TODO: wstring ElideMiddle.
     to_print = ElideMiddle(to_print, static_cast<size_t>(csbi.dwSize.X));
+    std::wstring to_print_wide;
+    // ElideMiddle may create invalid UTF-8, so ignore conversion errors.
+    (void)android::base::UTF8ToWide(to_print, &to_print_wide);
     // We don't want to have the cursor spamming back and forth, so instead of
     // printf use WriteConsoleOutput which updates the contents of the buffer,
     // but doesn't move the cursor position.
@@ -100,12 +103,10 @@
     };
     vector<CHAR_INFO> char_data(csbi.dwSize.X);
     for (size_t i = 0; i < static_cast<size_t>(csbi.dwSize.X); ++i) {
-      // TODO: UnicodeChar instead of AsciiChar, to_print_wide[i].
-      char_data[i].Char.AsciiChar = i < to_print.size() ? to_print[i] : ' ';
-      char_data[i].Attributes = csbi.wAttributes;
+        char_data[i].Char.UnicodeChar = i < to_print_wide.size() ? to_print_wide[i] : L' ';
+        char_data[i].Attributes = csbi.wAttributes;
     }
-    // TODO: WriteConsoleOutputW.
-    WriteConsoleOutput(console_, &char_data[0], buf_size, zero_zero, &target);
+    WriteConsoleOutputW(console_, &char_data[0], buf_size, zero_zero, &target);
 #else
     // Limit output to width of the terminal if provided so we don't cause
     // line-wrapping.
diff --git a/adb/sysdeps_win32.cpp b/adb/sysdeps_win32.cpp
index dbc8920..d587589 100644
--- a/adb/sysdeps_win32.cpp
+++ b/adb/sysdeps_win32.cpp
@@ -719,7 +719,7 @@
 /**************************************************************************/
 /**************************************************************************/
 
-static int _init_winsock(void) {
+static void _init_winsock() {
     static std::once_flag once;
     std::call_once(once, []() {
         WSADATA wsaData;
@@ -743,11 +743,8 @@
         //    crypt32.dll which calls atexit() which tries to acquire the C
         //    Runtime lock that the other thread holds.
     });
-    return 0;
 }
 
-static int _winsock_init = _init_winsock();
-
 // Map a socket type to an explicit socket protocol instead of using the socket
 // protocol of 0. Explicit socket protocols are used by most apps and we should
 // do the same to reduce the chance of exercising uncommon code-paths that might
@@ -2621,14 +2618,13 @@
 }
 
 // Shadow UTF-8 environment variable name/value pairs that are created from
-// _wenviron the first time that adb_getenv() is called. Note that this is not
-// currently updated if putenv, setenv, unsetenv are called. Note that no
-// thread synchronization is done, but we're called early enough in
+// _wenviron by _init_env(). Note that this is not currently updated if putenv, setenv, unsetenv are
+// called. Note that no thread synchronization is done, but we're called early enough in
 // single-threaded startup that things work ok.
 static auto& g_environ_utf8 = *new std::unordered_map<std::string, char*>();
 
-// Make sure that shadow UTF-8 environment variables are setup.
-static void _ensure_env_setup() {
+// Setup shadow UTF-8 environment variables.
+static void _init_env() {
     // If some name/value pairs exist, then we've already done the setup below.
     if (g_environ_utf8.size() != 0) {
         return;
@@ -2681,8 +2677,6 @@
 // Version of getenv() that takes a UTF-8 environment variable name and
 // retrieves a UTF-8 value. Case-insensitive to match getenv() on Windows.
 char* adb_getenv(const char* name) {
-    _ensure_env_setup();
-
     // Case-insensitive search by searching for lowercase name in a map of
     // lowercase names.
     const auto it = g_environ_utf8.find(ToLower(std::string(name)));
@@ -2757,3 +2751,65 @@
 
     return 0;
 }
+
+#if !defined(ENABLE_VIRTUAL_TERMINAL_PROCESSING)
+#define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004
+#endif
+
+#if !defined(DISABLE_NEWLINE_AUTO_RETURN)
+#define DISABLE_NEWLINE_AUTO_RETURN 0x0008
+#endif
+
+static void _init_console() {
+    DWORD old_out_console_mode;
+
+    const HANDLE out = _get_console_handle(STDOUT_FILENO, &old_out_console_mode);
+    if (out == nullptr) {
+        return;
+    }
+
+    // Try to use ENABLE_VIRTUAL_TERMINAL_PROCESSING on the output console to process virtual
+    // terminal sequences on newer versions of Windows 10 and later.
+    // https://docs.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences
+    // On older OSes that don't support the flag, SetConsoleMode() will return an error.
+    // ENABLE_VIRTUAL_TERMINAL_PROCESSING also solves a problem where the last column of the
+    // console cannot be overwritten.
+    //
+    // Note that we don't use DISABLE_NEWLINE_AUTO_RETURN because it doesn't seem to be necessary.
+    // If we use DISABLE_NEWLINE_AUTO_RETURN, _console_write_utf8() would need to be modified to
+    // translate \n to \r\n.
+    if (!SetConsoleMode(out, old_out_console_mode | ENABLE_VIRTUAL_TERMINAL_PROCESSING)) {
+        return;
+    }
+
+    // If SetConsoleMode() succeeded, the console supports virtual terminal processing, so we
+    // should set the TERM env var to match so that it will be propagated to adbd on devices.
+    //
+    // Below's direct manipulation of env vars and not g_environ_utf8 assumes that _init_env() has
+    // not yet been called. If this fails, _init_env() should be called after _init_console().
+    if (g_environ_utf8.size() > 0) {
+        LOG(FATAL) << "environment variables have already been converted to UTF-8";
+    }
+
+#pragma push_macro("getenv")
+#undef getenv
+#pragma push_macro("putenv")
+#undef putenv
+    if (getenv("TERM") == nullptr) {
+        // This is the same TERM value used by Gnome Terminal and the version of ssh included with
+        // Windows.
+        putenv("TERM=xterm-256color");
+    }
+#pragma pop_macro("putenv")
+#pragma pop_macro("getenv")
+}
+
+static bool _init_sysdeps() {
+    // _init_console() depends on _init_env() not being called yet.
+    _init_console();
+    _init_env();
+    _init_winsock();
+    return true;
+}
+
+static bool _sysdeps_init = _init_sysdeps();
diff --git a/base/include/android-base/unique_fd.h b/base/include/android-base/unique_fd.h
index c8d12cf..2c890b4 100644
--- a/base/include/android-base/unique_fd.h
+++ b/base/include/android-base/unique_fd.h
@@ -161,22 +161,35 @@
 
 // Inline functions, so that they can be used header-only.
 template <typename Closer>
-inline bool Pipe(unique_fd_impl<Closer>* read, unique_fd_impl<Closer>* write) {
+inline bool Pipe(unique_fd_impl<Closer>* read, unique_fd_impl<Closer>* write,
+                 int flags = O_CLOEXEC) {
   int pipefd[2];
 
 #if defined(__linux__)
-  if (pipe2(pipefd, O_CLOEXEC) != 0) {
+  if (pipe2(pipefd, flags) != 0) {
     return false;
   }
 #else  // defined(__APPLE__)
+  if (flags & ~(O_CLOEXEC | O_NONBLOCK)) {
+    return false;
+  }
   if (pipe(pipefd) != 0) {
     return false;
   }
 
-  if (fcntl(pipefd[0], F_SETFD, FD_CLOEXEC) != 0 || fcntl(pipefd[1], F_SETFD, FD_CLOEXEC) != 0) {
-    close(pipefd[0]);
-    close(pipefd[1]);
-    return false;
+  if (flags & O_CLOEXEC) {
+    if (fcntl(pipefd[0], F_SETFD, FD_CLOEXEC) != 0 || fcntl(pipefd[1], F_SETFD, FD_CLOEXEC) != 0) {
+      close(pipefd[0]);
+      close(pipefd[1]);
+      return false;
+    }
+  }
+  if (flags & O_NONBLOCK) {
+    if (fcntl(pipefd[0], F_SETFL, O_NONBLOCK) != 0 || fcntl(pipefd[1], F_SETFL, O_NONBLOCK) != 0) {
+      close(pipefd[0]);
+      close(pipefd[1]);
+      return false;
+    }
   }
 #endif
 
diff --git a/fs_mgr/OWNERS b/fs_mgr/OWNERS
index 817a0b8..cbbd3bc 100644
--- a/fs_mgr/OWNERS
+++ b/fs_mgr/OWNERS
@@ -1,2 +1,3 @@
 bowgotsai@google.com
+dvander@google.com
 tomcherry@google.com
diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp
index 70a1045..ded3678 100644
--- a/fs_mgr/fs_mgr.cpp
+++ b/fs_mgr/fs_mgr.cpp
@@ -81,6 +81,8 @@
 #define ZRAM_CONF_MCS   "/sys/block/zram0/max_comp_streams"
 #define ZRAM_BACK_DEV   "/sys/block/zram0/backing_dev"
 
+#define SYSFS_EXT4_VERITY "/sys/fs/ext4/features/verity"
+
 #define ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a)))
 
 using android::base::Realpath;
@@ -110,6 +112,7 @@
     FS_STAT_TOGGLE_QUOTAS_FAILED = 0x10000,
     FS_STAT_SET_RESERVED_BLOCKS_FAILED = 0x20000,
     FS_STAT_ENABLE_ENCRYPTION_FAILED = 0x40000,
+    FS_STAT_ENABLE_VERITY_FAILED = 0x80000,
 };
 
 // TODO: switch to inotify()
@@ -440,6 +443,43 @@
     }
 }
 
+// Enable fs-verity if needed.
+static void tune_verity(const std::string& blk_device, const FstabEntry& entry,
+                        const struct ext4_super_block* sb, int* fs_stat) {
+    bool has_verity = (sb->s_feature_ro_compat & cpu_to_le32(EXT4_FEATURE_RO_COMPAT_VERITY)) != 0;
+    bool want_verity = entry.fs_mgr_flags.fs_verity;
+
+    if (has_verity || !want_verity) {
+        return;
+    }
+
+    std::string verity_support;
+    if (!android::base::ReadFileToString(SYSFS_EXT4_VERITY, &verity_support)) {
+        LERROR << "Failed to open " << SYSFS_EXT4_VERITY;
+        return;
+    }
+
+    if (!(android::base::Trim(verity_support) == "supported")) {
+        LERROR << "Current ext4 verity not supported by kernel";
+        return;
+    }
+
+    if (!tune2fs_available()) {
+        LERROR << "Unable to enable ext4 verity on " << blk_device
+               << " because " TUNE2FS_BIN " is missing";
+        return;
+    }
+
+    LINFO << "Enabling ext4 verity on " << blk_device;
+
+    const char* argv[] = {TUNE2FS_BIN, "-O", "verity", blk_device.c_str()};
+    if (!run_tune2fs(argv, ARRAY_SIZE(argv))) {
+        LERROR << "Failed to run " TUNE2FS_BIN " to enable "
+               << "ext4 verity on " << blk_device;
+        *fs_stat |= FS_STAT_ENABLE_VERITY_FAILED;
+    }
+}
+
 // Read the primary superblock from an f2fs filesystem.  On failure return
 // false.  If it's not an f2fs filesystem, also set FS_STAT_INVALID_MAGIC.
 #define F2FS_BLKSIZE 4096
@@ -511,12 +551,14 @@
     }
 
     if (is_extfs(entry.fs_type) &&
-        (entry.fs_mgr_flags.reserved_size || entry.fs_mgr_flags.file_encryption)) {
+        (entry.fs_mgr_flags.reserved_size || entry.fs_mgr_flags.file_encryption ||
+         entry.fs_mgr_flags.fs_verity)) {
         struct ext4_super_block sb;
 
         if (read_ext4_superblock(blk_device, &sb, &fs_stat)) {
             tune_reserved_size(blk_device, entry, &sb, &fs_stat);
             tune_encrypt(blk_device, entry, &sb, &fs_stat);
+            tune_verity(blk_device, entry, &sb, &fs_stat);
         }
     }
 
diff --git a/fs_mgr/fs_mgr_fstab.cpp b/fs_mgr/fs_mgr_fstab.cpp
index c9f34a7..9d4f280 100644
--- a/fs_mgr/fs_mgr_fstab.cpp
+++ b/fs_mgr/fs_mgr_fstab.cpp
@@ -125,6 +125,7 @@
         {"zram_loopback_path=", MF_ZRAM_LOOPBACK_PATH},
         {"zram_loopback_size=", MF_ZRAM_LOOPBACK_SIZE},
         {"zram_backing_dev_path=", MF_ZRAM_BACKING_DEV_PATH},
+        {"fsverity", MF_FS_VERITY},
         {0, 0},
 };
 
@@ -1087,6 +1088,10 @@
     return fstab->fs_mgr_flags & MF_CHECKPOINT_BLK;
 }
 
+int fs_mgr_is_fs_verity(const struct fstab_rec* fstab) {
+    return fstab->fs_mgr_flags & MF_FS_VERITY;
+}
+
 FstabEntry BuildGsiSystemFstabEntry() {
     FstabEntry system = {
             .blk_device = "system_gsi",
diff --git a/fs_mgr/fs_mgr_overlayfs.cpp b/fs_mgr/fs_mgr_overlayfs.cpp
index 0f89467..2c4299a 100644
--- a/fs_mgr/fs_mgr_overlayfs.cpp
+++ b/fs_mgr/fs_mgr_overlayfs.cpp
@@ -137,9 +137,9 @@
 
 bool fs_mgr_overlayfs_enabled(FstabEntry* entry) {
     // readonly filesystem, can not be mount -o remount,rw
-    // if squashfs or if free space is (near) zero making such a remount
+    // for squashfs, erofs or if free space is (near) zero making such a remount
     // virtually useless, or if there are shared blocks that prevent remount,rw
-    if ("squashfs" == entry->fs_type || !fs_mgr_filesystem_has_space(entry->mount_point)) {
+    if (!fs_mgr_filesystem_has_space(entry->mount_point)) {
         return true;
     }
     if (entry->fs_mgr_flags.logical) {
@@ -626,8 +626,8 @@
 
 // Only a suggestion for _first_ try during mounting
 std::string fs_mgr_overlayfs_scratch_mount_type() {
-    if (!access(kMkF2fs.c_str(), X_OK)) return "f2fs";
-    if (!access(kMkExt4.c_str(), X_OK)) return "ext4";
+    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";
     return "auto";
 }
 
@@ -642,7 +642,11 @@
         // Create from within single super device;
         auto& dm = DeviceMapper::Instance();
         const auto partition_name = android::base::Basename(kScratchMountPoint);
-        if (!dm.GetDmDevicePathByName(partition_name, &path)) return "";
+        if (!dm.GetDmDevicePathByName(partition_name, &path)) {
+            // non-DAP A/B device?
+            if (fs_mgr_access(super_device)) return "";
+            path = kPhysicalDevice + "system" + (slot_number ? "_a" : "_b");
+        }
     }
     return scratch_device_cache = path;
 }
@@ -829,8 +833,9 @@
                                                    true /* readonly */)) {
                     auto has_overlayfs_dir = fs_mgr_access(kScratchMountPoint + kOverlayTopDir);
                     fs_mgr_overlayfs_umount_scratch();
-                    if (has_overlayfs_dir)
+                    if (has_overlayfs_dir) {
                         fs_mgr_overlayfs_mount_scratch(scratch_device, mount_type);
+                    }
                 }
             }
         }
@@ -882,10 +887,6 @@
     for (const auto& overlay_mount_point : kOverlayMountPoints) {
         if (backing && backing[0] && (overlay_mount_point != backing)) continue;
         if (overlay_mount_point == kScratchMountPoint) {
-            if (!fs_mgr_rw_access(fs_mgr_overlayfs_super_device(fs_mgr_overlayfs_slot_number())) ||
-                !fs_mgr_overlayfs_has_logical(fstab)) {
-                continue;
-            }
             if (!fs_mgr_overlayfs_setup_scratch(fstab, change)) continue;
         } else {
             if (std::find_if(fstab.begin(), fstab.end(), [&overlay_mount_point](const auto& entry) {
diff --git a/fs_mgr/fs_mgr_priv.h b/fs_mgr/fs_mgr_priv.h
index 39ceff7..3b9ddee 100644
--- a/fs_mgr/fs_mgr_priv.h
+++ b/fs_mgr/fs_mgr_priv.h
@@ -128,6 +128,8 @@
                          0x400000000
 #define MF_ZRAM_BACKING_DEV_PATH \
                          0x800000000
+#define MF_FS_VERITY  \
+                         0x1000000000
 // clang-format on
 
 #define DM_BUF_SIZE 4096
diff --git a/fs_mgr/include_fstab/fstab/fstab.h b/fs_mgr/include_fstab/fstab/fstab.h
index 5d8496d..4a05949 100644
--- a/fs_mgr/include_fstab/fstab/fstab.h
+++ b/fs_mgr/include_fstab/fstab/fstab.h
@@ -95,6 +95,7 @@
 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);
+int fs_mgr_is_fs_verity(const struct fstab_rec* fstab);
 
 std::string fs_mgr_get_slot_suffix();
 std::set<std::string> fs_mgr_get_boot_devices();
@@ -174,6 +175,10 @@
 
             // 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;
 
diff --git a/fs_mgr/libfiemap_writer/fiemap_writer.cpp b/fs_mgr/libfiemap_writer/fiemap_writer.cpp
index 71b39a9..164fc91 100644
--- a/fs_mgr/libfiemap_writer/fiemap_writer.cpp
+++ b/fs_mgr/libfiemap_writer/fiemap_writer.cpp
@@ -220,7 +220,7 @@
 }
 
 static bool AllocateFile(int file_fd, const std::string& file_path, uint64_t blocksz,
-                         uint64_t file_size) {
+                         uint64_t file_size, std::function<bool(uint64_t, uint64_t)> on_progress) {
     // Reserve space for the file on the file system and write it out to make sure the extents
     // don't come back unwritten. Return from this function with the kernel file offset set to 0.
     // If the filesystem is f2fs, then we also PIN the file on disk to make sure the blocks
@@ -245,12 +245,22 @@
         return false;
     }
 
+    int permille = -1;
     for (; offset < file_size; offset += blocksz) {
         if (!::android::base::WriteFully(file_fd, buffer.get(), blocksz)) {
             PLOG(ERROR) << "Failed to write" << blocksz << " bytes at offset" << offset
                         << " in file " << file_path;
             return false;
         }
+        // Don't invoke the callback every iteration - wait until a significant
+        // chunk (here, 1/1000th) of the data has been processed.
+        int new_permille = (static_cast<uint64_t>(offset) * 1000) / file_size;
+        if (new_permille != permille) {
+            if (on_progress && !on_progress(offset, file_size)) {
+                return false;
+            }
+            permille = new_permille;
+        }
     }
 
     if (lseek64(file_fd, 0, SEEK_SET) < 0) {
@@ -264,6 +274,10 @@
         return false;
     }
 
+    // Send one last progress notification.
+    if (on_progress && !on_progress(file_size, file_size)) {
+        return false;
+    }
     return true;
 }
 
@@ -412,7 +426,8 @@
     return last_extent_seen;
 }
 
-FiemapUniquePtr FiemapWriter::Open(const std::string& file_path, uint64_t file_size, bool create) {
+FiemapUniquePtr FiemapWriter::Open(const std::string& file_path, uint64_t file_size, bool create,
+                                   std::function<bool(uint64_t, uint64_t)> progress) {
     // if 'create' is false, open an existing file and do not truncate.
     int open_flags = O_RDWR | O_CLOEXEC;
     if (create) {
@@ -474,7 +489,7 @@
     }
 
     if (create) {
-        if (!AllocateFile(file_fd, abs_path, blocksz, file_size)) {
+        if (!AllocateFile(file_fd, abs_path, blocksz, file_size, std::move(progress))) {
             LOG(ERROR) << "Failed to allocate file: " << abs_path << " of size: " << file_size
                        << " bytes";
             cleanup(abs_path, create);
diff --git a/fs_mgr/libfiemap_writer/fiemap_writer_test.cpp b/fs_mgr/libfiemap_writer/fiemap_writer_test.cpp
index 6dff0e8..5101537 100644
--- a/fs_mgr/libfiemap_writer/fiemap_writer_test.cpp
+++ b/fs_mgr/libfiemap_writer/fiemap_writer_test.cpp
@@ -83,6 +83,25 @@
     EXPECT_EQ(access(testfile.c_str(), F_OK), 0);
 }
 
+TEST_F(FiemapWriterTest, CheckProgress) {
+    std::vector<uint64_t> expected{
+            0,
+            4096,
+    };
+    size_t invocations = 0;
+    auto callback = [&](uint64_t done, uint64_t total) -> bool {
+        EXPECT_LT(invocations, expected.size());
+        EXPECT_EQ(done, expected[invocations]);
+        EXPECT_EQ(total, 4096);
+        invocations++;
+        return true;
+    };
+
+    auto ptr = FiemapWriter::Open(testfile, 4096, true, std::move(callback));
+    EXPECT_NE(ptr, nullptr);
+    EXPECT_EQ(invocations, 2);
+}
+
 TEST_F(FiemapWriterTest, CheckBlockDevicePath) {
     FiemapUniquePtr fptr = FiemapWriter::Open(testfile, 4096);
     EXPECT_EQ(fptr->size(), 4096);
diff --git a/fs_mgr/libfiemap_writer/include/libfiemap_writer/fiemap_writer.h b/fs_mgr/libfiemap_writer/include/libfiemap_writer/fiemap_writer.h
index ae61344..ab78f93 100644
--- a/fs_mgr/libfiemap_writer/include/libfiemap_writer/fiemap_writer.h
+++ b/fs_mgr/libfiemap_writer/include/libfiemap_writer/fiemap_writer.h
@@ -21,6 +21,7 @@
 #include <sys/types.h>
 #include <unistd.h>
 
+#include <functional>
 #include <string>
 #include <vector>
 
@@ -36,9 +37,13 @@
   public:
     // Factory method for FiemapWriter.
     // The method returns FiemapUniquePtr that contains all the data necessary to be able to write
-    // to the given file directly using raw block i/o.
+    // to the given file directly using raw block i/o. The optional progress callback will be
+    // invoked, if create is true, while the file is being initialized. It receives the bytes
+    // written and the number of total bytes. If the callback returns false, the operation will
+    // fail.
     static FiemapUniquePtr Open(const std::string& file_path, uint64_t file_size,
-                                bool create = true);
+                                bool create = true,
+                                std::function<bool(uint64_t, uint64_t)> progress = {});
 
     // Syncs block device writes.
     bool Flush() const;
diff --git a/fs_mgr/liblp/builder.cpp b/fs_mgr/liblp/builder.cpp
index b99ff8f..110d56e 100644
--- a/fs_mgr/liblp/builder.cpp
+++ b/fs_mgr/liblp/builder.cpp
@@ -269,6 +269,11 @@
 }
 
 static bool VerifyDeviceProperties(const BlockDeviceInfo& device_info) {
+    if (device_info.logical_block_size == 0) {
+        LERROR << "Block device " << device_info.partition_name
+               << " logical block size must not be zero.";
+        return false;
+    }
     if (device_info.logical_block_size % LP_SECTOR_SIZE != 0) {
         LERROR << "Block device " << device_info.partition_name
                << " logical block size must be a multiple of 512.";
@@ -335,7 +340,7 @@
         out.alignment = device_info.alignment;
         out.alignment_offset = device_info.alignment_offset;
         out.size = device_info.size;
-        if (device_info.partition_name.size() >= sizeof(out.partition_name)) {
+        if (device_info.partition_name.size() > sizeof(out.partition_name)) {
             LERROR << "Partition name " << device_info.partition_name << " exceeds maximum length.";
             return false;
         }
diff --git a/fs_mgr/liblp/include/liblp/metadata_format.h b/fs_mgr/liblp/include/liblp/metadata_format.h
index 9c5ec5c..8934aaf 100644
--- a/fs_mgr/liblp/include/liblp/metadata_format.h
+++ b/fs_mgr/liblp/include/liblp/metadata_format.h
@@ -127,7 +127,7 @@
  * num_entries, and the result must not overflow a 32-bit signed integer.
  */
 typedef struct LpMetadataTableDescriptor {
-    /*  0: Location of the table, relative to the metadata header. */
+    /*  0: Location of the table, relative to end of the metadata header. */
     uint32_t offset;
     /*  4: Number of entries in the table. */
     uint32_t num_entries;
@@ -272,7 +272,7 @@
 
     /* 40: Maximum size in bytes. If 0, the group has no maximum size. */
     uint64_t maximum_size;
-} LpMetadataPartitionGroup;
+} __attribute__((packed)) LpMetadataPartitionGroup;
 
 /* This flag is only intended to be used with super_empty.img and super.img on
  * retrofit devices. If set, the group needs a slot suffix to be interpreted
@@ -323,7 +323,7 @@
 
     /* 60: Flags (see LP_BLOCK_DEVICE_* flags below). */
     uint32_t flags;
-} LpMetadataBlockDevice;
+} __attribute__((packed)) LpMetadataBlockDevice;
 
 /* This flag is only intended to be used with super_empty.img and super.img on
  * retrofit devices. On these devices there are A and B super partitions, and
diff --git a/fs_mgr/liblp/reader.cpp b/fs_mgr/liblp/reader.cpp
index 24c6b2c..dcee6d2 100644
--- a/fs_mgr/liblp/reader.cpp
+++ b/fs_mgr/liblp/reader.cpp
@@ -256,6 +256,10 @@
             LERROR << "Logical partition has invalid attribute set.";
             return nullptr;
         }
+        if (partition.first_extent_index + partition.num_extents < partition.first_extent_index) {
+            LERROR << "Logical partition first_extent_index + num_extents overflowed.";
+            return nullptr;
+        }
         if (partition.first_extent_index + partition.num_extents > header.extents.num_entries) {
             LERROR << "Logical partition has invalid extent list.";
             return nullptr;
diff --git a/fs_mgr/liblp/writer.cpp b/fs_mgr/liblp/writer.cpp
index 54a1883..bffcb7e 100644
--- a/fs_mgr/liblp/writer.cpp
+++ b/fs_mgr/liblp/writer.cpp
@@ -373,11 +373,11 @@
         // safety.
         std::string old_blob;
         if (!ValidateAndSerializeMetadata(opener, *backup.get(), slot_suffix, &old_blob)) {
-            LERROR << "Error serializing primary metadata to repair corrupted backup";
+            LERROR << "Error serializing backup metadata to repair corrupted primary";
             return false;
         }
         if (!WritePrimaryMetadata(fd, metadata, slot_number, old_blob, writer)) {
-            LERROR << "Error writing primary metadata to repair corrupted backup";
+            LERROR << "Error writing backup metadata to repair corrupted primary";
             return false;
         }
     }
diff --git a/fs_mgr/tests/adb-remount-test.sh b/fs_mgr/tests/adb-remount-test.sh
index 0765f04..42f3f29 100755
--- a/fs_mgr/tests/adb-remount-test.sh
+++ b/fs_mgr/tests/adb-remount-test.sh
@@ -309,7 +309,7 @@
     -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 " /\(cache\|mnt/scratch\|mnt/vendor/persist\|metadata\) "
+    -e " /\(cache\|mnt/scratch\|mnt/vendor/persist\|persist\|metadata\) "
 }
 
 if [ X"-s" = X"${1}" -a -n "${2}" ]; then
@@ -403,9 +403,15 @@
      echo "${D}" | grep -v /dev/root`
 fi
 D=`echo "${D}" | cut -s -d' ' -f1 | sort -u`
+no_dedupe=true
+for d in ${D}; do
+  adb_sh tune2fs -l $d 2>&1 |
+    grep "Filesystem features:.*shared_blocks" >/dev/null &&
+  no_dedupe=false
+done
 D=`adb_sh df -k ${D} </dev/null`
 echo "${D}"
-if [ X"${D}" = X"${D##* 100[%] }" ]; then
+if [ X"${D}" = X"${D##* 100[%] }" ] && ${no_dedupe} ; then
   overlayfs_needed=false
 elif ! ${overlayfs_supported}; then
   die "need overlayfs, but do not have it"
@@ -597,6 +603,7 @@
 echo "${GREEN}[ RUN      ]${NORMAL} flash vendor, confirm its content disappears" >&2
 
 H=`adb_sh echo '${HOSTNAME}' </dev/null 2>/dev/null`
+is_userspace_fastboot=false
 if [ -z "${ANDROID_PRODUCT_OUT}" ]; then
   echo "${ORANGE}[  WARNING ]${NORMAL} build tree not setup, skipping"
 elif [ ! -s "${ANDROID_PRODUCT_OUT}/vendor.img" ]; then
@@ -609,6 +616,8 @@
     fastboot flash vendor ||
     ( fastboot reboot && false) ||
     die "fastboot flash vendor"
+  fastboot_getvar is-userspace yes &&
+    is_userspace_fastboot=true
   if [ -n "${scratch_paritition}" ]; then
     fastboot_getvar partition-type:${scratch_partition} raw ||
       ( fastboot reboot && false) ||
@@ -654,7 +663,12 @@
       echo "${D}" | grep "^overlay .* /system\$" >/dev/null ||
       die  "overlay /system takeover after flash vendor"
     echo "${D}" | grep "^overlay .* /vendor\$" >/dev/null &&
-      die  "overlay supposed to be minus /vendor takeover after flash vendor"
+      if ${is_userspace_fastboot}; then
+        die  "overlay supposed to be minus /vendor takeover after flash vendor"
+      else
+        echo "${ORANGE}[  WARNING ]${NORMAL} user fastboot missing, ignoring a failure"
+        ( die  "overlay supposed to be minus /vendor takeover after flash vendor" )
+      fi
   fi
   B="`adb_cat /system/hello`" ||
     die "re-read /system/hello after flash vendor"
@@ -662,8 +676,17 @@
   adb_root ||
     die "adb root"
   B="`adb_cat /vendor/hello`" &&
-    die "re-read /vendor/hello after flash vendor"
-  check_eq "cat: /vendor/hello: No such file or directory" "${B}" vendor after flash vendor
+    if ${is_userspace_fastboot} || ! ${overlayfs_needed}; then
+      die "re-read /vendor/hello after flash vendor"
+    else
+      echo "${ORANGE}[  WARNING ]${NORMAL} user fastboot missing, ignoring a failure"
+      ( die "re-read /vendor/hello after flash vendor" )
+    fi
+  if ${is_userspace_fastboot} || ! ${overlayfs_needed}; then
+    check_eq "cat: /vendor/hello: No such file or directory" "${B}" vendor after flash vendor
+  else
+    ( check_eq "cat: /vendor/hello: No such file or directory" "${B}" vendor after flash vendor )
+  fi
 fi
 
 echo "${GREEN}[ RUN      ]${NORMAL} remove test content (cleanup)" >&2
diff --git a/healthd/Android.mk b/healthd/Android.mk
index 80bf84a..2127b96 100644
--- a/healthd/Android.mk
+++ b/healthd/Android.mk
@@ -109,6 +109,7 @@
     libbase \
     libutils \
     libcutils \
+    libprocessgroup \
     liblog \
     libm \
     libc \
diff --git a/init/reboot.cpp b/init/reboot.cpp
index 0aa7810..5b90969 100644
--- a/init/reboot.cpp
+++ b/init/reboot.cpp
@@ -57,6 +57,7 @@
 #include "service.h"
 #include "sigchld_handler.h"
 
+using android::base::GetBoolProperty;
 using android::base::Split;
 using android::base::StringPrintf;
 using android::base::Timer;
@@ -398,9 +399,31 @@
     Service* bootAnim = ServiceList::GetInstance().FindService("bootanim");
     Service* surfaceFlinger = ServiceList::GetInstance().FindService("surfaceflinger");
     if (bootAnim != nullptr && surfaceFlinger != nullptr && surfaceFlinger->IsRunning()) {
-        // will not check animation class separately
+        bool do_shutdown_animation = GetBoolProperty("ro.init.shutdown_animation", false);
+
+        if (do_shutdown_animation) {
+            property_set("service.bootanim.exit", "0");
+            // Could be in the middle of animation. Stop and start so that it can pick
+            // up the right mode.
+            bootAnim->Stop();
+        }
+
         for (const auto& service : ServiceList::GetInstance()) {
-            if (service->classnames().count("animation")) service->SetShutdownCritical();
+            if (service->classnames().count("animation") == 0) {
+                continue;
+            }
+
+            // start all animation classes if stopped.
+            if (do_shutdown_animation) {
+                service->Start().IgnoreError();
+            }
+            service->SetShutdownCritical();  // will not check animation class separately
+        }
+
+        if (do_shutdown_animation) {
+            bootAnim->Start().IgnoreError();
+            surfaceFlinger->SetShutdownCritical();
+            bootAnim->SetShutdownCritical();
         }
     }
 
diff --git a/init/selinux.cpp b/init/selinux.cpp
index c0fc3ce..d93e9ec 100644
--- a/init/selinux.cpp
+++ b/init/selinux.cpp
@@ -304,13 +304,18 @@
     if (!GetVendorMappingVersion(&vend_plat_vers)) {
         return false;
     }
-    std::string mapping_file("/system/etc/selinux/mapping/" + vend_plat_vers + ".cil");
+    std::string plat_mapping_file("/system/etc/selinux/mapping/" + vend_plat_vers + ".cil");
 
     std::string product_policy_cil_file("/product/etc/selinux/product_sepolicy.cil");
     if (access(product_policy_cil_file.c_str(), F_OK) == -1) {
         product_policy_cil_file.clear();
     }
 
+    std::string product_mapping_file("/product/etc/selinux/mapping/" + vend_plat_vers + ".cil");
+    if (access(product_mapping_file.c_str(), F_OK) == -1) {
+        product_mapping_file.clear();
+    }
+
     // vendor_sepolicy.cil and plat_pub_versioned.cil are the new design to replace
     // nonplat_sepolicy.cil.
     std::string plat_pub_versioned_cil_file("/vendor/etc/selinux/plat_pub_versioned.cil");
@@ -340,7 +345,7 @@
         "-m", "-M", "true", "-G", "-N",
         // Target the highest policy language version supported by the kernel
         "-c", version_as_string.c_str(),
-        mapping_file.c_str(),
+        plat_mapping_file.c_str(),
         "-o", compiled_sepolicy,
         // We don't care about file_contexts output by the compiler
         "-f", "/sys/fs/selinux/null",  // /dev/null is not yet available
@@ -350,6 +355,9 @@
     if (!product_policy_cil_file.empty()) {
         compile_args.push_back(product_policy_cil_file.c_str());
     }
+    if (!product_mapping_file.empty()) {
+        compile_args.push_back(product_mapping_file.c_str());
+    }
     if (!plat_pub_versioned_cil_file.empty()) {
         compile_args.push_back(plat_pub_versioned_cil_file.c_str());
     }
diff --git a/libcutils/Android.bp b/libcutils/Android.bp
index 4291212..0dbbc3f 100644
--- a/libcutils/Android.bp
+++ b/libcutils/Android.bp
@@ -66,7 +66,6 @@
         "load_file.cpp",
         "native_handle.cpp",
         "record_stream.cpp",
-        "sched_policy.cpp",
         "sockets.cpp",
         "strdup16to8.cpp",
         "strdup8to16.cpp",
@@ -178,8 +177,12 @@
         "libbase_headers",
         "libcutils_headers",
         "libutils_headers",
+        "libprocessgroup_headers",
     ],
-    export_header_lib_headers: ["libcutils_headers"],
+    export_header_lib_headers: [
+        "libcutils_headers",
+        "libprocessgroup_headers",
+    ],
     local_include_dirs: ["include"],
 
     cflags: [
diff --git a/libcutils/include/cutils/sched_policy.h b/libcutils/include/cutils/sched_policy.h
index cf91b76..538ff6b 100644
--- a/libcutils/include/cutils/sched_policy.h
+++ b/libcutils/include/cutils/sched_policy.h
@@ -17,67 +17,10 @@
 #ifndef __CUTILS_SCHED_POLICY_H
 #define __CUTILS_SCHED_POLICY_H
 
-#include <stdbool.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 /*
- * Check if Linux kernel enables CPUSETS feature.
- *
- * Return value: 1 if Linux kernel CONFIG_CPUSETS=y; 0 otherwise.
+ * For backwards compatibility only
+ * New users should include processgroup/sched_policy.h directly
  */
-extern bool cpusets_enabled();
-
-/*
- * Check if Linux kernel enables SCHEDTUNE feature (only available in Android
- * common kernel or Linaro LSK, not in mainline Linux as of v4.9)
- *
- * Return value: 1 if Linux kernel CONFIG_CGROUP_SCHEDTUNE=y; 0 otherwise.
- */
-extern bool schedboost_enabled();
-
-/* Keep in sync with THREAD_GROUP_* in frameworks/base/core/java/android/os/Process.java */
-typedef enum {
-    SP_DEFAULT = -1,
-    SP_BACKGROUND = 0,
-    SP_FOREGROUND = 1,
-    SP_SYSTEM = 2,  // can't be used with set_sched_policy()
-    SP_AUDIO_APP = 3,
-    SP_AUDIO_SYS = 4,
-    SP_TOP_APP = 5,
-    SP_RT_APP = 6,
-    SP_RESTRICTED = 7,
-    SP_CNT,
-    SP_MAX = SP_CNT - 1,
-    SP_SYSTEM_DEFAULT = SP_FOREGROUND,
-} SchedPolicy;
-
-extern int set_cpuset_policy(int tid, SchedPolicy policy);
-
-/* Assign thread tid to the cgroup associated with the specified policy.
- * If the thread is a thread group leader, that is it's gettid() == getpid(),
- * then the other threads in the same thread group are _not_ affected.
- * On platforms which support gettid(), zero tid means current thread.
- * Return value: 0 for success, or -errno for error.
- */
-extern int set_sched_policy(int tid, SchedPolicy policy);
-
-/* Return the policy associated with the cgroup of thread tid via policy pointer.
- * On platforms which support gettid(), zero tid means current thread.
- * Return value: 0 for success, or -1 for error and set errno.
- */
-extern int get_sched_policy(int tid, SchedPolicy *policy);
-
-/* Return a displayable string corresponding to policy.
- * Return value: non-NULL NUL-terminated name of unspecified length;
- * the caller is responsible for displaying the useful part of the string.
- */
-extern const char *get_sched_policy_name(SchedPolicy policy);
-
-#ifdef __cplusplus
-}
-#endif
+#include <processgroup/sched_policy.h>
 
 #endif /* __CUTILS_SCHED_POLICY_H */ 
diff --git a/libcutils/tests/Android.bp b/libcutils/tests/Android.bp
index 7884190..72ae559 100644
--- a/libcutils/tests/Android.bp
+++ b/libcutils/tests/Android.bp
@@ -59,6 +59,7 @@
     "libcutils",
     "liblog",
     "libbase",
+    "libprocessgroup",
 ]
 
 cc_test {
diff --git a/liblog/Android.bp b/liblog/Android.bp
index 4fd36f5..bd7a551 100644
--- a/liblog/Android.bp
+++ b/liblog/Android.bp
@@ -73,6 +73,7 @@
             cflags: ["-DFAKE_LOG_DEVICE=1"],
         },
         android: {
+            version_script: "liblog.map.txt",
             srcs: liblog_target_sources,
             // AddressSanitizer runtime library depends on liblog.
             sanitize: {
diff --git a/liblog/liblog.map.txt b/liblog/liblog.map.txt
index 015c9cb..191ef1b 100644
--- a/liblog/liblog.map.txt
+++ b/liblog/liblog.map.txt
@@ -59,3 +59,24 @@
     android_log_reset; #vndk
     android_log_parser_reset; #vndk
 };
+
+LIBLOG_PRIVATE {
+  global:
+    __android_log_bswrite;
+    __android_log_btwrite;
+    __android_log_bwrite;
+    __android_log_close;
+    __android_log_pmsg_file_read;
+    __android_log_pmsg_file_write;
+    __android_log_security;
+    __android_log_security_bswrite;
+    __android_logger_get_buffer_size;
+    __android_logger_property_get_bool;
+    android_openEventTagMap;
+    android_log_processBinaryLogBuffer;
+    android_log_processLogBuffer;
+    android_log_read_next;
+    android_log_write_list_buffer;
+    android_lookupEventTagNum;
+    create_android_log_parser;
+};
diff --git a/libmeminfo/include/meminfo/pageacct.h b/libmeminfo/include/meminfo/pageacct.h
index 8ddaef2..8483d84 100644
--- a/libmeminfo/include/meminfo/pageacct.h
+++ b/libmeminfo/include/meminfo/pageacct.h
@@ -65,5 +65,17 @@
     ::android::base::unique_fd pageidle_fd_;
 };
 
+// Returns if the page present bit is set in the value
+// passed in.
+bool page_present(uint64_t pagemap_val);
+
+// Returns if the page swapped bit is set in the value
+// passed in.
+bool page_swapped(uint64_t pagemap_val);
+
+// Returns the page frame number (physical page) from
+// pagemap value
+uint64_t page_pfn(uint64_t pagemap_val);
+
 }  // namespace meminfo
 }  // namespace android
diff --git a/libmeminfo/include/meminfo/procmeminfo.h b/libmeminfo/include/meminfo/procmeminfo.h
index 0b66074..95e5053 100644
--- a/libmeminfo/include/meminfo/procmeminfo.h
+++ b/libmeminfo/include/meminfo/procmeminfo.h
@@ -73,6 +73,13 @@
 
     const std::vector<uint16_t>& SwapOffsets();
 
+    // Reads /proc/<pid>/pagemap for this process for each page within
+    // the 'vma' and stores that in 'pagemap'. It is assumed that the 'vma'
+    // is obtained by calling Maps() or 'ForEachVma' for the same object. No special checks
+    // are made to see if 'vma' is *valid*.
+    // Returns false if anything goes wrong, 'true' otherwise.
+    bool PageMap(const Vma& vma, std::vector<uint64_t>* pagemap);
+
     ~ProcMemInfo() = default;
 
   private:
diff --git a/libmeminfo/include/meminfo/sysmeminfo.h b/libmeminfo/include/meminfo/sysmeminfo.h
index 450a469..8388920 100644
--- a/libmeminfo/include/meminfo/sysmeminfo.h
+++ b/libmeminfo/include/meminfo/sysmeminfo.h
@@ -58,7 +58,7 @@
     // in vmalloc area by the kernel.
     // Note that this deliberately ignores binder buffers. They are _always_
     // mapped in a process and are counted for in each process.
-    uint64_t ReadVmallocInfo(const std::string& path = "/proc/vmallocinfo");
+    uint64_t ReadVmallocInfo();
 
     // getters
     uint64_t mem_total_kb() { return mem_in_kb_[kMemTotal]; }
@@ -84,5 +84,10 @@
                      std::function<void(const std::string&, uint64_t)> store_val);
 };
 
+// Parse /proc/vmallocinfo and return total physical memory mapped
+// in vmalloc area by the kernel. Note that this deliberately ignores binder buffers. They are
+// _always_ mapped in a process and are counted for in each process.
+uint64_t ReadVmallocInfo(const std::string& path = "/proc/vmallocinfo");
+
 }  // namespace meminfo
 }  // namespace android
diff --git a/libmeminfo/libmeminfo_benchmark.cpp b/libmeminfo/libmeminfo_benchmark.cpp
index 81fc3b3..d88919b 100644
--- a/libmeminfo/libmeminfo_benchmark.cpp
+++ b/libmeminfo/libmeminfo_benchmark.cpp
@@ -455,8 +455,7 @@
     std::string vmallocinfo =
             ::android::base::StringPrintf("%s/testdata1/vmallocinfo", exec_dir.c_str());
     for (auto _ : state) {
-        SysMemInfo smi;
-        CHECK_EQ(smi.ReadVmallocInfo(vmallocinfo), 29884416);
+        CHECK_EQ(::android::meminfo::ReadVmallocInfo(vmallocinfo), 29884416);
     }
 }
 BENCHMARK(BM_VmallocInfo_new);
diff --git a/libmeminfo/libmeminfo_test.cpp b/libmeminfo/libmeminfo_test.cpp
index 7d85dd2..ccc40d1 100644
--- a/libmeminfo/libmeminfo_test.cpp
+++ b/libmeminfo/libmeminfo_test.cpp
@@ -121,6 +121,23 @@
     EXPECT_EQ(proc_usage.swap / getpagesize(), swap_offsets.size());
 }
 
+TEST_F(ValidateProcMemInfo, TestPageMap) {
+    std::vector<uint64_t> pagemap;
+
+    auto vma_callback = [&](const Vma& vma) {
+        uint64_t* pmap_out;
+        size_t len;
+        ASSERT_EQ(0, pm_process_pagemap_range(proc, vma.start, vma.end, &pmap_out, &len));
+        ASSERT_TRUE(proc_mem->PageMap(vma, &pagemap));
+
+        EXPECT_EQ(len, ((vma.end - vma.start) / getpagesize()));
+        for (size_t i = 0; i < len; i++) {
+            EXPECT_EQ(pmap_out[i], pagemap[i]);
+        }
+    };
+    ASSERT_TRUE(proc_mem->ForEachVma(vma_callback));
+}
+
 class ValidateProcMemInfoWss : public ::testing::Test {
   protected:
     void SetUp() override {
@@ -844,8 +861,7 @@
     ASSERT_TRUE(::android::base::WriteStringToFd(vmallocinfo, tf.fd));
     std::string file = std::string(tf.path);
 
-    SysMemInfo smi;
-    EXPECT_EQ(smi.ReadVmallocInfo(file), 0);
+    EXPECT_EQ(ReadVmallocInfo(file), 0);
 }
 
 TEST(SysMemInfoParser, TestVmallocInfoKernel) {
@@ -857,8 +873,7 @@
     ASSERT_TRUE(::android::base::WriteStringToFd(vmallocinfo, tf.fd));
     std::string file = std::string(tf.path);
 
-    SysMemInfo smi;
-    EXPECT_EQ(smi.ReadVmallocInfo(file), getpagesize());
+    EXPECT_EQ(ReadVmallocInfo(file), getpagesize());
 }
 
 TEST(SysMemInfoParser, TestVmallocInfoModule) {
@@ -870,8 +885,7 @@
     ASSERT_TRUE(::android::base::WriteStringToFd(vmallocinfo, tf.fd));
     std::string file = std::string(tf.path);
 
-    SysMemInfo smi;
-    EXPECT_EQ(smi.ReadVmallocInfo(file), 6 * getpagesize());
+    EXPECT_EQ(ReadVmallocInfo(file), 6 * getpagesize());
 }
 
 TEST(SysMemInfoParser, TestVmallocInfoAll) {
@@ -888,8 +902,7 @@
     ASSERT_TRUE(::android::base::WriteStringToFd(vmallocinfo, tf.fd));
     std::string file = std::string(tf.path);
 
-    SysMemInfo smi;
-    EXPECT_EQ(smi.ReadVmallocInfo(file), 7 * getpagesize());
+    EXPECT_EQ(ReadVmallocInfo(file), 7 * getpagesize());
 }
 
 int main(int argc, char** argv) {
diff --git a/libmeminfo/pageacct.cpp b/libmeminfo/pageacct.cpp
index 887a74d..0a26c08 100644
--- a/libmeminfo/pageacct.cpp
+++ b/libmeminfo/pageacct.cpp
@@ -138,5 +138,18 @@
     return !!(idle_bits & (1ULL << (pfn % 64)));
 }
 
+// Public methods
+bool page_present(uint64_t pagemap_val) {
+    return PAGE_PRESENT(pagemap_val);
+}
+
+bool page_swapped(uint64_t pagemap_val) {
+    return PAGE_SWAPPED(pagemap_val);
+}
+
+uint64_t page_pfn(uint64_t pagemap_val) {
+    return PAGE_PFN(pagemap_val);
+}
+
 }  // namespace meminfo
 }  // namespace android
diff --git a/libmeminfo/procmeminfo.cpp b/libmeminfo/procmeminfo.cpp
index d6332a3..1df03b2 100644
--- a/libmeminfo/procmeminfo.cpp
+++ b/libmeminfo/procmeminfo.cpp
@@ -199,6 +199,33 @@
     return swap_offsets_;
 }
 
+bool ProcMemInfo::PageMap(const Vma& vma, std::vector<uint64_t>* pagemap) {
+    pagemap->clear();
+    std::string pagemap_file = ::android::base::StringPrintf("/proc/%d/pagemap", pid_);
+    ::android::base::unique_fd pagemap_fd(
+            TEMP_FAILURE_RETRY(open(pagemap_file.c_str(), O_RDONLY | O_CLOEXEC)));
+    if (pagemap_fd < 0) {
+        PLOG(ERROR) << "Failed to open " << pagemap_file;
+        return false;
+    }
+
+    uint64_t nr_pages = (vma.end - vma.start) / getpagesize();
+    pagemap->reserve(nr_pages);
+
+    uint64_t idx = vma.start / getpagesize();
+    uint64_t last = idx + nr_pages;
+    uint64_t val;
+    for (; idx < last; idx++) {
+        if (pread64(pagemap_fd, &val, sizeof(uint64_t), idx * sizeof(uint64_t)) < 0) {
+            PLOG(ERROR) << "Failed to read page frames from page map for pid: " << pid_;
+            return false;
+        }
+        pagemap->emplace_back(val);
+    }
+
+    return true;
+}
+
 bool ProcMemInfo::ReadMaps(bool get_wss) {
     // Each object reads /proc/<pid>/maps only once. This is done to make sure programs that are
     // running for the lifetime of the system can recycle the objects and don't have to
diff --git a/libmeminfo/sysmeminfo.cpp b/libmeminfo/sysmeminfo.cpp
index 8fd18d0..5cfa6c3 100644
--- a/libmeminfo/sysmeminfo.cpp
+++ b/libmeminfo/sysmeminfo.cpp
@@ -79,36 +79,8 @@
     });
 }
 
-uint64_t SysMemInfo::ReadVmallocInfo(const std::string& path) {
-    uint64_t vmalloc_total = 0;
-    auto fp = std::unique_ptr<FILE, decltype(&fclose)>{fopen(path.c_str(), "re"), fclose};
-    if (fp == nullptr) {
-        return vmalloc_total;
-    }
-
-    char line[1024];
-    while (fgets(line, 1024, fp.get()) != nullptr) {
-        // We are looking for lines like
-        // 0x0000000000000000-0x0000000000000000   12288 drm_property_create_blob+0x44/0xec pages=2
-        // vmalloc 0x0000000000000000-0x0000000000000000    8192
-        // wlan_logging_sock_init_svc+0xf8/0x4f0 [wlan] pages=1 vmalloc Notice that if the caller is
-        // coming from a module, the kernel prints and extra "[module_name]" after the address and
-        // the symbol of the call site. This means we can't use the old sscanf() method of getting
-        // the # of pages.
-        char* p_start = strstr(line, "pages=");
-        if (p_start == nullptr) {
-            // we didn't find anything
-            continue;
-        }
-
-        p_start = strtok(p_start, " ");
-        long nr_pages;
-        if (sscanf(p_start, "pages=%ld", &nr_pages) == 1) {
-            vmalloc_total += (nr_pages * getpagesize());
-        }
-    }
-
-    return vmalloc_total;
+uint64_t SysMemInfo::ReadVmallocInfo() {
+    return ::android::meminfo::ReadVmallocInfo();
 }
 
 // TODO: Delete this function if it can't match up with the c-like implementation below.
@@ -263,5 +235,41 @@
     return false;
 }
 
+// Public methods
+uint64_t ReadVmallocInfo(const std::string& path) {
+    uint64_t vmalloc_total = 0;
+    auto fp = std::unique_ptr<FILE, decltype(&fclose)>{fopen(path.c_str(), "re"), fclose};
+    if (fp == nullptr) {
+        return vmalloc_total;
+    }
+
+    char* line = nullptr;
+    size_t line_alloc = 0;
+    while (getline(&line, &line_alloc, fp.get()) > 0) {
+        // We are looking for lines like
+        //
+        // 0x0000000000000000-0x0000000000000000   12288 drm_property_create_blob+0x44/0xec pages=2 vmalloc
+        // 0x0000000000000000-0x0000000000000000    8192 wlan_logging_sock_init_svc+0xf8/0x4f0 [wlan] pages=1 vmalloc
+        //
+        // Notice that if the caller is coming from a module, the kernel prints and extra
+        // "[module_name]" after the address and the symbol of the call site. This means we can't
+        // use the old sscanf() method of getting the # of pages.
+        char* p_start = strstr(line, "pages=");
+        if (p_start == nullptr) {
+            // we didn't find anything
+            continue;
+        }
+
+        uint64_t nr_pages;
+        if (sscanf(p_start, "pages=%" SCNu64 "", &nr_pages) == 1) {
+            vmalloc_total += (nr_pages * getpagesize());
+        }
+    }
+
+    free(line);
+
+    return vmalloc_total;
+}
+
 }  // namespace meminfo
 }  // namespace android
diff --git a/libmeminfo/tools/Android.bp b/libmeminfo/tools/Android.bp
index c852bbb..24054c6 100644
--- a/libmeminfo/tools/Android.bp
+++ b/libmeminfo/tools/Android.bp
@@ -13,7 +13,7 @@
 // limitations under the License.
 
 cc_binary {
-    name: "librank2",
+    name: "librank",
     cflags: [
         "-Wall",
         "-Werror",
@@ -27,7 +27,7 @@
 }
 
 cc_binary {
-    name: "procmem2",
+    name: "procmem",
     cflags: [
         "-Wall",
         "-Werror",
@@ -41,7 +41,7 @@
 }
 
 cc_binary {
-    name: "procrank2",
+    name: "procrank",
     cflags: [
         "-Wall",
         "-Werror",
@@ -55,7 +55,7 @@
 }
 
 cc_binary {
-    name: "showmap2",
+    name: "showmap",
     cflags: [
         "-Wall",
         "-Werror",
diff --git a/libmemtrack/.clang-format b/libmemtrack/.clang-format
new file mode 120000
index 0000000..1af4f51
--- /dev/null
+++ b/libmemtrack/.clang-format
@@ -0,0 +1 @@
+../.clang-format-4
\ No newline at end of file
diff --git a/libmemtrack/Android.bp b/libmemtrack/Android.bp
index 0955633..4e4554a 100644
--- a/libmemtrack/Android.bp
+++ b/libmemtrack/Android.bp
@@ -28,10 +28,11 @@
 
 cc_binary {
     name: "memtrack_test",
-    srcs: ["memtrack_test.c"],
+    srcs: ["memtrack_test.cpp"],
+    static_libs: ["libc++fs"],
     shared_libs: [
+        "libbase",
         "libmemtrack",
-        "libpagemap",
     ],
     cflags: [
         "-Wall",
diff --git a/libmemtrack/memtrack_test.c b/libmemtrack/memtrack_test.c
deleted file mode 100644
index 77c935e..0000000
--- a/libmemtrack/memtrack_test.c
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * Copyright (C) 2013 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 <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-
-#include <memtrack/memtrack.h>
-
-#include <pagemap/pagemap.h>
-
-#define DIV_ROUND_UP(x,y) (((x) + (y) - 1) / (y))
-
-static int getprocname(pid_t pid, char *buf, int len) {
-    char *filename;
-    FILE *f;
-    int rc = 0;
-    static const char* unknown_cmdline = "<unknown>";
-
-    if (len <= 0) {
-        return -1;
-    }
-
-    if (asprintf(&filename, "/proc/%d/cmdline", pid) < 0) {
-        rc = 1;
-        goto exit;
-    }
-
-    f = fopen(filename, "r");
-    if (f == NULL) {
-        rc = 2;
-        goto releasefilename;
-    }
-
-    if (fgets(buf, len, f) == NULL) {
-        rc = 3;
-        goto closefile;
-    }
-
-closefile:
-    (void) fclose(f);
-releasefilename:
-    free(filename);
-exit:
-    if (rc != 0) {
-        /*
-         * The process went away before we could read its process name. Try
-         * to give the user "<unknown>" here, but otherwise they get to look
-         * at a blank.
-         */
-        if (strlcpy(buf, unknown_cmdline, (size_t)len) >= (size_t)len) {
-            rc = 4;
-        }
-    }
-
-    return rc;
-}
-
-int main(int argc, char *argv[])
-{
-    int ret;
-    pm_kernel_t *ker;
-    size_t num_procs;
-    pid_t *pids;
-    struct memtrack_proc *p;
-    size_t i;
-
-    (void)argc;
-    (void)argv;
-
-    ret = pm_kernel_create(&ker);
-    if (ret) {
-        fprintf(stderr, "Error creating kernel interface -- "
-                        "does this kernel have pagemap?\n");
-        exit(EXIT_FAILURE);
-    }
-
-    ret = pm_kernel_pids(ker, &pids, &num_procs);
-    if (ret) {
-        fprintf(stderr, "Error listing processes.\n");
-        exit(EXIT_FAILURE);
-    }
-
-    p = memtrack_proc_new();
-    if (ret) {
-        fprintf(stderr, "failed to create memtrack process handle\n");
-        exit(EXIT_FAILURE);
-    }
-
-    for (i = 0; i < num_procs; i++) {
-        pid_t pid = pids[i];
-        char cmdline[256];
-        size_t v1;
-        size_t v2;
-        size_t v3;
-        size_t v4;
-        size_t v5;
-        size_t v6;
-
-        getprocname(pid, cmdline, (int)sizeof(cmdline));
-
-        ret = memtrack_proc_get(p, pid);
-        if (ret) {
-            fprintf(stderr, "failed to get memory info for pid %d: %s (%d)\n",
-                    pid, strerror(-ret), ret);
-            continue;
-        }
-
-        v1 = DIV_ROUND_UP(memtrack_proc_graphics_total(p), 1024);
-        v2 = DIV_ROUND_UP(memtrack_proc_graphics_pss(p), 1024);
-        v3 = DIV_ROUND_UP(memtrack_proc_gl_total(p), 1024);
-        v4 = DIV_ROUND_UP(memtrack_proc_gl_pss(p), 1024);
-        v5 = DIV_ROUND_UP(memtrack_proc_other_total(p), 1024);
-        v6 = DIV_ROUND_UP(memtrack_proc_other_pss(p), 1024);
-
-        if (v1 | v2 | v3 | v4 | v5 | v6) {
-            printf("%5d %6zu %6zu %6zu %6zu %6zu %6zu %s\n", pid,
-                   v1, v2, v3, v4, v5, v6, cmdline);
-        }
-    }
-
-    memtrack_proc_destroy(p);
-
-    return 0;
-}
diff --git a/libmemtrack/memtrack_test.cpp b/libmemtrack/memtrack_test.cpp
new file mode 100644
index 0000000..aeeaf24
--- /dev/null
+++ b/libmemtrack/memtrack_test.cpp
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2013 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include <filesystem>
+#include <vector>
+
+#include <android-base/file.h>
+#include <android-base/parseint.h>
+#include <android-base/stringprintf.h>
+#include <memtrack/memtrack.h>
+
+#define DIV_ROUND_UP(x, y) (((x) + (y)-1) / (y))
+
+static void getprocname(pid_t pid, std::string* name) {
+    std::string fname = ::android::base::StringPrintf("/proc/%d/cmdline", pid);
+    if (!::android::base::ReadFileToString(fname, name)) {
+        fprintf(stderr, "Failed to read cmdline from: %s\n", fname.c_str());
+        *name = "<unknown>";
+    }
+}
+
+int main(int /* argc */, char** /* argv */) {
+    int ret;
+    struct memtrack_proc* p;
+    std::vector<pid_t> pids;
+
+    p = memtrack_proc_new();
+    if (p == nullptr) {
+        fprintf(stderr, "failed to create memtrack process handle\n");
+        exit(EXIT_FAILURE);
+    }
+
+    for (auto& de : std::filesystem::directory_iterator("/proc")) {
+        if (!std::filesystem::is_directory(de.status())) {
+            continue;
+        }
+
+        pid_t pid;
+        if (!::android::base::ParseInt(de.path().filename().string(), &pid)) {
+            continue;
+        }
+        pids.emplace_back(pid);
+    }
+
+    for (auto& pid : pids) {
+        size_t v1;
+        size_t v2;
+        size_t v3;
+        size_t v4;
+        size_t v5;
+        size_t v6;
+        std::string cmdline;
+
+        getprocname(pid, &cmdline);
+
+        ret = memtrack_proc_get(p, pid);
+        if (ret) {
+            fprintf(stderr, "failed to get memory info for pid %d: %s (%d)\n", pid, strerror(-ret),
+                    ret);
+            continue;
+        }
+
+        v1 = DIV_ROUND_UP(memtrack_proc_graphics_total(p), 1024);
+        v2 = DIV_ROUND_UP(memtrack_proc_graphics_pss(p), 1024);
+        v3 = DIV_ROUND_UP(memtrack_proc_gl_total(p), 1024);
+        v4 = DIV_ROUND_UP(memtrack_proc_gl_pss(p), 1024);
+        v5 = DIV_ROUND_UP(memtrack_proc_other_total(p), 1024);
+        v6 = DIV_ROUND_UP(memtrack_proc_other_pss(p), 1024);
+
+        if (v1 | v2 | v3 | v4 | v5 | v6) {
+            fprintf(stdout, "%5d %6zu %6zu %6zu %6zu %6zu %6zu %s\n", pid, v1, v2, v3, v4, v5, v6,
+                    cmdline.c_str());
+        }
+    }
+
+    memtrack_proc_destroy(p);
+
+    return ret;
+}
diff --git a/libnativeloader/include/nativeloader/dlext_namespaces.h b/libnativeloader/include/nativeloader/dlext_namespaces.h
index ca026b3..2d6ce85 100644
--- a/libnativeloader/include/nativeloader/dlext_namespaces.h
+++ b/libnativeloader/include/nativeloader/dlext_namespaces.h
@@ -109,19 +109,6 @@
                                     struct android_namespace_t* to,
                                     const char* shared_libs_sonames);
 
-/*
- * Get the default library search path.
- * The path will be copied into buffer, which must have space for at least
- * buffer_size chars. Elements are separated with ':', and the path will always
- * be null-terminated.
- *
- * If buffer_size is too small to hold the entire default search path and the
- * null terminator, this function will abort. There is currently no way to find
- * out what the required buffer size is. At the time of this writing, PATH_MAX
- * is sufficient and used by all callers of this function.
- */
-extern void android_get_LD_LIBRARY_PATH(char* buffer, size_t buffer_size);
-
 extern struct android_namespace_t* android_get_exported_namespace(const char* name);
 
 __END_DECLS
diff --git a/libnativeloader/include/nativeloader/native_loader.h b/libnativeloader/include/nativeloader/native_loader.h
index af53dc5..260f655 100644
--- a/libnativeloader/include/nativeloader/native_loader.h
+++ b/libnativeloader/include/nativeloader/native_loader.h
@@ -47,7 +47,7 @@
 
 __attribute__((visibility("default"))) void* OpenNativeLibrary(
     JNIEnv* env, int32_t target_sdk_version, const char* path, jobject class_loader,
-    jstring library_path, bool* needs_native_bridge, char** error_msg);
+    const char* caller_location, jstring library_path, bool* needs_native_bridge, char** error_msg);
 
 __attribute__((visibility("default"))) bool CloseNativeLibrary(void* handle,
                                                                const bool needs_native_bridge,
diff --git a/libnativeloader/native_loader.cpp b/libnativeloader/native_loader.cpp
index af7df72..ad967db 100644
--- a/libnativeloader/native_loader.cpp
+++ b/libnativeloader/native_loader.cpp
@@ -119,6 +119,8 @@
 // This list includes all directories app is allowed to access this way.
 static constexpr const char* kWhitelistedDirectories = "/data:/mnt/expand";
 
+static constexpr const char* kApexPath = "/apex/";
+
 static bool is_debuggable() {
   char debuggable[PROP_VALUE_MAX];
   property_get("ro.debuggable", debuggable, "0");
@@ -623,13 +625,51 @@
   return nullptr;
 }
 
+#if defined(__ANDROID__)
+static android_namespace_t* FindExportedNamespace(const char* caller_location) {
+  std::string location = caller_location;
+  // Lots of implicit assumptions here: we expect `caller_location` to be of the form:
+  // /apex/com.android...modulename/...
+  //
+  // And we extract from it 'modulename', which is the name of the linker namespace.
+  if (android::base::StartsWith(location, kApexPath)) {
+    size_t slash_index = location.find_first_of('/', strlen(kApexPath));
+    LOG_ALWAYS_FATAL_IF((slash_index == std::string::npos),
+                        "Error finding namespace of apex: no slash in path %s", caller_location);
+    size_t dot_index = location.find_last_of('.', slash_index);
+    LOG_ALWAYS_FATAL_IF((dot_index == std::string::npos),
+                        "Error finding namespace of apex: no dot in apex name %s", caller_location);
+    std::string name = location.substr(dot_index + 1, slash_index - dot_index - 1);
+    android_namespace_t* boot_namespace = android_get_exported_namespace(name.c_str());
+    LOG_ALWAYS_FATAL_IF((boot_namespace == nullptr),
+                        "Error finding namespace of apex: no namespace called %s", name.c_str());
+    return boot_namespace;
+  }
+  return nullptr;
+}
+#endif
+
 void* OpenNativeLibrary(JNIEnv* env, int32_t target_sdk_version, const char* path,
-                        jobject class_loader, jstring library_path, bool* needs_native_bridge,
-                        char** error_msg) {
+                        jobject class_loader, const char* caller_location, jstring library_path,
+                        bool* needs_native_bridge, char** error_msg) {
 #if defined(__ANDROID__)
   UNUSED(target_sdk_version);
   if (class_loader == nullptr) {
     *needs_native_bridge = false;
+    if (caller_location != nullptr) {
+      android_namespace_t* boot_namespace = FindExportedNamespace(caller_location);
+      if (boot_namespace != nullptr) {
+        const android_dlextinfo dlextinfo = {
+            .flags = ANDROID_DLEXT_USE_NAMESPACE,
+            .library_namespace = boot_namespace,
+        };
+        void* handle = android_dlopen_ext(path, RTLD_NOW, &dlextinfo);
+        if (handle == nullptr) {
+          *error_msg = strdup(dlerror());
+        }
+        return handle;
+      }
+    }
     void* handle = dlopen(path, RTLD_NOW);
     if (handle == nullptr) {
       *error_msg = strdup(dlerror());
@@ -654,7 +694,7 @@
 
   return OpenNativeLibraryInNamespace(ns, path, needs_native_bridge, error_msg);
 #else
-  UNUSED(env, target_sdk_version, class_loader);
+  UNUSED(env, target_sdk_version, class_loader, caller_location);
 
   // Do some best effort to emulate library-path support. It will not
   // work for dependencies.
diff --git a/libprocessgroup/Android.bp b/libprocessgroup/Android.bp
index c38279d..d04a79a 100644
--- a/libprocessgroup/Android.bp
+++ b/libprocessgroup/Android.bp
@@ -1,10 +1,45 @@
+cc_library_headers {
+    name: "libprocessgroup_headers",
+    vendor_available: true,
+    recovery_available: true,
+    host_supported: true,
+    export_include_dirs: ["include"],
+    target: {
+        linux_bionic: {
+            enabled: true,
+        },
+        windows: {
+            enabled: true,
+        },
+    },
+}
+
 cc_library {
-    srcs: ["processgroup.cpp"],
+    srcs: [
+        "processgroup.cpp",
+        "sched_policy.cpp",
+    ],
     name: "libprocessgroup",
     host_supported: true,
     recovery_available: true,
-    shared_libs: ["libbase"],
+    vendor_available: true,
+    vndk: {
+        enabled: true,
+        support_system_process: true,
+    },
+    shared_libs: [
+        "libbase",
+        "liblog",
+    ],
+    // for cutils/android_filesystem_config.h
+    header_libs: [
+        "libcutils_headers",
+        "libprocessgroup_headers",
+    ],
     export_include_dirs: ["include"],
+    export_header_lib_headers: [
+        "libprocessgroup_headers",
+    ],
     cflags: [
         "-Wall",
         "-Werror",
diff --git a/libprocessgroup/include/processgroup/sched_policy.h b/libprocessgroup/include/processgroup/sched_policy.h
new file mode 100644
index 0000000..79a32fd
--- /dev/null
+++ b/libprocessgroup/include/processgroup/sched_policy.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <stdbool.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Check if Linux kernel enables CPUSETS feature.
+ *
+ * Return value: 1 if Linux kernel CONFIG_CPUSETS=y; 0 otherwise.
+ */
+extern bool cpusets_enabled();
+
+/*
+ * Check if Linux kernel enables SCHEDTUNE feature (only available in Android
+ * common kernel or Linaro LSK, not in mainline Linux as of v4.9)
+ *
+ * Return value: 1 if Linux kernel CONFIG_CGROUP_SCHEDTUNE=y; 0 otherwise.
+ */
+extern bool schedboost_enabled();
+
+/* Keep in sync with THREAD_GROUP_* in frameworks/base/core/java/android/os/Process.java */
+typedef enum {
+    SP_DEFAULT = -1,
+    SP_BACKGROUND = 0,
+    SP_FOREGROUND = 1,
+    SP_SYSTEM = 2,  // can't be used with set_sched_policy()
+    SP_AUDIO_APP = 3,
+    SP_AUDIO_SYS = 4,
+    SP_TOP_APP = 5,
+    SP_RT_APP = 6,
+    SP_RESTRICTED = 7,
+    SP_CNT,
+    SP_MAX = SP_CNT - 1,
+    SP_SYSTEM_DEFAULT = SP_FOREGROUND,
+} SchedPolicy;
+
+extern int set_cpuset_policy(int tid, SchedPolicy policy);
+
+/* Assign thread tid to the cgroup associated with the specified policy.
+ * If the thread is a thread group leader, that is it's gettid() == getpid(),
+ * then the other threads in the same thread group are _not_ affected.
+ * On platforms which support gettid(), zero tid means current thread.
+ * Return value: 0 for success, or -errno for error.
+ */
+extern int set_sched_policy(int tid, SchedPolicy policy);
+
+/* Return the policy associated with the cgroup of thread tid via policy pointer.
+ * On platforms which support gettid(), zero tid means current thread.
+ * Return value: 0 for success, or -1 for error and set errno.
+ */
+extern int get_sched_policy(int tid, SchedPolicy *policy);
+
+/* Return a displayable string corresponding to policy.
+ * Return value: non-NULL NUL-terminated name of unspecified length;
+ * the caller is responsible for displaying the useful part of the string.
+ */
+extern const char *get_sched_policy_name(SchedPolicy policy);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/libprocessgroup/processgroup.cpp b/libprocessgroup/processgroup.cpp
index 9df8dd9..8d2ac3d 100644
--- a/libprocessgroup/processgroup.cpp
+++ b/libprocessgroup/processgroup.cpp
@@ -42,7 +42,7 @@
 #include <android-base/properties.h>
 #include <android-base/stringprintf.h>
 #include <android-base/strings.h>
-#include <private/android_filesystem_config.h>
+#include <cutils/android_filesystem_config.h>
 
 #include <processgroup/processgroup.h>
 
diff --git a/libcutils/sched_policy.cpp b/libprocessgroup/sched_policy.cpp
similarity index 99%
rename from libcutils/sched_policy.cpp
rename to libprocessgroup/sched_policy.cpp
index 3fa548f..f95d7e4 100644
--- a/libcutils/sched_policy.cpp
+++ b/libprocessgroup/sched_policy.cpp
@@ -14,7 +14,7 @@
 ** limitations under the License.
 */
 
-#include <cutils/sched_policy.h>
+#include <processgroup/sched_policy.h>
 
 #define LOG_TAG "SchedPolicy"
 
diff --git a/libunwindstack/Unwinder.cpp b/libunwindstack/Unwinder.cpp
index 57207de..0dd95cf 100644
--- a/libunwindstack/Unwinder.cpp
+++ b/libunwindstack/Unwinder.cpp
@@ -144,7 +144,6 @@
 
   bool return_address_attempt = false;
   bool adjust_pc = false;
-  std::unique_ptr<JitDebug> jit_debug;
   for (; frames_.size() < max_frames_;) {
     uint64_t cur_pc = regs_->pc();
     uint64_t cur_sp = regs_->sp();
diff --git a/libutils/Android.bp b/libutils/Android.bp
index 3e8417e..fb7ca32 100644
--- a/libutils/Android.bp
+++ b/libutils/Android.bp
@@ -22,11 +22,13 @@
         "liblog_headers",
         "libsystem_headers",
         "libcutils_headers",
+        "libprocessgroup_headers",
     ],
     export_header_lib_headers: [
         "liblog_headers",
         "libsystem_headers",
         "libcutils_headers",
+        "libprocessgroup_headers",
     ],
     export_include_dirs: ["include"],
 
@@ -82,6 +84,7 @@
 
             shared_libs: [
                 "libcutils",
+                "libprocessgroup",
                 "libdl",
                 "libvndksupport",
             ],
diff --git a/libutils/Threads.cpp b/libutils/Threads.cpp
index 64bc402..31ca138 100644
--- a/libutils/Threads.cpp
+++ b/libutils/Threads.cpp
@@ -36,7 +36,7 @@
 
 #include <utils/Log.h>
 
-#include <cutils/sched_policy.h>
+#include <processgroup/sched_policy.h>
 
 #if defined(__ANDROID__)
 # define __android_unused
diff --git a/lmkd/Android.bp b/lmkd/Android.bp
index 903d0e2..f9ed57c 100644
--- a/lmkd/Android.bp
+++ b/lmkd/Android.bp
@@ -5,6 +5,7 @@
     shared_libs: [
         "libcutils",
         "liblog",
+        "libprocessgroup",
     ],
     static_libs: [
         "libstatslogc",
diff --git a/logcat/Android.bp b/logcat/Android.bp
index 0543aba..5030b15 100644
--- a/logcat/Android.bp
+++ b/logcat/Android.bp
@@ -24,8 +24,8 @@
     ],
     shared_libs: [
         "libbase",
-        "libcutils",
         "libpcrecpp",
+        "libprocessgroup",
     ],
     static_libs: ["liblog"],
     logtags: ["event.logtags"],
diff --git a/logcat/logcat.cpp b/logcat/logcat.cpp
index 87bc6ae..15e07fe 100644
--- a/logcat/logcat.cpp
+++ b/logcat/logcat.cpp
@@ -49,11 +49,11 @@
 #include <android-base/properties.h>
 #include <android-base/stringprintf.h>
 #include <android-base/strings.h>
-#include <cutils/sched_policy.h>
 #include <cutils/sockets.h>
 #include <log/event_tag_map.h>
 #include <log/logprint.h>
 #include <private/android_logger.h>
+#include <processgroup/sched_policy.h>
 #include <system/thread_defs.h>
 
 #include <pcrecpp.h>
diff --git a/logd/Android.bp b/logd/Android.bp
index 3abfc21..bdbdf12 100644
--- a/logd/Android.bp
+++ b/logd/Android.bp
@@ -73,6 +73,7 @@
         "libcutils",
         "libbase",
         "libpackagelistparser",
+        "libprocessgroup",
         "libcap",
     ],
 
diff --git a/logd/Android.mk b/logd/Android.mk
index b3ce560..aafa28d 100644
--- a/logd/Android.mk
+++ b/logd/Android.mk
@@ -5,7 +5,6 @@
 LOCAL_MODULE := logtagd.rc
 LOCAL_SRC_FILES := $(LOCAL_MODULE)
 LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_TAGS := debug
 LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/init
 
 include $(BUILD_PREBUILT)
diff --git a/logd/main.cpp b/logd/main.cpp
index 8c38d9a..fd3cdf8 100644
--- a/logd/main.cpp
+++ b/logd/main.cpp
@@ -38,12 +38,12 @@
 #include <android-base/macros.h>
 #include <cutils/android_get_control_file.h>
 #include <cutils/properties.h>
-#include <cutils/sched_policy.h>
 #include <cutils/sockets.h>
 #include <log/event_tag_map.h>
 #include <packagelistparser/packagelistparser.h>
 #include <private/android_filesystem_config.h>
 #include <private/android_logger.h>
+#include <processgroup/sched_policy.h>
 #include <utils/threads.h>
 
 #include "CommandListener.h"
diff --git a/property_service/libpropertyinfoparser/Android.bp b/property_service/libpropertyinfoparser/Android.bp
index 6637deb..5c57d69 100644
--- a/property_service/libpropertyinfoparser/Android.bp
+++ b/property_service/libpropertyinfoparser/Android.bp
@@ -13,5 +13,6 @@
     ],
     stl: "none",
     system_shared_libs: [],
+    header_libs: ["libc_headers"],
     export_include_dirs: ["include"],
 }
diff --git a/rootdir/Android.mk b/rootdir/Android.mk
index f88f6b9..85c7e9e 100644
--- a/rootdir/Android.mk
+++ b/rootdir/Android.mk
@@ -22,7 +22,6 @@
 LOCAL_MODULE := init-debug.rc
 LOCAL_SRC_FILES := $(LOCAL_MODULE)
 LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_TAGS := debug
 LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/init
 
 include $(BUILD_PREBUILT)
diff --git a/rootdir/etc/ld.config.txt b/rootdir/etc/ld.config.txt
index 2dda648..1d4b1e2 100644
--- a/rootdir/etc/ld.config.txt
+++ b/rootdir/etc/ld.config.txt
@@ -28,7 +28,7 @@
 dir.postinstall = /postinstall
 
 [system]
-additional.namespaces = runtime,sphal,vndk,rs
+additional.namespaces = runtime,conscrypt,media,sphal,vndk,rs
 
 ###############################################################################
 # "default" namespace
@@ -109,7 +109,11 @@
 
 # Keep in sync with ld.config.txt in the com.android.runtime APEX.
 namespace.default.links = runtime
+# Visible because some libraries are dlopen'ed, e.g. libopenjdk is dlopen'ed by
+# libart.
+namespace.default.visible = true
 namespace.default.link.runtime.shared_libs  = libart.so:libartd.so
+namespace.default.link.runtime.shared_libs += libdexfile_external.so
 namespace.default.link.runtime.shared_libs += libnativebridge.so
 namespace.default.link.runtime.shared_libs += libnativehelper.so
 namespace.default.link.runtime.shared_libs += libnativeloader.so
@@ -129,6 +133,37 @@
 namespace.runtime.link.default.allow_all_shared_libs = true
 
 ###############################################################################
+# "media" APEX namespace
+#
+# This namespace is for libraries within the media APEX.
+###############################################################################
+namespace.media.isolated = true
+namespace.media.visible = true
+
+namespace.media.search.paths = /apex/com.android.media/${LIB}
+
+namespace.media.links = default
+namespace.media.link.default.shared_libs  = %LLNDK_LIBRARIES%
+namespace.media.link.default.shared_libs += libandroid.so
+namespace.media.link.default.shared_libs += libbinder_ndk.so
+namespace.media.link.default.shared_libs += %SANITIZER_RUNTIME_LIBRARIES%
+
+###############################################################################
+# "conscrypt" APEX namespace
+#
+# This namespace is for libraries within the conscrypt APEX.
+###############################################################################
+namespace.conscrypt.isolated = true
+namespace.conscrypt.visible = true
+
+# Keep in sync with ld.config.txt in the com.android.runtime APEX.
+namespace.conscrypt.search.paths = /apex/com.android.conscrypt/${LIB}
+namespace.conscrypt.links = default
+namespace.conscrypt.link.default.shared_libs  = libc.so
+namespace.conscrypt.link.default.shared_libs += libm.so
+namespace.conscrypt.link.default.shared_libs += libdl.so
+
+###############################################################################
 # "sphal" namespace
 #
 # SP-HAL(Sameprocess-HAL)s are the only vendor libraries that are allowed to be
@@ -280,7 +315,7 @@
 # (LL-NDK only) access.
 ###############################################################################
 [vendor]
-additional.namespaces = system,vndk
+additional.namespaces = runtime,system,vndk
 
 ###############################################################################
 # "default" namespace
@@ -317,6 +352,20 @@
 namespace.default.link.vndk.shared_libs += %VNDK_CORE_LIBRARIES%
 
 ###############################################################################
+# "runtime" APEX namespace
+#
+# This namespace exposes externally accessible libraries from the Runtime APEX.
+###############################################################################
+namespace.runtime.isolated = true
+
+# Keep in sync with ld.config.txt in the com.android.runtime APEX.
+namespace.runtime.search.paths = /apex/com.android.runtime/${LIB}
+namespace.runtime.links = system
+# TODO(b/119867084): Restrict to Bionic dlopen dependencies and PALette library
+# when it exists.
+namespace.runtime.link.system.allow_all_shared_libs = true
+
+###############################################################################
 # "vndk" namespace
 #
 # This namespace is where VNDK and VNDK-SP libraries are loaded for
@@ -373,6 +422,9 @@
 namespace.system.asan.search.paths += /data/asan/product_services/${LIB}
 namespace.system.asan.search.paths +=           /%PRODUCT_SERVICES%/${LIB}
 
+namespace.system.links = runtime
+namespace.system.link.runtime.shared_libs = libdexfile_external.so
+
 ###############################################################################
 # Namespace config for binaries under /postinstall.
 # Only default namespace is defined and default has no directories
diff --git a/rootdir/etc/ld.config.vndk_lite.txt b/rootdir/etc/ld.config.vndk_lite.txt
index 33b4698..d54156b 100644
--- a/rootdir/etc/ld.config.vndk_lite.txt
+++ b/rootdir/etc/ld.config.vndk_lite.txt
@@ -28,7 +28,7 @@
 dir.postinstall = /postinstall
 
 [system]
-additional.namespaces = runtime,sphal,vndk,rs
+additional.namespaces = runtime,conscrypt,media,sphal,vndk,rs
 
 ###############################################################################
 # "default" namespace
@@ -55,9 +55,14 @@
 namespace.default.asan.search.paths += /data/asan/product_services/${LIB}
 namespace.default.asan.search.paths +=           /%PRODUCT_SERVICES%/${LIB}
 
-# Keep in sync with ld.config.txt in the com.android.runtime APEX.
+# Keep in sync with the platform namespace in the com.android.runtime APEX
+# ld.config.txt.
 namespace.default.links = runtime
+# Visible because some libraries are dlopen'ed, e.g. libopenjdk is dlopen'ed by
+# libart.
+namespace.default.visible = true
 namespace.default.link.runtime.shared_libs  = libart.so:libartd.so
+namespace.default.link.runtime.shared_libs += libdexfile_external.so
 namespace.default.link.runtime.shared_libs += libnativehelper.so
 namespace.default.link.runtime.shared_libs += libnativeloader.so
 
@@ -68,7 +73,8 @@
 ###############################################################################
 namespace.runtime.isolated = true
 
-# Keep in sync with ld.config.txt in the com.android.runtime APEX.
+# Keep in sync with the default namespace in the com.android.runtime APEX
+# ld.config.txt.
 namespace.runtime.search.paths = /apex/com.android.runtime/${LIB}
 namespace.runtime.links = default
 # TODO(b/119867084): Restrict to Bionic dlopen dependencies and PALette library
@@ -76,6 +82,37 @@
 namespace.runtime.link.default.allow_all_shared_libs = true
 
 ###############################################################################
+# "media" APEX namespace
+#
+# This namespace is for libraries within the media APEX.
+###############################################################################
+namespace.media.isolated = true
+namespace.media.visible = true
+
+namespace.media.search.paths = /apex/com.android.media/${LIB}
+
+namespace.media.links = default
+namespace.media.link.default.shared_libs  = %LLNDK_LIBRARIES%
+namespace.media.link.default.shared_libs += libandroid.so
+namespace.media.link.default.shared_libs += libbinder_ndk.so
+namespace.media.link.default.shared_libs += %SANITIZER_RUNTIME_LIBRARIES%
+
+###############################################################################
+# "conscrypt" APEX namespace
+#
+# This namespace is for libraries within the conscrypt APEX.
+###############################################################################
+namespace.conscrypt.isolated = true
+namespace.conscrypt.visible = true
+
+# Keep in sync with ld.config.txt in the com.android.runtime APEX.
+namespace.conscrypt.search.paths = /apex/com.android.conscrypt/${LIB}
+namespace.conscrypt.links = default
+namespace.conscrypt.link.default.shared_libs  = libc.so
+namespace.conscrypt.link.default.shared_libs += libm.so
+namespace.conscrypt.link.default.shared_libs += libdl.so
+
+###############################################################################
 # "sphal" namespace
 #
 # SP-HAL(Sameprocess-HAL)s are the only vendor libraries that are allowed to be
@@ -221,6 +258,8 @@
 # (LL-NDK only) access.
 ###############################################################################
 [vendor]
+additional.namespaces = runtime
+
 namespace.default.isolated = false
 
 namespace.default.search.paths  = /odm/${LIB}
@@ -260,6 +299,23 @@
 namespace.default.asan.search.paths += /data/asan/product_services/${LIB}
 namespace.default.asan.search.paths +=           /%PRODUCT_SERVICES%/${LIB}
 
+namespace.default.links = runtime
+namespace.default.link.runtime.shared_libs = libdexfile_external.so
+
+###############################################################################
+# "runtime" APEX namespace
+#
+# This namespace exposes externally accessible libraries from the Runtime APEX.
+###############################################################################
+namespace.runtime.isolated = true
+
+# Keep in sync with ld.config.txt in the com.android.runtime APEX.
+namespace.runtime.search.paths = /apex/com.android.runtime/${LIB}
+namespace.runtime.links = default
+# TODO(b/119867084): Restrict to Bionic dlopen dependencies and PALette library
+# when it exists.
+namespace.runtime.link.default.allow_all_shared_libs = true
+
 ###############################################################################
 # Namespace config for binaries under /postinstall.
 # Only default namespace is defined and default has no directories
diff --git a/rootdir/init.zygote32.rc b/rootdir/init.zygote32.rc
index ac87979..2e95687 100644
--- a/rootdir/init.zygote32.rc
+++ b/rootdir/init.zygote32.rc
@@ -4,6 +4,7 @@
     user root
     group root readproc reserved_disk
     socket zygote stream 660 root system
+    updatable
     onrestart write /sys/android_power/request_state wake
     onrestart write /sys/power/state on
     onrestart restart audioserver
diff --git a/rootdir/init.zygote32_64.rc b/rootdir/init.zygote32_64.rc
index a535846..1cfc3d6 100644
--- a/rootdir/init.zygote32_64.rc
+++ b/rootdir/init.zygote32_64.rc
@@ -4,6 +4,7 @@
     user root
     group root readproc reserved_disk
     socket zygote stream 660 root system
+    updatable
     onrestart write /sys/android_power/request_state wake
     onrestart write /sys/power/state on
     onrestart restart audioserver
@@ -19,5 +20,6 @@
     user root
     group root readproc reserved_disk
     socket zygote_secondary stream 660 root system
+    updatable
     onrestart restart zygote
     writepid /dev/cpuset/foreground/tasks
diff --git a/rootdir/init.zygote64.rc b/rootdir/init.zygote64.rc
index 6fc810b..8ab012d 100644
--- a/rootdir/init.zygote64.rc
+++ b/rootdir/init.zygote64.rc
@@ -4,6 +4,7 @@
     user root
     group root readproc reserved_disk
     socket zygote stream 660 root system
+    updatable
     onrestart write /sys/android_power/request_state wake
     onrestart write /sys/power/state on
     onrestart restart audioserver
diff --git a/rootdir/init.zygote64_32.rc b/rootdir/init.zygote64_32.rc
index 7ddd52e..5abf149 100644
--- a/rootdir/init.zygote64_32.rc
+++ b/rootdir/init.zygote64_32.rc
@@ -4,6 +4,7 @@
     user root
     group root readproc reserved_disk
     socket zygote stream 660 root system
+    updatable
     onrestart write /sys/android_power/request_state wake
     onrestart write /sys/power/state on
     onrestart restart audioserver
@@ -19,5 +20,6 @@
     user root
     group root readproc reserved_disk
     socket zygote_secondary stream 660 root system
+    updatable
     onrestart restart zygote
     writepid /dev/cpuset/foreground/tasks