Merge "libsnapshot: Don't compare strings for snapshot state."
diff --git a/adb/adb_utils.h b/adb/adb_utils.h
index faad03d..66cba12 100644
--- a/adb/adb_utils.h
+++ b/adb/adb_utils.h
@@ -16,6 +16,7 @@
 
 #pragma once
 
+#include <charconv>
 #include <condition_variable>
 #include <mutex>
 #include <string>
@@ -112,33 +113,17 @@
 // Base-10 stroll on a string_view.
 template <typename T>
 inline bool ParseUint(T* result, std::string_view str, std::string_view* remaining = nullptr) {
-    if (str.empty() || !isdigit(str[0])) {
+    T value;
+    const auto res = std::from_chars(str.begin(), str.end(), value);
+    if (res.ec != std::errc{}) {
         return false;
     }
-
-    T value = 0;
-    std::string_view::iterator it;
-    constexpr T max = std::numeric_limits<T>::max();
-    for (it = str.begin(); it != str.end() && isdigit(*it); ++it) {
-        if (value > max / 10) {
-            return false;
-        }
-
-        value *= 10;
-
-        T digit = *it - '0';
-        if (value > max - digit) {
-            return false;
-        }
-
-        value += digit;
+    if (res.ptr != str.end() && !remaining) {
+        return false;
+    }
+    if (remaining) {
+        *remaining = std::string_view(res.ptr, str.end() - res.ptr);
     }
     *result = value;
-    if (remaining) {
-        *remaining = str.substr(it - str.begin());
-    } else {
-      return it == str.end();
-    }
-
     return true;
 }
diff --git a/adb/client/commandline.cpp b/adb/client/commandline.cpp
index 599e0e6..fe2bdfe 100644
--- a/adb/client/commandline.cpp
+++ b/adb/client/commandline.cpp
@@ -1704,10 +1704,23 @@
             error_exit("tcpip: invalid port: %s", argv[1]);
         }
         return adb_connect_command(android::base::StringPrintf("tcpip:%d", port));
+    } else if (!strcmp(argv[0], "remount")) {
+        FeatureSet features;
+        std::string error;
+        if (!adb_get_feature_set(&features, &error)) {
+            fprintf(stderr, "error: %s\n", error.c_str());
+            return 1;
+        }
+
+        if (CanUseFeature(features, kFeatureRemountShell)) {
+            const char* arg[2] = {"shell", "remount"};
+            return adb_shell(2, arg);
+        } else {
+            return adb_connect_command("remount:");
+        }
     }
     // clang-format off
-    else if (!strcmp(argv[0], "remount") ||
-             !strcmp(argv[0], "reboot") ||
+    else if (!strcmp(argv[0], "reboot") ||
              !strcmp(argv[0], "reboot-bootloader") ||
              !strcmp(argv[0], "reboot-fastboot") ||
              !strcmp(argv[0], "usb") ||
diff --git a/adb/daemon/remount_service.cpp b/adb/daemon/remount_service.cpp
index ce494ee..6bd7855 100644
--- a/adb/daemon/remount_service.cpp
+++ b/adb/daemon/remount_service.cpp
@@ -48,6 +48,8 @@
         dup2(fd, STDERR_FILENO);
 
         execl(kRemountCmd, kRemountCmd, cmd.empty() ? nullptr : cmd.c_str(), nullptr);
+        const char* msg = "failed to exec remount\n";
+        write(STDERR_FILENO, msg, strlen(msg));
         _exit(errno);
     }
 
@@ -83,6 +85,6 @@
 }
 
 void remount_service(unique_fd fd, const std::string& cmd) {
-    const char* success = do_remount(fd.get(), cmd) ? "succeeded" : "failed";
-    WriteFdFmt(fd.get(), "remount %s\n", success);
+    do_remount(fd.get(), cmd);
+    // The remount command will print success or failure for us.
 }
diff --git a/adb/sysdeps.h b/adb/sysdeps.h
index b0e7fa0..b08a13b 100644
--- a/adb/sysdeps.h
+++ b/adb/sysdeps.h
@@ -91,11 +91,14 @@
 extern int adb_open(const char* path, int options);
 extern int adb_creat(const char* path, int mode);
 extern int adb_read(borrowed_fd fd, void* buf, int len);
+extern int adb_pread(borrowed_fd fd, void* buf, int len, off64_t offset);
 extern int adb_write(borrowed_fd fd, const void* buf, int len);
+extern int adb_pwrite(borrowed_fd fd, const void* buf, int len, off64_t offset);
 extern int64_t adb_lseek(borrowed_fd fd, int64_t pos, int where);
 extern int adb_shutdown(borrowed_fd fd, int direction = SHUT_RDWR);
 extern int adb_close(int fd);
 extern int adb_register_socket(SOCKET s);
+extern HANDLE adb_get_os_handle(borrowed_fd fd);
 
 // See the comments for the !defined(_WIN32) version of unix_close().
 static __inline__ int unix_close(int fd) {
@@ -115,6 +118,9 @@
 #undef   read
 #define  read  ___xxx_read
 
+#undef pread
+#define pread ___xxx_pread
+
 // See the comments for the !defined(_WIN32) version of unix_write().
 static __inline__ int unix_write(borrowed_fd fd, const void* buf, size_t len) {
     return write(fd.get(), buf, len);
@@ -122,6 +128,9 @@
 #undef   write
 #define  write  ___xxx_write
 
+#undef pwrite
+#define pwrite ___xxx_pwrite
+
 // See the comments for the !defined(_WIN32) version of unix_lseek().
 static __inline__ int unix_lseek(borrowed_fd fd, int pos, int where) {
     return lseek(fd.get(), pos, where);
@@ -415,6 +424,14 @@
     return TEMP_FAILURE_RETRY(read(fd.get(), buf, len));
 }
 
+static __inline__ int adb_pread(int fd, void* buf, size_t len, off64_t offset) {
+#if defined(__APPLE__)
+    return TEMP_FAILURE_RETRY(pread(fd, buf, len, offset));
+#else
+    return TEMP_FAILURE_RETRY(pread64(fd, buf, len, offset));
+#endif
+}
+
 // Like unix_read(), but does not handle EINTR.
 static __inline__ int unix_read_interruptible(borrowed_fd fd, void* buf, size_t len) {
     return read(fd.get(), buf, len);
@@ -422,12 +439,25 @@
 
 #undef read
 #define read ___xxx_read
+#undef pread
+#define pread ___xxx_pread
 
 static __inline__ int adb_write(borrowed_fd fd, const void* buf, size_t len) {
     return TEMP_FAILURE_RETRY(write(fd.get(), buf, len));
 }
+
+static __inline__ int adb_pwrite(int fd, const void* buf, size_t len, off64_t offset) {
+#if defined(__APPLE__)
+    return TEMP_FAILURE_RETRY(pwrite(fd, buf, len, offset));
+#else
+    return TEMP_FAILURE_RETRY(pwrite64(fd, buf, len, offset));
+#endif
+}
+
 #undef   write
 #define  write  ___xxx_write
+#undef pwrite
+#define pwrite ___xxx_pwrite
 
 static __inline__ int64_t adb_lseek(borrowed_fd fd, int64_t pos, int where) {
 #if defined(__APPLE__)
diff --git a/adb/sysdeps_win32.cpp b/adb/sysdeps_win32.cpp
index dc2525c..4d6cf3d 100644
--- a/adb/sysdeps_win32.cpp
+++ b/adb/sysdeps_win32.cpp
@@ -60,6 +60,7 @@
     int (*_fh_read)(FH, void*, int);
     int (*_fh_write)(FH, const void*, int);
     int (*_fh_writev)(FH, const adb_iovec*, int);
+    intptr_t (*_fh_get_os_handle)(FH);
 } FHClassRec;
 
 static void _fh_file_init(FH);
@@ -68,14 +69,11 @@
 static int _fh_file_read(FH, void*, int);
 static int _fh_file_write(FH, const void*, int);
 static int _fh_file_writev(FH, const adb_iovec*, int);
+static intptr_t _fh_file_get_os_handle(FH f);
 
 static const FHClassRec _fh_file_class = {
-    _fh_file_init,
-    _fh_file_close,
-    _fh_file_lseek,
-    _fh_file_read,
-    _fh_file_write,
-    _fh_file_writev,
+        _fh_file_init,  _fh_file_close,  _fh_file_lseek,         _fh_file_read,
+        _fh_file_write, _fh_file_writev, _fh_file_get_os_handle,
 };
 
 static void _fh_socket_init(FH);
@@ -84,14 +82,11 @@
 static int _fh_socket_read(FH, void*, int);
 static int _fh_socket_write(FH, const void*, int);
 static int _fh_socket_writev(FH, const adb_iovec*, int);
+static intptr_t _fh_socket_get_os_handle(FH f);
 
 static const FHClassRec _fh_socket_class = {
-    _fh_socket_init,
-    _fh_socket_close,
-    _fh_socket_lseek,
-    _fh_socket_read,
-    _fh_socket_write,
-    _fh_socket_writev,
+        _fh_socket_init,  _fh_socket_close,  _fh_socket_lseek,         _fh_socket_read,
+        _fh_socket_write, _fh_socket_writev, _fh_socket_get_os_handle,
 };
 
 #if defined(assert)
@@ -331,6 +326,10 @@
     return li.QuadPart;
 }
 
+static intptr_t _fh_file_get_os_handle(FH f) {
+    return reinterpret_cast<intptr_t>(f->u.handle);
+}
+
 /**************************************************************************/
 /**************************************************************************/
 /*****                                                                *****/
@@ -456,6 +455,26 @@
     return f->clazz->_fh_read(f, buf, len);
 }
 
+int adb_pread(borrowed_fd fd, void* buf, int len, off64_t offset) {
+    OVERLAPPED overlapped = {};
+    overlapped.Offset = static_cast<DWORD>(offset);
+    overlapped.OffsetHigh = static_cast<DWORD>(offset >> 32);
+    DWORD bytes_read;
+    if (!::ReadFile(adb_get_os_handle(fd), buf, static_cast<DWORD>(len), &bytes_read,
+                    &overlapped)) {
+        D("adb_pread: could not read %d bytes from FD %d", len, fd.get());
+        switch (::GetLastError()) {
+            case ERROR_IO_PENDING:
+                errno = EAGAIN;
+                return -1;
+            default:
+                errno = EINVAL;
+                return -1;
+        }
+    }
+    return static_cast<int>(bytes_read);
+}
+
 int adb_write(borrowed_fd fd, const void* buf, int len) {
     FH f = _fh_from_int(fd, __func__);
 
@@ -478,6 +497,25 @@
     return f->clazz->_fh_writev(f, iov, iovcnt);
 }
 
+int adb_pwrite(borrowed_fd fd, const void* buf, int len, off64_t offset) {
+    OVERLAPPED params = {};
+    params.Offset = static_cast<DWORD>(offset);
+    params.OffsetHigh = static_cast<DWORD>(offset >> 32);
+    DWORD bytes_written = 0;
+    if (!::WriteFile(adb_get_os_handle(fd), buf, len, &bytes_written, &params)) {
+        D("adb_pwrite: could not write %d bytes to FD %d", len, fd.get());
+        switch (::GetLastError()) {
+            case ERROR_IO_PENDING:
+                errno = EAGAIN;
+                return -1;
+            default:
+                errno = EINVAL;
+                return -1;
+        }
+    }
+    return static_cast<int>(bytes_written);
+}
+
 int64_t adb_lseek(borrowed_fd fd, int64_t pos, int where) {
     FH f = _fh_from_int(fd, __func__);
     if (!f) {
@@ -500,6 +538,20 @@
     return 0;
 }
 
+HANDLE adb_get_os_handle(borrowed_fd fd) {
+    FH f = _fh_from_int(fd, __func__);
+
+    if (!f) {
+        errno = EBADF;
+        return nullptr;
+    }
+
+    D("adb_get_os_handle: %s", f->name);
+    const intptr_t intptr_handle = f->clazz->_fh_get_os_handle(f);
+    const HANDLE handle = reinterpret_cast<const HANDLE>(intptr_handle);
+    return handle;
+}
+
 /**************************************************************************/
 /**************************************************************************/
 /*****                                                                *****/
@@ -694,6 +746,10 @@
     return static_cast<int>(bytes_written);
 }
 
+static intptr_t _fh_socket_get_os_handle(FH f) {
+    return f->u.socket;
+}
+
 /**************************************************************************/
 /**************************************************************************/
 /*****                                                                *****/
diff --git a/adb/transport.cpp b/adb/transport.cpp
index 3d1d620..d9749ac 100644
--- a/adb/transport.cpp
+++ b/adb/transport.cpp
@@ -73,6 +73,7 @@
 const char* const kFeatureAbb = "abb";
 const char* const kFeatureFixedPushSymlinkTimestamp = "fixed_push_symlink_timestamp";
 const char* const kFeatureAbbExec = "abb_exec";
+const char* const kFeatureRemountShell = "remount_shell";
 
 namespace {
 
@@ -1049,6 +1050,7 @@
             kFeatureAbb,
             kFeatureFixedPushSymlinkTimestamp,
             kFeatureAbbExec,
+            kFeatureRemountShell,
             // Increment ADB_SERVER_VERSION when adding a feature that adbd needs
             // to know about. Otherwise, the client can be stuck running an old
             // version of the server even after upgrading their copy of adb.
diff --git a/adb/transport.h b/adb/transport.h
index f4490ed..245037e 100644
--- a/adb/transport.h
+++ b/adb/transport.h
@@ -69,6 +69,7 @@
 extern const char* const kFeatureAbb;
 // adbd properly updates symlink timestamps on push.
 extern const char* const kFeatureFixedPushSymlinkTimestamp;
+extern const char* const kFeatureRemountShell;
 
 TransportId NextTransportId();
 
diff --git a/base/include/android-base/endian.h b/base/include/android-base/endian.h
index 10efaa3..2d0f614 100644
--- a/base/include/android-base/endian.h
+++ b/base/include/android-base/endian.h
@@ -18,6 +18,9 @@
 
 /* A cross-platform equivalent of bionic's <sys/endian.h>. */
 
+/* For __BIONIC__ and __GLIBC__ */
+#include <sys/cdefs.h>
+
 #if defined(__BIONIC__)
 
 #include <sys/endian.h>
@@ -38,6 +41,9 @@
 #define betoh16(x) be16toh(x)
 #define betoh32(x) be32toh(x)
 #define betoh64(x) be64toh(x)
+#define letoh16(x) le16toh(x)
+#define letoh32(x) le32toh(x)
+#define letoh64(x) le64toh(x)
 
 #else
 
@@ -45,10 +51,8 @@
 /* macOS has some of the basics. */
 #include <sys/_endian.h>
 #else
-/* Windows really has nothing. */
-#define LITTLE_ENDIAN __LITTLE_ENDIAN
-#define BIG_ENDIAN __BIG_ENDIAN
-#define BYTE_ORDER __BYTE_ORDER
+/* Windows has even less. */
+#include <sys/param.h>
 #define htons(x) __builtin_bswap16(x)
 #define htonl(x) __builtin_bswap32(x)
 #define ntohs(x) __builtin_bswap16(x)
diff --git a/base/include/android-base/mapped_file.h b/base/include/android-base/mapped_file.h
index 2ab49ab..6a19f1b 100644
--- a/base/include/android-base/mapped_file.h
+++ b/base/include/android-base/mapped_file.h
@@ -28,15 +28,17 @@
 #include <windows.h>
 #define PROT_READ 1
 #define PROT_WRITE 2
+using os_handle = HANDLE;
 #else
 #include <sys/mman.h>
+using os_handle = int;
 #endif
 
 namespace android {
 namespace base {
 
 /**
- * A region of a file mapped into memory, also known as MmapFile.
+ * A region of a file mapped into memory (for grepping: also known as MmapFile or file mapping).
  */
 class MappedFile {
  public:
@@ -49,16 +51,33 @@
                                             int prot);
 
   /**
+   * Same thing, but using the raw OS file handle instead of a CRT wrapper.
+   */
+  static MappedFile FromOsHandle(os_handle h, off64_t offset, size_t length, int prot);
+
+  /**
    * Removes the mapping.
    */
   ~MappedFile();
 
-  char* data() { return base_ + offset_; }
-  size_t size() { return size_; }
+  /**
+   * Not copyable but movable.
+   */
+  MappedFile(MappedFile&& other);
+  MappedFile& operator=(MappedFile&& other);
+
+  char* data() const { return base_ + offset_; }
+  size_t size() const { return size_; }
+
+  bool isValid() const { return base_ != nullptr; }
+
+  explicit operator bool() const { return isValid(); }
 
  private:
   DISALLOW_IMPLICIT_CONSTRUCTORS(MappedFile);
 
+  void Close();
+
   char* base_;
   size_t size_;
 
diff --git a/base/mapped_file.cpp b/base/mapped_file.cpp
index f60de56..862b73b 100644
--- a/base/mapped_file.cpp
+++ b/base/mapped_file.cpp
@@ -16,13 +16,15 @@
 
 #include "android-base/mapped_file.h"
 
-#include <errno.h>
+#include <utility>
 
-#include "android-base/unique_fd.h"
+#include <errno.h>
 
 namespace android {
 namespace base {
 
+static constexpr char kEmptyBuffer[] = {'0'};
+
 static off64_t InitPageSize() {
 #if defined(_WIN32)
   SYSTEM_INFO si;
@@ -35,51 +37,86 @@
 
 std::unique_ptr<MappedFile> MappedFile::FromFd(borrowed_fd fd, off64_t offset, size_t length,
                                                int prot) {
-  static off64_t page_size = InitPageSize();
+#if defined(_WIN32)
+  auto file =
+      FromOsHandle(reinterpret_cast<HANDLE>(_get_osfhandle(fd.get())), offset, length, prot);
+#else
+  auto file = FromOsHandle(fd.get(), offset, length, prot);
+#endif
+  return file ? std::make_unique<MappedFile>(std::move(file)) : std::unique_ptr<MappedFile>{};
+}
+
+MappedFile MappedFile::FromOsHandle(os_handle h, off64_t offset, size_t length, int prot) {
+  static const off64_t page_size = InitPageSize();
   size_t slop = offset % page_size;
   off64_t file_offset = offset - slop;
   off64_t file_length = length + slop;
 
 #if defined(_WIN32)
-  HANDLE handle =
-      CreateFileMapping(reinterpret_cast<HANDLE>(_get_osfhandle(fd.get())), nullptr,
-                        (prot & PROT_WRITE) ? PAGE_READWRITE : PAGE_READONLY, 0, 0, nullptr);
+  HANDLE handle = CreateFileMappingW(
+      h, nullptr, (prot & PROT_WRITE) ? PAGE_READWRITE : PAGE_READONLY, 0, 0, nullptr);
   if (handle == nullptr) {
     // http://b/119818070 "app crashes when reading asset of zero length".
     // Return a MappedFile that's only valid for reading the size.
-    if (length == 0) {
-      return std::unique_ptr<MappedFile>(new MappedFile{nullptr, 0, 0, nullptr});
+    if (length == 0 && ::GetLastError() == ERROR_FILE_INVALID) {
+      return MappedFile{const_cast<char*>(kEmptyBuffer), 0, 0, nullptr};
     }
-    return nullptr;
+    return MappedFile(nullptr, 0, 0, nullptr);
   }
   void* base = MapViewOfFile(handle, (prot & PROT_WRITE) ? FILE_MAP_ALL_ACCESS : FILE_MAP_READ, 0,
                              file_offset, file_length);
   if (base == nullptr) {
     CloseHandle(handle);
-    return nullptr;
+    return MappedFile(nullptr, 0, 0, nullptr);
   }
-  return std::unique_ptr<MappedFile>(
-      new MappedFile{static_cast<char*>(base), length, slop, handle});
+  return MappedFile{static_cast<char*>(base), length, slop, handle};
 #else
-  void* base = mmap(nullptr, file_length, prot, MAP_SHARED, fd.get(), file_offset);
+  void* base = mmap(nullptr, file_length, prot, MAP_SHARED, h, file_offset);
   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 MappedFile{const_cast<char*>(kEmptyBuffer), 0, 0};
     }
-    return nullptr;
+    return MappedFile(nullptr, 0, 0);
   }
-  return std::unique_ptr<MappedFile>(new MappedFile{static_cast<char*>(base), length, slop});
+  return MappedFile{static_cast<char*>(base), length, slop};
 #endif
 }
 
+MappedFile::MappedFile(MappedFile&& other)
+    : base_(std::exchange(other.base_, nullptr)),
+      size_(std::exchange(other.size_, 0)),
+      offset_(std::exchange(other.offset_, 0))
+#ifdef _WIN32
+      ,
+      handle_(std::exchange(other.handle_, nullptr))
+#endif
+{
+}
+
+MappedFile& MappedFile::operator=(MappedFile&& other) {
+  Close();
+  base_ = std::exchange(other.base_, nullptr);
+  size_ = std::exchange(other.size_, 0);
+  offset_ = std::exchange(other.offset_, 0);
+#ifdef _WIN32
+  handle_ = std::exchange(other.handle_, nullptr);
+#endif
+  return *this;
+}
+
 MappedFile::~MappedFile() {
+  Close();
+}
+
+void MappedFile::Close() {
 #if defined(_WIN32)
-  if (base_ != nullptr) UnmapViewOfFile(base_);
+  if (base_ != nullptr && size_ != 0) UnmapViewOfFile(base_);
   if (handle_ != nullptr) CloseHandle(handle_);
+  handle_ = nullptr;
 #else
-  if (base_ != nullptr) munmap(base_, size_ + offset_);
+  if (base_ != nullptr && size_ != 0) munmap(base_, size_ + offset_);
 #endif
 
   base_ = nullptr;
diff --git a/base/mapped_file_test.cpp b/base/mapped_file_test.cpp
index cfde73c..3629108 100644
--- a/base/mapped_file_test.cpp
+++ b/base/mapped_file_test.cpp
@@ -44,5 +44,8 @@
   ASSERT_TRUE(tf.fd != -1);
 
   auto m = android::base::MappedFile::FromFd(tf.fd, 4096, 0, PROT_READ);
-  ASSERT_EQ(0u, m->size());
+  ASSERT_NE(nullptr, m);
+  EXPECT_TRUE((bool)*m);
+  EXPECT_EQ(0u, m->size());
+  EXPECT_NE(nullptr, m->data());
 }
diff --git a/fs_mgr/fs_mgr_remount.cpp b/fs_mgr/fs_mgr_remount.cpp
index 149bee3..93bba68 100644
--- a/fs_mgr/fs_mgr_remount.cpp
+++ b/fs_mgr/fs_mgr_remount.cpp
@@ -82,13 +82,7 @@
 
 void MyLogger(android::base::LogId id, android::base::LogSeverity severity, const char* tag,
               const char* file, unsigned int line, const char* message) {
-    static const char log_characters[] = "VD\0WEFF";
-    if (severity < sizeof(log_characters)) {
-        auto severity_char = log_characters[severity];
-        if (severity_char) fprintf(stderr, "%c ", severity_char);
-    }
     fprintf(stderr, "%s\n", message);
-
     static auto logd = android::base::LogdLogger();
     logd(id, severity, tag, file, line, message);
 }
@@ -107,11 +101,9 @@
 
 }  // namespace
 
-int main(int argc, char* argv[]) {
-    android::base::InitLogging(argv, MyLogger);
-
+static int do_remount(int argc, char* argv[]) {
     enum {
-        SUCCESS,
+        SUCCESS = 0,
         NOT_USERDEBUG,
         BADARG,
         NOT_ROOT,
@@ -165,7 +157,7 @@
 
     // Make sure we are root.
     if (::getuid() != 0) {
-        LOG(ERROR) << "must be run as root";
+        LOG(ERROR) << "Not running as root. Try \"adb root\" first.";
         return NOT_ROOT;
     }
 
@@ -390,3 +382,10 @@
 
     return retval;
 }
+
+int main(int argc, char* argv[]) {
+    android::base::InitLogging(argv, MyLogger);
+    int result = do_remount(argc, argv);
+    printf("remount %s\n", result ? "failed" : "succeeded");
+    return result;
+}
diff --git a/fs_mgr/liblp/builder.cpp b/fs_mgr/liblp/builder.cpp
index 777743c..6dc288e 100644
--- a/fs_mgr/liblp/builder.cpp
+++ b/fs_mgr/liblp/builder.cpp
@@ -140,7 +140,7 @@
     }
     if (opener) {
         for (size_t i = 0; i < builder->block_devices_.size(); i++) {
-            std::string partition_name = GetBlockDevicePartitionName(builder->block_devices_[i]);
+            std::string partition_name = builder->GetBlockDevicePartitionName(i);
             BlockDeviceInfo device_info;
             if (opener->GetInfo(partition_name, &device_info)) {
                 builder->UpdateBlockDeviceInfo(i, device_info);
@@ -164,7 +164,7 @@
     // name and system properties.
     // See comments for UpdateMetadataForOtherSuper.
     auto super_device = GetMetadataSuperBlockDevice(*metadata.get());
-    if (GetBlockDevicePartitionName(*super_device) != "super" &&
+    if (android::fs_mgr::GetBlockDevicePartitionName(*super_device) != "super" &&
         IsRetrofitDynamicPartitionsDevice()) {
         if (!UpdateMetadataForOtherSuper(metadata.get(), source_slot_number, target_slot_number)) {
             return nullptr;
@@ -192,7 +192,8 @@
     // Translate block devices.
     auto source_block_devices = std::move(metadata->block_devices);
     for (const auto& source_block_device : source_block_devices) {
-        std::string partition_name = GetBlockDevicePartitionName(source_block_device);
+        std::string partition_name =
+                android::fs_mgr::GetBlockDevicePartitionName(source_block_device);
         std::string slot_suffix = GetPartitionSlotSuffix(partition_name);
         if (slot_suffix.empty() || slot_suffix != source_slot_suffix) {
             // This should never happen. It means that the source metadata
@@ -375,7 +376,7 @@
             block_devices_.emplace_back(out);
         }
     }
-    if (GetBlockDevicePartitionName(block_devices_[0]) != super_partition) {
+    if (GetBlockDevicePartitionName(0) != super_partition) {
         LERROR << "No super partition was specified.";
         return false;
     }
@@ -458,7 +459,7 @@
     return nullptr;
 }
 
-PartitionGroup* MetadataBuilder::FindGroup(const std::string& group_name) {
+PartitionGroup* MetadataBuilder::FindGroup(std::string_view group_name) {
     for (const auto& group : groups_) {
         if (group->name() == group_name) {
             return group.get();
@@ -582,8 +583,7 @@
     CHECK_NE(sectors_per_block, 0);
     CHECK(sectors_needed % sectors_per_block == 0);
 
-    if (IsABDevice() && !IsRetrofitMetadata() &&
-        GetPartitionSlotSuffix(partition->name()) == "_b") {
+    if (IsABDevice() && ShouldHalveSuper() && GetPartitionSlotSuffix(partition->name()) == "_b") {
         // Allocate "a" partitions top-down and "b" partitions bottom-up, to
         // minimize fragmentation during OTA.
         free_regions = PrioritizeSecondHalfOfSuper(free_regions);
@@ -849,7 +849,7 @@
 bool MetadataBuilder::FindBlockDeviceByName(const std::string& partition_name,
                                             uint32_t* index) const {
     for (size_t i = 0; i < block_devices_.size(); i++) {
-        if (GetBlockDevicePartitionName(block_devices_[i]) == partition_name) {
+        if (GetBlockDevicePartitionName(i) == partition_name) {
             *index = i;
             return true;
         }
@@ -974,7 +974,8 @@
     // Note: we don't compare alignment, since it's a performance thing and
     // won't affect whether old extents continue to work.
     return first.first_logical_sector == second.first_logical_sector && first.size == second.size &&
-           GetBlockDevicePartitionName(first) == GetBlockDevicePartitionName(second);
+           android::fs_mgr::GetBlockDevicePartitionName(first) ==
+                   android::fs_mgr::GetBlockDevicePartitionName(second);
 }
 
 bool MetadataBuilder::ImportPartitions(const LpMetadata& metadata,
@@ -1056,8 +1057,9 @@
                                                             false);
 }
 
-bool MetadataBuilder::IsRetrofitMetadata() const {
-    return GetBlockDevicePartitionName(block_devices_[0]) != LP_METADATA_DEFAULT_PARTITION_NAME;
+bool MetadataBuilder::ShouldHalveSuper() const {
+    return GetBlockDevicePartitionName(0) == LP_METADATA_DEFAULT_PARTITION_NAME &&
+           !IPropertyFetcher::GetInstance()->GetBoolProperty("ro.virtual_ab.enabled", false);
 }
 
 bool MetadataBuilder::AddLinearExtent(Partition* partition, const std::string& block_device,
@@ -1083,7 +1085,7 @@
     return partitions;
 }
 
-bool MetadataBuilder::ChangePartitionGroup(Partition* partition, const std::string& group_name) {
+bool MetadataBuilder::ChangePartitionGroup(Partition* partition, std::string_view group_name) {
     if (!FindGroup(group_name)) {
         LERROR << "Partition cannot change to unknown group: " << group_name;
         return false;
@@ -1121,5 +1123,11 @@
     return true;
 }
 
+std::string MetadataBuilder::GetBlockDevicePartitionName(uint64_t index) const {
+    return index < block_devices_.size()
+                   ? android::fs_mgr::GetBlockDevicePartitionName(block_devices_[index])
+                   : "";
+}
+
 }  // namespace fs_mgr
 }  // namespace android
diff --git a/fs_mgr/liblp/builder_test.cpp b/fs_mgr/liblp/builder_test.cpp
index 6d27873..b3c13e6 100644
--- a/fs_mgr/liblp/builder_test.cpp
+++ b/fs_mgr/liblp/builder_test.cpp
@@ -35,7 +35,7 @@
     IPropertyFetcher::OverrideForTesting(std::make_unique<NiceMock<MockPropertyFetcher>>());
 }
 
-MockPropertyFetcher* GetMockedInstance() {
+MockPropertyFetcher* GetMockedPropertyFetcher() {
     return static_cast<MockPropertyFetcher*>(IPropertyFetcher::GetInstance());
 }
 
@@ -789,7 +789,7 @@
 
     // A and B slots should be allocated from separate halves of the partition,
     // to mitigate allocating too many extents. (b/120433288)
-    ON_CALL(*GetMockedInstance(), GetProperty("ro.boot.slot_suffix", _))
+    ON_CALL(*GetMockedPropertyFetcher(), GetProperty("ro.boot.slot_suffix", _))
             .WillByDefault(Return("_a"));
 
     auto builder = MetadataBuilder::New(device_info, 65536, 2);
diff --git a/fs_mgr/liblp/include/liblp/builder.h b/fs_mgr/liblp/include/liblp/builder.h
index 3b229bd..c3f6e91 100644
--- a/fs_mgr/liblp/include/liblp/builder.h
+++ b/fs_mgr/liblp/include/liblp/builder.h
@@ -128,7 +128,7 @@
 
   private:
     void ShrinkTo(uint64_t aligned_size);
-    void set_group_name(const std::string& group_name) { group_name_ = group_name; }
+    void set_group_name(std::string_view group_name) { group_name_ = group_name; }
 
     std::string name_;
     std::string group_name_;
@@ -227,7 +227,7 @@
     Partition* FindPartition(const std::string& name);
 
     // Find a group by name. If no group is found, nullptr is returned.
-    PartitionGroup* FindGroup(const std::string& name);
+    PartitionGroup* FindGroup(std::string_view name);
 
     // Add a predetermined extent to a partition.
     bool AddLinearExtent(Partition* partition, const std::string& block_device,
@@ -252,7 +252,7 @@
     // the metadata is exported, to avoid errors during potential group and
     // size shuffling operations. This will return false if the new group does
     // not exist.
-    bool ChangePartitionGroup(Partition* partition, const std::string& group_name);
+    bool ChangePartitionGroup(Partition* partition, std::string_view group_name);
 
     // Changes the size of a partition group. Size constraints will not be
     // checked until metadata is exported, to avoid errors during group
@@ -287,6 +287,9 @@
     // Return true if a block device is found, else false.
     bool HasBlockDevice(const std::string& partition_name) const;
 
+    // Return the name of the block device at |index|.
+    std::string GetBlockDevicePartitionName(uint64_t index) const;
+
   private:
     MetadataBuilder();
     MetadataBuilder(const MetadataBuilder&) = delete;
@@ -314,8 +317,8 @@
     // Return true if the device is retrofitting dynamic partitions.
     static bool IsRetrofitDynamicPartitionsDevice();
 
-    // Return true if "this" metadata represents a metadata on a retrofit device.
-    bool IsRetrofitMetadata() const;
+    // Return true if _b partitions should be prioritized at the second half of the device.
+    bool ShouldHalveSuper() const;
 
     bool ValidatePartitionGroups() const;
 
diff --git a/fs_mgr/liblp/io_test.cpp b/fs_mgr/liblp/io_test.cpp
index 2990863..3dace25 100644
--- a/fs_mgr/liblp/io_test.cpp
+++ b/fs_mgr/liblp/io_test.cpp
@@ -668,7 +668,7 @@
 }
 
 TEST(liblp, UpdateRetrofit) {
-    ON_CALL(*GetMockedInstance(), GetBoolProperty("ro.boot.dynamic_partitions_retrofit", _))
+    ON_CALL(*GetMockedPropertyFetcher(), GetBoolProperty("ro.boot.dynamic_partitions_retrofit", _))
             .WillByDefault(Return(true));
 
     unique_ptr<MetadataBuilder> builder = CreateDefaultBuilder();
@@ -700,7 +700,7 @@
 }
 
 TEST(liblp, UpdateNonRetrofit) {
-    ON_CALL(*GetMockedInstance(), GetBoolProperty("ro.boot.dynamic_partitions_retrofit", _))
+    ON_CALL(*GetMockedPropertyFetcher(), GetBoolProperty("ro.boot.dynamic_partitions_retrofit", _))
             .WillByDefault(Return(false));
 
     unique_fd fd = CreateFlashedDisk();
diff --git a/fs_mgr/liblp/mock_property_fetcher.h b/fs_mgr/liblp/mock_property_fetcher.h
index eb91de2..0c28710 100644
--- a/fs_mgr/liblp/mock_property_fetcher.h
+++ b/fs_mgr/liblp/mock_property_fetcher.h
@@ -44,4 +44,4 @@
 }  // namespace fs_mgr
 }  // namespace android
 
-android::fs_mgr::MockPropertyFetcher* GetMockedInstance();
+android::fs_mgr::MockPropertyFetcher* GetMockedPropertyFetcher();
diff --git a/fs_mgr/libsnapshot/Android.bp b/fs_mgr/libsnapshot/Android.bp
index 746987e..128a4f9 100644
--- a/fs_mgr/libsnapshot/Android.bp
+++ b/fs_mgr/libsnapshot/Android.bp
@@ -32,9 +32,14 @@
     whole_static_libs: [
         "libext2_uuid",
         "libext4_utils",
-        "libfiemap",
         "libfstab",
     ],
+    header_libs: [
+        "libfiemap_headers",
+    ],
+    export_header_lib_headers: [
+        "libfiemap_headers",
+    ],
     export_include_dirs: ["include"],
 }
 
@@ -49,7 +54,7 @@
     name: "libsnapshot",
     defaults: ["libsnapshot_defaults"],
     srcs: [":libsnapshot_sources"],
-    static_libs: [
+    whole_static_libs: [
         "libfiemap_binder",
     ],
 }
@@ -59,6 +64,9 @@
     defaults: ["libsnapshot_defaults"],
     srcs: [":libsnapshot_sources"],
     recovery_available: true,
+    whole_static_libs: [
+        "libfiemap_passthrough",
+    ],
 }
 
 cc_test {
diff --git a/fs_mgr/libsnapshot/snapshot.cpp b/fs_mgr/libsnapshot/snapshot.cpp
index 88800ed..fef5c06 100644
--- a/fs_mgr/libsnapshot/snapshot.cpp
+++ b/fs_mgr/libsnapshot/snapshot.cpp
@@ -313,7 +313,8 @@
     // There may be an extra device, since the kernel doesn't let us have a
     // snapshot and linear target in the same table.
     auto dm_name = GetSnapshotDeviceName(name, status);
-    if (name != dm_name && !dm.DeleteDevice(dm_name)) {
+    if (name != dm_name && dm.GetState(dm_name) != DmDeviceState::INVALID &&
+        !dm.DeleteDevice(dm_name)) {
         LOG(ERROR) << "Could not delete inner snapshot device: " << dm_name;
         return false;
     }
diff --git a/fs_mgr/tests/adb-remount-test.sh b/fs_mgr/tests/adb-remount-test.sh
index 642f2c1..397d8e5 100755
--- a/fs_mgr/tests/adb-remount-test.sh
+++ b/fs_mgr/tests/adb-remount-test.sh
@@ -890,14 +890,37 @@
 # If reboot too soon after fresh flash, could trip device update failure logic
 wait_for_screen
 # Can we test remount -R command?
+OVERLAYFS_BACKING="cache mnt/scratch"
 overlayfs_supported=true
-if [ "orange" = "`get_property ro.boot.verifiedbootstate`" -a \
-     "2" = "`get_property partition.system.verified`" ]; then
+if [ "orange" != "`get_property ro.boot.verifiedbootstate`" -o \
+     "2" != "`get_property partition.system.verified`" ]; then
   restore() {
     ${overlayfs_supported} || return 0
     inFastboot &&
       fastboot reboot &&
-      adb_wait ${ADB_WAIT}
+      adb_wait ${ADB_WAIT} ||
+      true
+    if inAdb; then
+      reboot=false
+      for d in ${OVERLAYFS_BACKING}; do
+        if adb_su ls -d /${d}/overlay </dev/null >/dev/null 2>/dev/null; then
+          adb_su rm -rf /${d}/overlay </dev/null
+          reboot=true
+        fi
+      done
+      if ${reboot}; then
+        adb_reboot &&
+        adb_wait ${ADB_WAIT}
+      fi
+    fi
+  }
+else
+  restore() {
+    ${overlayfs_supported} || return 0
+    inFastboot &&
+      fastboot reboot &&
+      adb_wait ${ADB_WAIT} ||
+      true
     inAdb &&
       adb_root &&
       adb enable-verity >/dev/null 2>/dev/null &&
@@ -956,7 +979,6 @@
 # So lets do our best to surgically wipe the overlayfs state without
 # having to go through enable-verity transition.
 reboot=false
-OVERLAYFS_BACKING="cache mnt/scratch"
 for d in ${OVERLAYFS_BACKING}; do
   if adb_sh ls -d /${d}/overlay </dev/null >/dev/null 2>/dev/null; then
     echo "${ORANGE}[  WARNING ]${NORMAL} /${d}/overlay is setup, surgically wiping" >&2
@@ -1468,7 +1490,7 @@
   }
   dd if=/dev/zero of=${img} bs=4096 count=16 2>/dev/null &&
     fastboot_wait ${FASTBOOT_WAIT} ||
-    die "reboot into fastboot `usb_status`"
+    die "reboot into fastboot to flash scratch `usb_status`"
   fastboot flash --force ${scratch_partition} ${img}
   err=${?}
   cleanup
diff --git a/init/README.ueventd.md b/init/README.ueventd.md
new file mode 100644
index 0000000..c592c37
--- /dev/null
+++ b/init/README.ueventd.md
@@ -0,0 +1,112 @@
+# Ueventd
+-------
+Ueventd manages `/dev`, sets permissions for `/sys`, and handles firmware uevents. It has default
+behavior described below, along with a scripting language that allows customizing this behavior,
+built on the same parser as init.
+
+Ueventd has one generic customization parameter, the size of rcvbuf_size for the ueventd socket. It
+is customized by the `uevent_socket_rcvbuf_size` parameter, which takes the format of
+
+    uevent_socket_rcvbuf_size <size>
+For example
+
+    uevent_socket_rcvbuf_size 16M
+Sets the uevent socket rcvbuf_size to 16 megabytes.
+
+## /dev
+----
+Ueventd listens to the kernel uevent sockets and creates/deletes nodes in `/dev` based on the
+incoming add/remove uevents. It defaults to using `0600` mode and `root` user/group. It always
+creates the nodes with the SELabel from the current loaded SEPolicy. It has three default behaviors
+for the node path:
+
+  1. Block devices are created as `/dev/block/<basename uevent DEVPATH>`. There are symlinks created
+     to this node at `/dev/block/<type>/<parent device>/<basename uevent DEVPATH>`,
+     `/dev/block/<type>/<parent device>/by-name/<uevent PARTNAME>`, and `/dev/block/by-name/<uevent
+     PARTNAME>` if the device is a boot device.
+  2. USB devices are created as `/dev/<uevent DEVNAME>` if `DEVNAME` was specified for the uevent,
+     otherwise as `/dev/bus/usb/<bus_id>/<device_id>` where `bus_id` is `uevent MINOR / 128 + 1` and
+     `device_id` is `uevent MINOR % 128 + 1`.
+  3. All other devices are created as `/dev/<basename uevent DEVPATH>`
+
+The permissions can be modified using a ueventd.rc script and a line that beings with `/dev`. These
+lines take the format of
+
+    devname mode uid gid
+For example
+
+    /dev/null 0666 root root
+When `/dev/null` is created, its mode will be set to `0666`, its user to `root` and its group to
+`root`.
+
+The path can be modified using a ueventd.rc script and a `subsystem` section. There are three to set
+for a subsystem: the subsystem name, which device name to use, and which directory to place the
+device in. The section takes the below format of
+
+    subsystem <subsystem_name>
+      devname uevent_devname|uevent_devpath
+      [dirname <directory>]
+
+`subsystem_name` is used to match uevent `SUBSYSTEM` value
+
+`devname` takes one of two options
+  1. `uevent_devname` specifies that the name of the node will be the uevent `DEVNAME`
+  2. `uevent_devpath` specified that the name of the node will be basename uevent `DEVPATH`
+
+`dirname` is an optional parameter that specifies a directory within `/dev` where the node will be
+created.
+
+For example
+
+    subsystem sound
+      devname uevent_devpath
+      dirname /dev/snd
+Indicates that all uevents with `SUBSYSTEM=sound` will create nodes as `/dev/snd/<basename uevent
+DEVPATH>`.
+
+## /sys
+----
+Ueventd by default takes no action for `/sys`, however it can be instructed to set permissions for
+certain files in `/sys` when matching uevents are generated. This is done using a ueventd.rc script
+and a line that begins with `/sys`. These lines take the format of
+
+    nodename attr mode uid gid
+For example
+
+    /sys/devices/system/cpu/cpu* cpufreq/scaling_max_freq 0664 system system
+When a uevent that matches the pattern `/sys/devices/system/cpu/cpu*` is sent, the matching sysfs
+attribute, `cpufreq/scaling_max_freq`, will have its mode set to `0664`, its user to to `system` and
+its group set to `system`.
+
+Note that `*` matches as a wildcard and can be used anywhere in a path.
+
+## Firmware loading
+----------------
+Ueventd automatically serves firmware requests by searching through a list of firmware directories
+for a file matching the uevent `FIRMWARE`. It then forks a process to serve this firmware to the
+kernel.
+
+The list of firmware directories is customized by a `firmware_directories` line in a ueventd.rc
+file. This line takes the format of
+
+    firmware_directories <firmware_directory> [ <firmware_directory> ]*
+For example
+
+    firmware_directories /etc/firmware/ /odm/firmware/ /vendor/firmware/ /firmware/image/
+Adds those 4 directories, in that order to the list of firmware directories that will be tried by
+ueventd. Note that this option always accumulates to the list; it is not possible to remove previous
+entries.
+
+Ueventd will wait until after `post-fs` in init, to keep retrying before believing the firmwares are
+not present.
+
+## Coldboot
+--------
+Ueventd must create devices in `/dev` for all devices that have already sent their uevents before
+ueventd has started. To do so, when ueventd is started it does what it calls a 'coldboot' on `/sys`,
+in which it writes 'add' to every 'uevent' file that it finds in `/sys/class`, `/sys/block`, and
+`/sys/devices`. This causes the kernel to regenerate the uevents for these paths, and thus for
+ueventd to create the nodes.
+
+For boot time purposes, this is done in parallel across a set of child processes. `ueventd.cpp` in
+this directory contains documentation on how the parallelization is done.
diff --git a/init/first_stage_init.cpp b/init/first_stage_init.cpp
index b60c450..fd2d766 100644
--- a/init/first_stage_init.cpp
+++ b/init/first_stage_init.cpp
@@ -121,9 +121,9 @@
         _exit(127);
     }
     ioctl(fd, TIOCSCTTY, 0);
-    dup2(fd, 0);
-    dup2(fd, 1);
-    dup2(fd, 2);
+    dup2(fd, STDIN_FILENO);
+    dup2(fd, STDOUT_FILENO);
+    dup2(fd, STDERR_FILENO);
     close(fd);
 
     const char* path = "/system/bin/sh";
@@ -291,6 +291,10 @@
 
     const char* path = "/system/bin/init";
     const char* args[] = {path, "selinux_setup", nullptr};
+    auto fd = open("/dev/kmsg", O_WRONLY | O_CLOEXEC);
+    dup2(fd, STDOUT_FILENO);
+    dup2(fd, STDERR_FILENO);
+    close(fd);
     execv(path, const_cast<char**>(args));
 
     // execv() only returns if an error happened, in which case we
diff --git a/init/selinux.cpp b/init/selinux.cpp
index 143cdfd..fd42256 100644
--- a/init/selinux.cpp
+++ b/init/selinux.cpp
@@ -523,6 +523,7 @@
 
 // This function initializes SELinux then execs init to run in the init SELinux context.
 int SetupSelinux(char** argv) {
+    SetStdioToDevNull(argv);
     InitKernelLogging(argv);
 
     if (REBOOT_BOOTLOADER_ON_PANIC) {
diff --git a/libnativeloader/include/nativeloader/dlext_namespaces.h b/libnativeloader/include/nativeloader/dlext_namespaces.h
index 2d6ce85..8937636 100644
--- a/libnativeloader/include/nativeloader/dlext_namespaces.h
+++ b/libnativeloader/include/nativeloader/dlext_namespaces.h
@@ -22,18 +22,6 @@
 
 __BEGIN_DECLS
 
-/*
- * Initializes anonymous namespaces. The shared_libs_sonames is the list of sonames
- * to be shared by default namespace separated by colon. Example: "libc.so:libm.so:libdl.so".
- *
- * The library_search_path is the search path for anonymous namespace. The anonymous namespace
- * is used in the case when linker cannot identify the caller of dlopen/dlsym. This happens
- * for the code not loaded by dynamic linker; for example calls from the mono-compiled code.
- */
-extern bool android_init_anonymous_namespace(const char* shared_libs_sonames,
-                                             const char* library_search_path);
-
-
 enum {
   /* A regular namespace is the namespace with a custom search path that does
    * not impose any restrictions on the location of native libraries.
@@ -62,8 +50,18 @@
    */
   ANDROID_NAMESPACE_TYPE_GREYLIST_ENABLED = 0x08000000,
 
-  ANDROID_NAMESPACE_TYPE_SHARED_ISOLATED = ANDROID_NAMESPACE_TYPE_SHARED |
-                                           ANDROID_NAMESPACE_TYPE_ISOLATED,
+  /* This flag instructs linker to use this namespace as the anonymous
+   * namespace. The anonymous namespace is used in the case when linker cannot
+   * identify the caller of dlopen/dlsym. This happens for the code not loaded
+   * by dynamic linker; for example calls from the mono-compiled code. There can
+   * be only one anonymous namespace in a process. If there already is an
+   * anonymous namespace in the process, using this flag when creating a new
+   * namespace causes an error.
+   */
+  ANDROID_NAMESPACE_TYPE_ALSO_USED_AS_ANONYMOUS = 0x10000000,
+
+  ANDROID_NAMESPACE_TYPE_SHARED_ISOLATED =
+      ANDROID_NAMESPACE_TYPE_SHARED | ANDROID_NAMESPACE_TYPE_ISOLATED,
 };
 
 /*
diff --git a/libnativeloader/library_namespaces.cpp b/libnativeloader/library_namespaces.cpp
index a9eea8c..7f5768c 100644
--- a/libnativeloader/library_namespaces.cpp
+++ b/libnativeloader/library_namespaces.cpp
@@ -159,13 +159,6 @@
     }
   }
 
-  // Initialize the anonymous namespace with the first non-empty library path.
-  Result<void> ret;
-  if (!library_path.empty() && !initialized_ &&
-      !(ret = InitPublicNamespace(library_path.c_str()))) {
-    return ret.error();
-  }
-
   LOG_ALWAYS_FATAL_IF(FindNamespaceByClassLoader(env, class_loader) != nullptr,
                       "There is already a namespace associated with this classloader");
 
@@ -215,13 +208,22 @@
 
   // Create the app namespace
   NativeLoaderNamespace* parent_ns = FindParentNamespaceByClassLoader(env, class_loader);
-  auto app_ns =
-      NativeLoaderNamespace::Create(namespace_name, library_path, permitted_path, parent_ns,
-                                    is_shared, target_sdk_version < 24 /* is_greylist_enabled */);
+  // Heuristic: the first classloader with non-empty library_path is assumed to
+  // be the main classloader for app
+  // TODO(b/139178525) remove this heuristic by determining this in LoadedApk (or its
+  // friends) and then passing it down to here.
+  bool is_main_classloader = app_main_namespace_ == nullptr && !library_path.empty();
+  // Policy: the namespace for the main classloader is also used as the
+  // anonymous namespace.
+  bool also_used_as_anonymous = is_main_classloader;
+  // Note: this function is executed with g_namespaces_mutex held, thus no
+  // racing here.
+  auto app_ns = NativeLoaderNamespace::Create(
+      namespace_name, library_path, permitted_path, parent_ns, is_shared,
+      target_sdk_version < 24 /* is_greylist_enabled */, also_used_as_anonymous);
   if (!app_ns) {
     return app_ns.error();
   }
-
   // ... and link to other namespaces to allow access to some public libraries
   bool is_bridged = app_ns->IsBridged();
 
@@ -278,6 +280,9 @@
   }
 
   namespaces_.push_back(std::make_pair(env->NewWeakGlobalRef(class_loader), *app_ns));
+  if (is_main_classloader) {
+    app_main_namespace_ = &(*app_ns);
+  }
 
   return &(namespaces_.back().second);
 }
@@ -295,32 +300,6 @@
   return nullptr;
 }
 
-Result<void> LibraryNamespaces::InitPublicNamespace(const char* library_path) {
-  // Ask native bride if this apps library path should be handled by it
-  bool is_native_bridge = NativeBridgeIsPathSupported(library_path);
-
-  // (http://b/25844435) - Some apps call dlopen from generated code (mono jited
-  // code is one example) unknown to linker in which  case linker uses anonymous
-  // namespace. The second argument specifies the search path for the anonymous
-  // namespace which is the library_path of the classloader.
-  initialized_ = android_init_anonymous_namespace(default_public_libraries().c_str(),
-                                                  is_native_bridge ? nullptr : library_path);
-  if (!initialized_) {
-    return Error() << dlerror();
-  }
-
-  // and now initialize native bridge namespaces if necessary.
-  if (NativeBridgeInitialized()) {
-    initialized_ = NativeBridgeInitAnonymousNamespace(default_public_libraries().c_str(),
-                                                      is_native_bridge ? library_path : nullptr);
-    if (!initialized_) {
-      return Error() << NativeBridgeGetError();
-    }
-  }
-
-  return {};
-}
-
 NativeLoaderNamespace* LibraryNamespaces::FindParentNamespaceByClassLoader(JNIEnv* env,
                                                                            jobject class_loader) {
   jobject parent_class_loader = GetParentClassLoader(env, class_loader);
diff --git a/libnativeloader/library_namespaces.h b/libnativeloader/library_namespaces.h
index e54bc0a..7b3efff 100644
--- a/libnativeloader/library_namespaces.h
+++ b/libnativeloader/library_namespaces.h
@@ -38,7 +38,7 @@
 // object for a given ClassLoader.
 class LibraryNamespaces {
  public:
-  LibraryNamespaces() : initialized_(false) {}
+  LibraryNamespaces() : initialized_(false), app_main_namespace_(nullptr) {}
 
   LibraryNamespaces(LibraryNamespaces&&) = default;
   LibraryNamespaces(const LibraryNamespaces&) = delete;
@@ -48,6 +48,7 @@
   void Reset() {
     namespaces_.clear();
     initialized_ = false;
+    app_main_namespace_ = nullptr;
   }
   Result<NativeLoaderNamespace*> Create(JNIEnv* env, uint32_t target_sdk_version,
                                         jobject class_loader, bool is_shared, jstring dex_path,
@@ -59,6 +60,7 @@
   NativeLoaderNamespace* FindParentNamespaceByClassLoader(JNIEnv* env, jobject class_loader);
 
   bool initialized_;
+  NativeLoaderNamespace* app_main_namespace_;
   std::list<std::pair<jweak, NativeLoaderNamespace>> namespaces_;
 };
 
diff --git a/libnativeloader/native_loader_namespace.cpp b/libnativeloader/native_loader_namespace.cpp
index 4add6e6..a81fddf 100644
--- a/libnativeloader/native_loader_namespace.cpp
+++ b/libnativeloader/native_loader_namespace.cpp
@@ -85,7 +85,8 @@
 
 Result<NativeLoaderNamespace> NativeLoaderNamespace::Create(
     const std::string& name, const std::string& search_paths, const std::string& permitted_paths,
-    const NativeLoaderNamespace* parent, bool is_shared, bool is_greylist_enabled) {
+    const NativeLoaderNamespace* parent, bool is_shared, bool is_greylist_enabled,
+    bool also_used_as_anonymous) {
   bool is_bridged = false;
   if (parent != nullptr) {
     is_bridged = parent->IsBridged();
@@ -100,7 +101,17 @@
   }
   const NativeLoaderNamespace& effective_parent = parent != nullptr ? *parent : *platform_ns;
 
+  // All namespaces for apps are isolated
   uint64_t type = ANDROID_NAMESPACE_TYPE_ISOLATED;
+
+  // The namespace is also used as the anonymous namespace
+  // which is used when the linker fails to determine the caller address
+  if (also_used_as_anonymous) {
+    type |= ANDROID_NAMESPACE_TYPE_ALSO_USED_AS_ANONYMOUS;
+  }
+
+  // Bundled apps have access to all system libraries that are currently loaded
+  // in the default namespace
   if (is_shared) {
     type |= ANDROID_NAMESPACE_TYPE_SHARED;
   }
diff --git a/libnativeloader/native_loader_namespace.h b/libnativeloader/native_loader_namespace.h
index 29b759c..7200ee7 100644
--- a/libnativeloader/native_loader_namespace.h
+++ b/libnativeloader/native_loader_namespace.h
@@ -39,7 +39,8 @@
                                               const std::string& search_paths,
                                               const std::string& permitted_paths,
                                               const NativeLoaderNamespace* parent, bool is_shared,
-                                              bool is_greylist_enabled);
+                                              bool is_greylist_enabled,
+                                              bool also_used_as_anonymous);
 
   NativeLoaderNamespace(NativeLoaderNamespace&&) = default;
   NativeLoaderNamespace(const NativeLoaderNamespace&) = default;
diff --git a/libnativeloader/native_loader_test.cpp b/libnativeloader/native_loader_test.cpp
index b939eee..a641109 100644
--- a/libnativeloader/native_loader_test.cpp
+++ b/libnativeloader/native_loader_test.cpp
@@ -331,7 +331,8 @@
 
   // expected output (.. for the default test inputs)
   std::string expected_namespace_name = "classloader-namespace";
-  uint64_t expected_namespace_flags = ANDROID_NAMESPACE_TYPE_ISOLATED;
+  uint64_t expected_namespace_flags =
+      ANDROID_NAMESPACE_TYPE_ISOLATED | ANDROID_NAMESPACE_TYPE_ALSO_USED_AS_ANONYMOUS;
   std::string expected_library_path = library_path;
   std::string expected_permitted_path = std::string("/data:/mnt/expand:") + permitted_path;
   std::string expected_parent_namespace = "platform";
@@ -356,17 +357,6 @@
     EXPECT_CALL(*mock, NativeBridgeIsPathSupported(_)).Times(AnyNumber());
     EXPECT_CALL(*mock, NativeBridgeInitialized()).Times(AnyNumber());
 
-    if (IsBridged()) {
-      EXPECT_CALL(*mock,
-                  mock_init_anonymous_namespace(false, StrEq(default_public_libraries()), nullptr))
-          .WillOnce(Return(true));
-
-      EXPECT_CALL(*mock, NativeBridgeInitialized()).WillOnce(Return(true));
-    }
-
-    EXPECT_CALL(*mock, mock_init_anonymous_namespace(
-                           Eq(IsBridged()), StrEq(default_public_libraries()), StrEq(library_path)))
-        .WillOnce(Return(true));
     EXPECT_CALL(*mock, mock_create_namespace(
                            Eq(IsBridged()), StrEq(expected_namespace_name), nullptr,
                            StrEq(expected_library_path), expected_namespace_flags,
@@ -443,7 +433,7 @@
   dex_path = "/system/app/foo/foo.apk";
   is_shared = true;
 
-  expected_namespace_flags = ANDROID_NAMESPACE_TYPE_ISOLATED | ANDROID_NAMESPACE_TYPE_SHARED;
+  expected_namespace_flags |= ANDROID_NAMESPACE_TYPE_SHARED;
   SetExpectations();
   RunTest();
 }
@@ -452,7 +442,7 @@
   dex_path = "/vendor/app/foo/foo.apk";
   is_shared = true;
 
-  expected_namespace_flags = ANDROID_NAMESPACE_TYPE_ISOLATED | ANDROID_NAMESPACE_TYPE_SHARED;
+  expected_namespace_flags |= ANDROID_NAMESPACE_TYPE_SHARED;
   SetExpectations();
   RunTest();
 }
@@ -475,7 +465,7 @@
   dex_path = "/product/app/foo/foo.apk";
   is_shared = true;
 
-  expected_namespace_flags = ANDROID_NAMESPACE_TYPE_ISOLATED | ANDROID_NAMESPACE_TYPE_SHARED;
+  expected_namespace_flags |= ANDROID_NAMESPACE_TYPE_SHARED;
   SetExpectations();
   RunTest();
 }
@@ -485,7 +475,7 @@
   is_shared = true;
   target_sdk_version = 30;
 
-  expected_namespace_flags = ANDROID_NAMESPACE_TYPE_ISOLATED | ANDROID_NAMESPACE_TYPE_SHARED;
+  expected_namespace_flags |= ANDROID_NAMESPACE_TYPE_SHARED;
   SetExpectations();
   RunTest();
 }
@@ -512,6 +502,22 @@
   RunTest();
 }
 
+TEST_P(NativeLoaderTest_Create, NamespaceForSharedLibIsNotUsedAsAnonymousNamespace) {
+  if (IsBridged()) {
+    // There is no shared lib in translated arch
+    // TODO(jiyong): revisit this
+    return;
+  }
+  // compared to apks, for java shared libs, library_path is empty; java shared
+  // libs don't have their own native libs. They use platform's.
+  library_path = "";
+  expected_library_path = library_path;
+  // no ALSO_USED_AS_ANONYMOUS
+  expected_namespace_flags = ANDROID_NAMESPACE_TYPE_ISOLATED;
+  SetExpectations();
+  RunTest();
+}
+
 TEST_P(NativeLoaderTest_Create, TwoApks) {
   SetExpectations();
   const uint32_t second_app_target_sdk_version = 29;
@@ -523,6 +529,8 @@
   const std::string expected_second_app_permitted_path =
       std::string("/data:/mnt/expand:") + second_app_permitted_path;
   const std::string expected_second_app_parent_namespace = "classloader-namespace";
+  // no ALSO_USED_AS_ANONYMOUS
+  const uint64_t expected_second_namespace_flags = ANDROID_NAMESPACE_TYPE_ISOLATED;
 
   // The scenario is that second app is loaded by the first app.
   // So the first app's classloader (`classloader`) is parent of the second
@@ -532,10 +540,10 @@
 
   // namespace for the second app is created. Its parent is set to the namespace
   // of the first app.
-  EXPECT_CALL(*mock, mock_create_namespace(Eq(IsBridged()), StrEq(expected_namespace_name), nullptr,
-                                           StrEq(second_app_library_path), expected_namespace_flags,
-                                           StrEq(expected_second_app_permitted_path),
-                                           NsEq(dex_path.c_str())))
+  EXPECT_CALL(*mock, mock_create_namespace(
+                         Eq(IsBridged()), StrEq(expected_namespace_name), nullptr,
+                         StrEq(second_app_library_path), expected_second_namespace_flags,
+                         StrEq(expected_second_app_permitted_path), NsEq(dex_path.c_str())))
       .WillOnce(Return(TO_MOCK_NAMESPACE(TO_ANDROID_NAMESPACE(second_app_dex_path.c_str()))));
   EXPECT_CALL(*mock, mock_link_namespaces(Eq(IsBridged()), NsEq(second_app_dex_path.c_str()), _, _))
       .WillRepeatedly(Return(true));
@@ -568,7 +576,5 @@
 
 INSTANTIATE_TEST_SUITE_P(NativeLoaderTests_Create, NativeLoaderTest_Create, testing::Bool());
 
-// TODO(b/130388701#comment22) add a test for anonymous namespace
-
 }  // namespace nativeloader
 }  // namespace android
diff --git a/libsparse/output_file.cpp b/libsparse/output_file.cpp
index 5b8179f..c5c4960 100644
--- a/libsparse/output_file.cpp
+++ b/libsparse/output_file.cpp
@@ -17,6 +17,7 @@
 #define _FILE_OFFSET_BITS 64
 #define _LARGEFILE64_SOURCE 1
 
+#include <algorithm>
 #include <fcntl.h>
 #include <inttypes.h>
 #include <limits.h>
@@ -48,13 +49,6 @@
 #define off64_t off_t
 #endif
 
-#define min(a, b)        \
-  ({                     \
-    typeof(a) _a = (a);  \
-    typeof(b) _b = (b);  \
-    (_a < _b) ? _a : _b; \
-  })
-
 #define SPARSE_HEADER_MAJOR_VER 1
 #define SPARSE_HEADER_MINOR_VER 0
 #define SPARSE_HEADER_LEN (sizeof(sparse_header_t))
@@ -231,7 +225,7 @@
   struct output_file_gz* outgz = to_output_file_gz(out);
 
   while (len > 0) {
-    ret = gzwrite(outgz->gz_fd, data, min(len, (unsigned int)INT_MAX));
+    ret = gzwrite(outgz->gz_fd, data, std::min<unsigned int>(len, (unsigned int)INT_MAX));
     if (ret == 0) {
       error("gzwrite %s", gzerror(outgz->gz_fd, nullptr));
       return -1;
@@ -268,7 +262,7 @@
   int ret;
 
   while (off > 0) {
-    to_write = min(off, (int64_t)INT_MAX);
+    to_write = std::min(off, (int64_t)INT_MAX);
     ret = outc->write(outc->priv, nullptr, to_write);
     if (ret < 0) {
       return ret;
@@ -470,7 +464,7 @@
   }
 
   while (len) {
-    write_len = min(len, out->block_size);
+    write_len = std::min(len, out->block_size);
     ret = out->ops->write(out, out->fill_buf, write_len);
     if (ret < 0) {
       return ret;
diff --git a/rootdir/etc/ld.config.txt b/rootdir/etc/ld.config.txt
index 3321425..a639592 100644
--- a/rootdir/etc/ld.config.txt
+++ b/rootdir/etc/ld.config.txt
@@ -633,15 +633,15 @@
 
 namespace.neuralnetworks.search.paths = /apex/com.android.neuralnetworks/${LIB}
 namespace.neuralnetworks.asan.search.paths = /apex/com.android.neuralnetworks/${LIB}
-namespace.neuralnetworks.links = default
-namespace.neuralnetworks.link.default.shared_libs  = libc.so
-namespace.neuralnetworks.link.default.shared_libs += libcgrouprc.so
-namespace.neuralnetworks.link.default.shared_libs += libdl.so
-namespace.neuralnetworks.link.default.shared_libs += liblog.so
-namespace.neuralnetworks.link.default.shared_libs += libm.so
-namespace.neuralnetworks.link.default.shared_libs += libnativewindow.so
-namespace.neuralnetworks.link.default.shared_libs += libsync.so
-namespace.neuralnetworks.link.default.shared_libs += libvndksupport.so
+namespace.neuralnetworks.links = system
+namespace.neuralnetworks.link.system.shared_libs  = libc.so
+namespace.neuralnetworks.link.system.shared_libs += libcgrouprc.so
+namespace.neuralnetworks.link.system.shared_libs += libdl.so
+namespace.neuralnetworks.link.system.shared_libs += liblog.so
+namespace.neuralnetworks.link.system.shared_libs += libm.so
+namespace.neuralnetworks.link.system.shared_libs += libnativewindow.so
+namespace.neuralnetworks.link.system.shared_libs += libsync.so
+namespace.neuralnetworks.link.system.shared_libs += libvndksupport.so
 
 ###############################################################################
 # Namespace config for native tests that need access to both system and vendor
@@ -795,5 +795,3 @@
 namespace.default.search.paths  = /system/${LIB}
 namespace.default.search.paths += /%SYSTEM_EXT%/${LIB}
 namespace.default.search.paths += /%PRODUCT%/${LIB}
-
-namespace.default.link.runtime.shared_libs = %SANITIZER_RUNTIME_LIBRARIES%
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 86d8042..4d34b67 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -121,6 +121,9 @@
     mkdir /mnt/media_rw 0750 root media_rw
     mkdir /mnt/user 0755 root root
     mkdir /mnt/user/0 0755 root root
+    mkdir /mnt/user/0/self 0755 root root
+    mkdir /mnt/user/0/emulated 0755 root root
+    mkdir /mnt/user/0/emulated/0 0755 root root
     mkdir /mnt/expand 0771 system system
     mkdir /mnt/appfuse 0711 root root
 
@@ -367,9 +370,6 @@
     # Once everything is setup, no need to modify /.
     # The bind+remount combination allows this to work in containers.
     mount rootfs rootfs / remount bind ro nodev
-    # Mount default storage into root namespace
-    mount none /mnt/runtime/default /storage bind rec
-    mount none none /storage slave rec
 
     # Make sure /sys/kernel/debug (if present) is labeled properly
     # Note that tracefs may be mounted under debug, so we need to cross filesystems
@@ -642,6 +642,22 @@
     chown root system /dev/fscklogs/log
     chmod 0770 /dev/fscklogs/log
 
+# Switch between sdcardfs and FUSE depending on persist property
+# TODO: Move this to ro property before launch because FDE devices
+# interact with persistent properties differently during boot
+on zygote-start && property:persist.sys.fuse=true
+  # Mount default storage into root namespace
+  mount none /mnt/user/0 /storage bind rec
+  mount none none /storage slave rec
+on zygote-start && property:persist.sys.fuse=false
+  # Mount default storage into root namespace
+  mount none /mnt/runtime/default /storage bind rec
+  mount none none /storage slave rec
+on zygote-start && property:persist.sys.fuse=""
+  # Mount default storage into root namespace
+  mount none /mnt/runtime/default /storage bind rec
+  mount none none /storage slave rec
+
 # 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