Merge "Reland "Revert "rootdir / sdcard : Stop creating /data/media/obb.""" into qt-dev
diff --git a/adb/daemon/include/adbd/usb.h b/adb/daemon/include/adbd/usb.h
index 3213f69..fca3c58 100644
--- a/adb/daemon/include/adbd/usb.h
+++ b/adb/daemon/include/adbd/usb.h
@@ -43,7 +43,7 @@
     bool open_new_connection = true;
 
     int (*write)(usb_handle* h, const void* data, int len);
-    int (*read)(usb_handle* h, void* data, int len);
+    int (*read)(usb_handle* h, void* data, int len, bool allow_partial);
     void (*kick)(usb_handle* h);
     void (*close)(usb_handle* h);
 
diff --git a/adb/daemon/usb_legacy.cpp b/adb/daemon/usb_legacy.cpp
index b65727a..fe80e7d 100644
--- a/adb/daemon/usb_legacy.cpp
+++ b/adb/daemon/usb_legacy.cpp
@@ -142,11 +142,12 @@
     return orig_len;
 }
 
-static int usb_ffs_read(usb_handle* h, void* data, int len) {
+static int usb_ffs_read(usb_handle* h, void* data, int len, bool allow_partial) {
     D("about to read (fd=%d, len=%d)", h->bulk_out.get(), len);
 
     char* buf = static_cast<char*>(data);
     int orig_len = len;
+    unsigned count = 0;
     while (len > 0) {
         int read_len = std::min(USB_FFS_BULK_SIZE, len);
         int n = adb_read(h->bulk_out, buf, read_len);
@@ -156,6 +157,16 @@
         }
         buf += n;
         len -= n;
+        count += n;
+
+        // For fastbootd command such as "getvar all", len parameter is always set 64.
+        // But what we read is actually less than 64.
+        // For example, length 10 for "getvar all" command.
+        // If we get less data than expected, this means there should be no more data.
+        if (allow_partial && n < read_len) {
+            orig_len = count;
+            break;
+        }
     }
 
     D("[ done fd=%d ]", h->bulk_out.get());
@@ -221,7 +232,7 @@
     }
 }
 
-static int usb_ffs_aio_read(usb_handle* h, void* data, int len) {
+static int usb_ffs_aio_read(usb_handle* h, void* data, int len, bool allow_partial) {
     return usb_ffs_do_aio(h, data, len, true);
 }
 
@@ -299,7 +310,7 @@
 }
 
 int usb_read(usb_handle* h, void* data, int len) {
-    return h->read(h, data, len);
+    return h->read(h, data, len, false /* allow_partial */);
 }
 
 int usb_close(usb_handle* h) {
diff --git a/base/mapped_file.cpp b/base/mapped_file.cpp
index 7c65dc3..d26e8ba 100644
--- a/base/mapped_file.cpp
+++ b/base/mapped_file.cpp
@@ -76,7 +76,7 @@
   if (base_ != nullptr) UnmapViewOfFile(base_);
   if (handle_ != nullptr) CloseHandle(handle_);
 #else
-  if (base_ != nullptr) munmap(base_, size_);
+  if (base_ != nullptr) munmap(base_, size_ + offset_);
 #endif
 
   base_ = nullptr;
diff --git a/fastboot/device/usb_client.cpp b/fastboot/device/usb_client.cpp
index 775d10c..1014291 100644
--- a/fastboot/device/usb_client.cpp
+++ b/fastboot/device/usb_client.cpp
@@ -255,7 +255,8 @@
     size_t bytes_read_total = 0;
     while (bytes_read_total < len) {
         auto bytes_to_read = std::min(len - bytes_read_total, kFbFfsNumBufs * kFbFfsBufSize);
-        auto bytes_read_now = handle_->read(handle_.get(), char_data, bytes_to_read);
+        auto bytes_read_now =
+                handle_->read(handle_.get(), char_data, bytes_to_read, true /* allow_partial */);
         if (bytes_read_now < 0) {
             return bytes_read_total;
         }
diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp
index 3ea479e..f1ce125 100644
--- a/fs_mgr/fs_mgr.cpp
+++ b/fs_mgr/fs_mgr.cpp
@@ -923,7 +923,7 @@
   public:
     CheckpointManager(int needs_checkpoint = -1) : needs_checkpoint_(needs_checkpoint) {}
 
-    bool Update(FstabEntry* entry) {
+    bool Update(FstabEntry* entry, const std::string& block_device = std::string()) {
         if (!entry->fs_mgr_flags.checkpoint_blk && !entry->fs_mgr_flags.checkpoint_fs) {
             return true;
         }
@@ -942,7 +942,7 @@
             return true;
         }
 
-        if (!UpdateCheckpointPartition(entry)) {
+        if (!UpdateCheckpointPartition(entry, block_device)) {
             LERROR << "Could not set up checkpoint partition, skipping!";
             return false;
         }
@@ -972,7 +972,7 @@
     }
 
   private:
-    bool UpdateCheckpointPartition(FstabEntry* entry) {
+    bool UpdateCheckpointPartition(FstabEntry* entry, const std::string& block_device) {
         if (entry->fs_mgr_flags.checkpoint_fs) {
             if (is_f2fs(entry->fs_type)) {
                 entry->fs_options += ",checkpoint=disable";
@@ -980,39 +980,43 @@
                 LERROR << entry->fs_type << " does not implement checkpoints.";
             }
         } else if (entry->fs_mgr_flags.checkpoint_blk) {
-            unique_fd fd(TEMP_FAILURE_RETRY(open(entry->blk_device.c_str(), O_RDONLY | O_CLOEXEC)));
-            if (fd < 0) {
-                PERROR << "Cannot open device " << entry->blk_device;
-                return false;
-            }
+            auto actual_block_device = block_device.empty() ? entry->blk_device : block_device;
+            if (fs_mgr_find_bow_device(actual_block_device).empty()) {
+                unique_fd fd(
+                        TEMP_FAILURE_RETRY(open(entry->blk_device.c_str(), O_RDONLY | O_CLOEXEC)));
+                if (fd < 0) {
+                    PERROR << "Cannot open device " << entry->blk_device;
+                    return false;
+                }
 
-            uint64_t size = get_block_device_size(fd) / 512;
-            if (!size) {
-                PERROR << "Cannot get device size";
-                return false;
-            }
+                uint64_t size = get_block_device_size(fd) / 512;
+                if (!size) {
+                    PERROR << "Cannot get device size";
+                    return false;
+                }
 
-            android::dm::DmTable table;
-            if (!table.AddTarget(
-                        std::make_unique<android::dm::DmTargetBow>(0, size, entry->blk_device))) {
-                LERROR << "Failed to add bow target";
-                return false;
-            }
+                android::dm::DmTable table;
+                if (!table.AddTarget(std::make_unique<android::dm::DmTargetBow>(
+                            0, size, entry->blk_device))) {
+                    LERROR << "Failed to add bow target";
+                    return false;
+                }
 
-            DeviceMapper& dm = DeviceMapper::Instance();
-            if (!dm.CreateDevice("bow", table)) {
-                PERROR << "Failed to create bow device";
-                return false;
-            }
+                DeviceMapper& dm = DeviceMapper::Instance();
+                if (!dm.CreateDevice("bow", table)) {
+                    PERROR << "Failed to create bow device";
+                    return false;
+                }
 
-            std::string name;
-            if (!dm.GetDmDevicePathByName("bow", &name)) {
-                PERROR << "Failed to get bow device name";
-                return false;
-            }
+                std::string name;
+                if (!dm.GetDmDevicePathByName("bow", &name)) {
+                    PERROR << "Failed to get bow device name";
+                    return false;
+                }
 
-            device_map_[name] = entry->blk_device;
-            entry->blk_device = name;
+                device_map_[name] = entry->blk_device;
+                entry->blk_device = name;
+            }
         }
         return true;
     }
@@ -1022,6 +1026,50 @@
     std::map<std::string, std::string> device_map_;
 };
 
+std::string fs_mgr_find_bow_device(const std::string& block_device) {
+    if (block_device.substr(0, 5) != "/dev/") {
+        LOG(ERROR) << "Expected block device, got " << block_device;
+        return std::string();
+    }
+
+    std::string sys_dir = std::string("/sys/") + block_device.substr(5);
+
+    for (;;) {
+        std::string name;
+        if (!android::base::ReadFileToString(sys_dir + "/dm/name", &name)) {
+            PLOG(ERROR) << block_device << " is not dm device";
+            return std::string();
+        }
+
+        if (name == "bow\n") return sys_dir;
+
+        std::string slaves = sys_dir + "/slaves";
+        std::unique_ptr<DIR, decltype(&closedir)> directory(opendir(slaves.c_str()), closedir);
+        if (!directory) {
+            PLOG(ERROR) << "Can't open slave directory " << slaves;
+            return std::string();
+        }
+
+        int count = 0;
+        for (dirent* entry = readdir(directory.get()); entry; entry = readdir(directory.get())) {
+            if (entry->d_type != DT_LNK) continue;
+
+            if (count == 1) {
+                LOG(ERROR) << "Too many slaves in " << slaves;
+                return std::string();
+            }
+
+            ++count;
+            sys_dir = std::string("/sys/block/") + entry->d_name;
+        }
+
+        if (count != 1) {
+            LOG(ERROR) << "No slave in " << slaves;
+            return std::string();
+        }
+    }
+}
+
 static bool IsMountPointMounted(const std::string& mount_point) {
     // Check if this is already mounted.
     Fstab fstab;
@@ -1160,7 +1208,8 @@
                 }
                 encryptable = status;
                 if (status == FS_MGR_MNTALL_DEV_NEEDS_METADATA_ENCRYPTION) {
-                    if (!call_vdc({"cryptfs", "encryptFstab", attempted_entry.mount_point})) {
+                    if (!call_vdc({"cryptfs", "encryptFstab", attempted_entry.blk_device,
+                                   attempted_entry.mount_point})) {
                         LERROR << "Encryption failed";
                         return FS_MGR_MNTALL_FAIL;
                     }
@@ -1231,7 +1280,8 @@
             encryptable = FS_MGR_MNTALL_DEV_MIGHT_BE_ENCRYPTED;
         } else if (mount_errno != EBUSY && mount_errno != EACCES &&
                    should_use_metadata_encryption(attempted_entry)) {
-            if (!call_vdc({"cryptfs", "mountFstab", attempted_entry.mount_point})) {
+            if (!call_vdc({"cryptfs", "mountFstab", attempted_entry.blk_device,
+                           attempted_entry.mount_point})) {
                 ++error_count;
             }
             encryptable = FS_MGR_MNTALL_DEV_IS_METADATA_ENCRYPTED;
@@ -1361,7 +1411,7 @@
             }
         }
 
-        if (!checkpoint_manager.Update(&fstab_entry)) {
+        if (!checkpoint_manager.Update(&fstab_entry, n_blk_device)) {
             LERROR << "Could not set up checkpoint partition, skipping!";
             continue;
         }
diff --git a/fs_mgr/fs_mgr_fstab.cpp b/fs_mgr/fs_mgr_fstab.cpp
index e7c175f..7df7cfd 100644
--- a/fs_mgr/fs_mgr_fstab.cpp
+++ b/fs_mgr/fs_mgr_fstab.cpp
@@ -61,6 +61,7 @@
         {"nodiratime", MS_NODIRATIME},
         {"ro", MS_RDONLY},
         {"rw", 0},
+        {"sync", MS_SYNCHRONOUS},
         {"remount", MS_REMOUNT},
         {"bind", MS_BIND},
         {"rec", MS_REC},
diff --git a/fs_mgr/fs_mgr_overlayfs.cpp b/fs_mgr/fs_mgr_overlayfs.cpp
index c252ab5..0a6014d 100644
--- a/fs_mgr/fs_mgr_overlayfs.cpp
+++ b/fs_mgr/fs_mgr_overlayfs.cpp
@@ -90,7 +90,7 @@
     return {};
 }
 
-bool fs_mgr_overlayfs_setup(const char*, const char*, bool* change) {
+bool fs_mgr_overlayfs_setup(const char*, const char*, bool* change, bool) {
     if (change) *change = false;
     return false;
 }
@@ -621,7 +621,9 @@
         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");
+            auto other_slot = fs_mgr_get_other_slot_suffix();
+            if (other_slot.empty()) return "";
+            path = kPhysicalDevice + "system" + other_slot;
         }
     }
     return scratch_device_cache = path;
@@ -873,7 +875,8 @@
 
 // Returns false if setup not permitted, errno set to last error.
 // If something is altered, set *change.
-bool fs_mgr_overlayfs_setup(const char* backing, const char* mount_point, bool* change) {
+bool fs_mgr_overlayfs_setup(const char* backing, const char* mount_point, bool* change,
+                            bool force) {
     if (change) *change = false;
     auto ret = false;
     if (fs_mgr_overlayfs_valid() == OverlayfsValidResult::kNotSupported) return ret;
@@ -897,7 +900,7 @@
             continue;
         }
         save_errno = errno;
-        auto verity_enabled = fs_mgr_is_verity_enabled(*it);
+        auto verity_enabled = !force && fs_mgr_is_verity_enabled(*it);
         if (errno == ENOENT || errno == ENXIO) errno = save_errno;
         if (verity_enabled) {
             it = candidates.erase(it);
diff --git a/fs_mgr/fs_mgr_remount.cpp b/fs_mgr/fs_mgr_remount.cpp
index fcacd2a..967631b 100644
--- a/fs_mgr/fs_mgr_remount.cpp
+++ b/fs_mgr/fs_mgr_remount.cpp
@@ -250,6 +250,7 @@
     // Check verity and optionally setup overlayfs backing.
     auto reboot_later = false;
     auto uses_overlayfs = fs_mgr_overlayfs_valid() != OverlayfsValidResult::kNotSupported;
+    auto just_disabled_verity = false;
     for (auto it = partitions.begin(); it != partitions.end();) {
         auto& entry = *it;
         auto& mount_point = entry.mount_point;
@@ -262,7 +263,8 @@
                             false);
                     avb_ops_user_free(ops);
                     if (ret) {
-                        LOG(WARNING) << "Disable verity for " << mount_point;
+                        LOG(WARNING) << "Disabling verity for " << mount_point;
+                        just_disabled_verity = true;
                         reboot_later = can_reboot;
                         if (reboot_later) {
                             // w/o overlayfs available, also check for dedupe
@@ -275,7 +277,8 @@
                     } else if (fs_mgr_set_blk_ro(entry.blk_device, false)) {
                         fec::io fh(entry.blk_device.c_str(), O_RDWR);
                         if (fh && fh.set_verity_status(false)) {
-                            LOG(WARNING) << "Disable verity for " << mount_point;
+                            LOG(WARNING) << "Disabling verity for " << mount_point;
+                            just_disabled_verity = true;
                             reboot_later = can_reboot;
                             if (reboot_later && !uses_overlayfs) {
                                 ++it;
@@ -292,7 +295,7 @@
 
         auto change = false;
         errno = 0;
-        if (fs_mgr_overlayfs_setup(nullptr, mount_point.c_str(), &change)) {
+        if (fs_mgr_overlayfs_setup(nullptr, mount_point.c_str(), &change, just_disabled_verity)) {
             if (change) {
                 LOG(INFO) << "Using overlayfs for " << mount_point;
             }
diff --git a/fs_mgr/include/fs_mgr.h b/fs_mgr/include/fs_mgr.h
index 88b2f8f..bdec7be 100644
--- a/fs_mgr/include/fs_mgr.h
+++ b/fs_mgr/include/fs_mgr.h
@@ -104,3 +104,7 @@
 // fs_mgr_umount_all() is the reverse of fs_mgr_mount_all. In particular,
 // it destroys verity devices from device mapper after the device is unmounted.
 int fs_mgr_umount_all(android::fs_mgr::Fstab* fstab);
+
+// Finds the dm_bow device on which this block device is stacked, or returns
+// empty string
+std::string fs_mgr_find_bow_device(const std::string& block_device);
diff --git a/fs_mgr/include/fs_mgr_overlayfs.h b/fs_mgr/include/fs_mgr_overlayfs.h
index 6aaf1f3..9a7381f 100644
--- a/fs_mgr/include/fs_mgr_overlayfs.h
+++ b/fs_mgr/include/fs_mgr_overlayfs.h
@@ -26,7 +26,7 @@
 bool fs_mgr_overlayfs_mount_all(android::fs_mgr::Fstab* fstab);
 std::vector<std::string> fs_mgr_overlayfs_required_devices(android::fs_mgr::Fstab* fstab);
 bool fs_mgr_overlayfs_setup(const char* backing = nullptr, const char* mount_point = nullptr,
-                            bool* change = nullptr);
+                            bool* change = nullptr, bool force = true);
 bool fs_mgr_overlayfs_teardown(const char* mount_point = nullptr, bool* change = nullptr);
 bool fs_mgr_overlayfs_is_setup();
 bool fs_mgr_has_shared_blocks(const std::string& mount_point, const std::string& dev);
diff --git a/fs_mgr/liblp/Android.bp b/fs_mgr/liblp/Android.bp
index 7039994..b504161 100644
--- a/fs_mgr/liblp/Android.bp
+++ b/fs_mgr/liblp/Android.bp
@@ -14,6 +14,16 @@
 // limitations under the License.
 //
 
+liblp_lib_deps = [
+    "libbase",
+    "liblog",
+    "libcrypto",
+    "libcrypto_utils",
+    "libsparse",
+    "libext4_utils",
+    "libz",
+]
+
 cc_library {
     name: "liblp",
     host_supported: true,
@@ -30,15 +40,7 @@
         "utility.cpp",
         "writer.cpp",
     ],
-    shared_libs: [
-        "libbase",
-        "liblog",
-        "libcrypto",
-        "libcrypto_utils",
-        "libsparse",
-        "libext4_utils",
-        "libz",
-    ],
+    shared_libs: liblp_lib_deps,
     target: {
         windows: {
             enabled: true,
@@ -53,24 +55,28 @@
 }
 
 cc_test {
-    name: "liblp_test",
+    name: "liblp_test_static",
     defaults: ["fs_mgr_defaults"],
     cppflags: [
         "-Wno-unused-parameter",
     ],
     static_libs: [
         "libgmock",
-    ],
-    shared_libs: [
-        "liblp",
-        "libbase",
         "libfs_mgr",
-        "libsparse",
-    ],
+        "liblp",
+    ] + liblp_lib_deps,
+    stl: "libc++_static",
     srcs: [
         "builder_test.cpp",
         "io_test.cpp",
         "test_partition_opener.cpp",
         "utility_test.cpp",
     ],
+    target: {
+        android: {
+            static_libs: [
+                "libcutils",
+            ],
+        },
+    },
 }
diff --git a/fs_mgr/liblp/AndroidTest.xml b/fs_mgr/liblp/AndroidTest.xml
index 007a302..fe1002c 100644
--- a/fs_mgr/liblp/AndroidTest.xml
+++ b/fs_mgr/liblp/AndroidTest.xml
@@ -21,8 +21,8 @@
     </target_preparer>
     <test class="com.android.tradefed.testtype.VtsMultiDeviceTest">
       <option name="test-module-name" value="VtsKernelLiblpTest"/>
-        <option name="binary-test-source" value="_32bit::DATA/nativetest/liblp_test/liblp_test" />
-        <option name="binary-test-source" value="_64bit::DATA/nativetest64/liblp_test/liblp_test" />
+        <option name="binary-test-source" value="_32bit::DATA/nativetest/liblp_test_static/liblp_test_static" />
+        <option name="binary-test-source" value="_64bit::DATA/nativetest64/liblp_test_static/liblp_test_static" />
         <option name="binary-test-type" value="gtest"/>
         <option name="test-timeout" value="1m"/>
         <option name="precondition-first-api-level" value="29" />
diff --git a/gatekeeperd/SoftGateKeeper.h b/gatekeeperd/SoftGateKeeper.h
index 2f4f4d7..5c03dcf 100644
--- a/gatekeeperd/SoftGateKeeper.h
+++ b/gatekeeperd/SoftGateKeeper.h
@@ -58,23 +58,16 @@
     virtual ~SoftGateKeeper() {
     }
 
-    virtual bool GetAuthTokenKey(const uint8_t **auth_token_key,
-            uint32_t *length) const {
+    virtual bool GetAuthTokenKey(const uint8_t** auth_token_key, uint32_t* length) const {
         if (auth_token_key == NULL || length == NULL) return false;
-        uint8_t *auth_token_key_copy = new uint8_t[SIGNATURE_LENGTH_BYTES];
-        memcpy(auth_token_key_copy, key_.get(), SIGNATURE_LENGTH_BYTES);
-
-        *auth_token_key = auth_token_key_copy;
+        *auth_token_key = key_.get();
         *length = SIGNATURE_LENGTH_BYTES;
         return true;
     }
 
-    virtual void GetPasswordKey(const uint8_t **password_key, uint32_t *length) {
+    virtual void GetPasswordKey(const uint8_t** password_key, uint32_t* length) {
         if (password_key == NULL || length == NULL) return;
-        uint8_t *password_key_copy = new uint8_t[SIGNATURE_LENGTH_BYTES];
-        memcpy(password_key_copy, key_.get(), SIGNATURE_LENGTH_BYTES);
-
-        *password_key = password_key_copy;
+        *password_key = key_.get();
         *length = SIGNATURE_LENGTH_BYTES;
     }
 
diff --git a/healthd/Android.mk b/healthd/Android.mk
index d18f15a..05123af 100644
--- a/healthd/Android.mk
+++ b/healthd/Android.mk
@@ -93,7 +93,6 @@
     libbinderthreadstate \
     libhidltransport \
     libhidlbase \
-    libhwbinder_noltopgo \
     libhealthstoragedefault \
     libvndksupport \
     libhealthd_charger \
@@ -152,7 +151,6 @@
     libbinderthreadstate \
     libhidltransport \
     libhidlbase \
-    libhwbinder_noltopgo \
     libhealthstoragedefault \
     libvndksupport \
     libhealthd_charger_nops \
diff --git a/init/Android.bp b/init/Android.bp
index 69498ac..6be7290 100644
--- a/init/Android.bp
+++ b/init/Android.bp
@@ -68,6 +68,7 @@
         "libpropertyinfoparser",
     ],
     shared_libs: [
+        "libbacktrace",
         "libbase",
         "libbinder",
         "libbootloader_message",
diff --git a/init/Android.mk b/init/Android.mk
index b02c926..c4f7d34 100644
--- a/init/Android.mk
+++ b/init/Android.mk
@@ -105,6 +105,10 @@
     libcap \
     libgsi \
     libcom.android.sysprop.apex \
+    liblzma \
+    libdexfile_support \
+    libunwindstack \
+    libbacktrace \
 
 LOCAL_SANITIZE := signed-integer-overflow
 # First stage init is weird: it may start without stdout/stderr, and no /proc.
diff --git a/init/first_stage_init.cpp b/init/first_stage_init.cpp
index 8b95e38..2b89940 100644
--- a/init/first_stage_init.cpp
+++ b/init/first_stage_init.cpp
@@ -33,7 +33,6 @@
 #include <android-base/chrono_utils.h>
 #include <android-base/file.h>
 #include <android-base/logging.h>
-#include <cutils/android_reboot.h>
 #include <private/android_filesystem_config.h>
 
 #include "debug_ramdisk.h"
@@ -168,13 +167,10 @@
                     "mode=0755,uid=0,gid=0"));
 #undef CHECKCALL
 
+    SetStdioToDevNull(argv);
     // Now that tmpfs is mounted on /dev and we have /dev/kmsg, we can actually
     // talk to the outside world...
-    // We need to set up stdin/stdout/stderr for child processes forked from first
-    // stage init as part of the mount process.  This closes /dev/console if the
-    // kernel had previously opened it.
-    auto reboot_bootloader = [](const char*) { RebootSystem(ANDROID_RB_RESTART2, "bootloader"); };
-    InitKernelLogging(argv, reboot_bootloader);
+    InitKernelLogging(argv);
 
     if (!errors.empty()) {
         for (const auto& [error_string, error_errno] : errors) {
diff --git a/init/host_init_stubs.h b/init/host_init_stubs.h
index 63ceead..f6e9676 100644
--- a/init/host_init_stubs.h
+++ b/init/host_init_stubs.h
@@ -44,6 +44,12 @@
 uint32_t HandlePropertySet(const std::string& name, const std::string& value,
                            const std::string& source_context, const ucred& cr, std::string* error);
 
+// reboot_utils.h
+inline void SetFatalRebootTarget() {}
+inline void __attribute__((noreturn)) InitFatalReboot() {
+    abort();
+}
+
 // selinux.h
 int SelinuxGetVendorAndroidVersion();
 void SelabelInitialize();
diff --git a/init/init.cpp b/init/init.cpp
index c79e459..6b03bc9 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -38,7 +38,6 @@
 #include <android-base/properties.h>
 #include <android-base/stringprintf.h>
 #include <android-base/strings.h>
-#include <cutils/android_reboot.h>
 #include <fs_avb/fs_avb.h>
 #include <fs_mgr_vendor_overlay.h>
 #include <keyutils.h>
@@ -601,17 +600,6 @@
     }
 }
 
-static void InitAborter(const char* abort_message) {
-    // When init forks, it continues to use this aborter for LOG(FATAL), but we want children to
-    // simply abort instead of trying to reboot the system.
-    if (getpid() != 1) {
-        android::base::DefaultAborter(abort_message);
-        return;
-    }
-
-    RebootSystem(ANDROID_RB_RESTART2, "bootloader");
-}
-
 static void GlobalSeccomp() {
     import_kernel_cmdline(false, [](const std::string& key, const std::string& value,
                                     bool in_qemu) {
@@ -632,8 +620,8 @@
         InstallRebootSignalHandlers();
     }
 
-    // We need to set up stdin/stdout/stderr again now that we're running in init's context.
-    InitKernelLogging(argv, InitAborter);
+    SetStdioToDevNull(argv);
+    InitKernelLogging(argv);
     LOG(INFO) << "init second stage started!";
 
     // Set init and its forked children's oom_adj.
diff --git a/init/property_service.cpp b/init/property_service.cpp
index fce8d57..f2c7462 100644
--- a/init/property_service.cpp
+++ b/init/property_service.cpp
@@ -642,8 +642,14 @@
                 while (isspace(*key)) key++;
             }
 
-            load_properties_from_file(fn, key, properties);
+            std::string raw_filename(fn);
+            std::string expanded_filename;
+            if (!expand_props(raw_filename, &expanded_filename)) {
+                LOG(ERROR) << "Could not expand filename '" << raw_filename << "'";
+                continue;
+            }
 
+            load_properties_from_file(expanded_filename.c_str(), key, properties);
         } else {
             value = strchr(key, '=');
             if (!value) continue;
diff --git a/init/reboot_utils.cpp b/init/reboot_utils.cpp
index 9610304..d1a712f 100644
--- a/init/reboot_utils.cpp
+++ b/init/reboot_utils.cpp
@@ -19,14 +19,40 @@
 #include <sys/syscall.h>
 #include <unistd.h>
 
-#include <android-base/logging.h>
-#include <cutils/android_reboot.h>
+#include <string>
+
+#include "android-base/file.h"
+#include "android-base/logging.h"
+#include "android-base/strings.h"
+#include "backtrace/Backtrace.h"
+#include "cutils/android_reboot.h"
 
 #include "capabilities.h"
 
 namespace android {
 namespace init {
 
+static std::string init_fatal_reboot_target = "bootloader";
+
+void SetFatalRebootTarget() {
+    std::string cmdline;
+    android::base::ReadFileToString("/proc/cmdline", &cmdline);
+    cmdline = android::base::Trim(cmdline);
+
+    const char kRebootTargetString[] = "androidboot.init_fatal_reboot_target=";
+    auto start_pos = cmdline.find(kRebootTargetString);
+    if (start_pos == std::string::npos) {
+        return;  // We already default to bootloader if no setting is provided.
+    }
+    start_pos += sizeof(kRebootTargetString) - 1;
+
+    auto end_pos = cmdline.find(' ', start_pos);
+    // if end_pos isn't found, then we've run off the end, but this is okay as this is the last
+    // entry, and -1 is a valid size for string::substr();
+    auto size = end_pos == std::string::npos ? -1 : end_pos - start_pos;
+    init_fatal_reboot_target = cmdline.substr(start_pos, size);
+}
+
 bool IsRebootCapable() {
     if (!CAP_IS_SUPPORTED(CAP_SYS_BOOT)) {
         PLOG(WARNING) << "CAP_SYS_BOOT is not supported";
@@ -75,6 +101,32 @@
     abort();
 }
 
+void __attribute__((noreturn)) InitFatalReboot() {
+    auto pid = fork();
+
+    if (pid == -1) {
+        // Couldn't fork, don't even try to backtrace, just reboot.
+        RebootSystem(ANDROID_RB_RESTART2, init_fatal_reboot_target);
+    } else if (pid == 0) {
+        // Fork a child for safety, since we always want to shut down if something goes wrong, but
+        // its worth trying to get the backtrace, even in the signal handler, since typically it
+        // does work despite not being async-signal-safe.
+        sleep(5);
+        RebootSystem(ANDROID_RB_RESTART2, init_fatal_reboot_target);
+    }
+
+    // In the parent, let's try to get a backtrace then shutdown.
+    std::unique_ptr<Backtrace> backtrace(
+            Backtrace::Create(BACKTRACE_CURRENT_PROCESS, BACKTRACE_CURRENT_THREAD));
+    if (!backtrace->Unwind(0)) {
+        LOG(ERROR) << __FUNCTION__ << ": Failed to unwind callstack.";
+    }
+    for (size_t i = 0; i < backtrace->NumFrames(); i++) {
+        LOG(ERROR) << backtrace->FormatFrameData(i);
+    }
+    RebootSystem(ANDROID_RB_RESTART2, init_fatal_reboot_target);
+}
+
 void InstallRebootSignalHandlers() {
     // Instead of panic'ing the kernel as is the default behavior when init crashes,
     // we prefer to reboot to bootloader on development builds, as this will prevent
@@ -94,7 +146,7 @@
         // RebootSystem uses syscall() which isn't actually async-signal-safe, but our only option
         // and probably good enough given this is already an error case and only enabled for
         // development builds.
-        RebootSystem(ANDROID_RB_RESTART2, "bootloader");
+        InitFatalReboot();
     };
     action.sa_flags = SA_RESTART;
     sigaction(SIGABRT, &action, nullptr);
diff --git a/init/reboot_utils.h b/init/reboot_utils.h
index 073a16a..3fd969e 100644
--- a/init/reboot_utils.h
+++ b/init/reboot_utils.h
@@ -21,11 +21,13 @@
 namespace android {
 namespace init {
 
+void SetFatalRebootTarget();
 // Determines whether the system is capable of rebooting. This is conservative,
 // so if any of the attempts to determine this fail, it will still return true.
 bool IsRebootCapable();
 // This is a wrapper around the actual reboot calls.
 void __attribute__((noreturn)) RebootSystem(unsigned int cmd, const std::string& reboot_target);
+void __attribute__((noreturn)) InitFatalReboot();
 void InstallRebootSignalHandlers();
 
 }  // namespace init
diff --git a/init/selinux.cpp b/init/selinux.cpp
index 132fc13..86238b4 100644
--- a/init/selinux.cpp
+++ b/init/selinux.cpp
@@ -60,7 +60,6 @@
 #include <android-base/logging.h>
 #include <android-base/parseint.h>
 #include <android-base/unique_fd.h>
-#include <cutils/android_reboot.h>
 #include <fs_avb/fs_avb.h>
 #include <selinux/android.h>
 
@@ -518,9 +517,7 @@
 
 // This function initializes SELinux then execs init to run in the init SELinux context.
 int SetupSelinux(char** argv) {
-    android::base::InitLogging(argv, &android::base::KernelLogger, [](const char*) {
-        RebootSystem(ANDROID_RB_RESTART2, "bootloader");
-    });
+    InitKernelLogging(argv);
 
     if (REBOOT_BOOTLOADER_ON_PANIC) {
         InstallRebootSignalHandlers();
diff --git a/init/util.cpp b/init/util.cpp
index 29d7a76..63d2d44 100644
--- a/init/util.cpp
+++ b/init/util.cpp
@@ -40,6 +40,7 @@
 #include <selinux/android.h>
 
 #if defined(__ANDROID__)
+#include "reboot_utils.h"
 #include "selinux.h"
 #else
 #include "host_init_stubs.h"
@@ -425,20 +426,50 @@
     return true;
 }
 
-void InitKernelLogging(char** argv, std::function<void(const char*)> abort_function) {
+static void InitAborter(const char* abort_message) {
+    // When init forks, it continues to use this aborter for LOG(FATAL), but we want children to
+    // simply abort instead of trying to reboot the system.
+    if (getpid() != 1) {
+        android::base::DefaultAborter(abort_message);
+        return;
+    }
+
+    InitFatalReboot();
+}
+
+// The kernel opens /dev/console and uses that fd for stdin/stdout/stderr if there is a serial
+// console enabled and no initramfs, otherwise it does not provide any fds for stdin/stdout/stderr.
+// SetStdioToDevNull() is used to close these existing fds if they exist and replace them with
+// /dev/null regardless.
+//
+// In the case that these fds are provided by the kernel, the exec of second stage init causes an
+// SELinux denial as it does not have access to /dev/console.  In the case that they are not
+// provided, exec of any further process is potentially dangerous as the first fd's opened by that
+// process will take the stdin/stdout/stderr fileno's, which can cause issues if printf(), etc is
+// then used by that process.
+//
+// Lastly, simply calling SetStdioToDevNull() in first stage init is not enough, since first
+// stage init still runs in kernel context, future child processes will not have permissions to
+// access any fds that it opens, including the one opened below for /dev/null.  Therefore,
+// SetStdioToDevNull() must be called again in second stage init.
+void SetStdioToDevNull(char** argv) {
     // Make stdin/stdout/stderr all point to /dev/null.
     int fd = open("/dev/null", O_RDWR);
     if (fd == -1) {
         int saved_errno = errno;
-        android::base::InitLogging(argv, &android::base::KernelLogger, std::move(abort_function));
+        android::base::InitLogging(argv, &android::base::KernelLogger, InitAborter);
         errno = saved_errno;
         PLOG(FATAL) << "Couldn't open /dev/null";
     }
-    dup2(fd, 0);
-    dup2(fd, 1);
-    dup2(fd, 2);
-    if (fd > 2) close(fd);
-    android::base::InitLogging(argv, &android::base::KernelLogger, std::move(abort_function));
+    dup2(fd, STDIN_FILENO);
+    dup2(fd, STDOUT_FILENO);
+    dup2(fd, STDERR_FILENO);
+    if (fd > STDERR_FILENO) close(fd);
+}
+
+void InitKernelLogging(char** argv) {
+    SetFatalRebootTarget();
+    android::base::InitLogging(argv, &android::base::KernelLogger, InitAborter);
 }
 
 bool IsRecoveryMode() {
diff --git a/init/util.h b/init/util.h
index 2232a0f..767620b 100644
--- a/init/util.h
+++ b/init/util.h
@@ -63,7 +63,8 @@
 
 bool IsLegalPropertyName(const std::string& name);
 
-void InitKernelLogging(char** argv, std::function<void(const char*)> abort_function);
+void SetStdioToDevNull(char** argv);
+void InitKernelLogging(char** argv);
 bool IsRecoveryMode();
 }  // namespace init
 }  // namespace android
diff --git a/libappfuse/FuseBridgeLoop.cc b/libappfuse/FuseBridgeLoop.cc
index ac94e69..f71d0c3 100644
--- a/libappfuse/FuseBridgeLoop.cc
+++ b/libappfuse/FuseBridgeLoop.cc
@@ -86,6 +86,7 @@
         const bool proxy_read_ready = last_proxy_events_.events & EPOLLIN;
         const bool proxy_write_ready = last_proxy_events_.events & EPOLLOUT;
 
+        last_state_ = state_;
         last_device_events_.events = 0;
         last_proxy_events_.events = 0;
 
@@ -353,8 +354,8 @@
         }
         if (entry->IsClosing()) {
             const int mount_id = entry->mount_id();
-            callback->OnClosed(mount_id);
             bridges_.erase(mount_id);
+            callback->OnClosed(mount_id);
             if (bridges_.size() == 0) {
                 // All bridges are now closed.
                 return false;
diff --git a/libmemunreachable/Android.bp b/libmemunreachable/Android.bp
index b78a4c4..8f01e50 100644
--- a/libmemunreachable/Android.bp
+++ b/libmemunreachable/Android.bp
@@ -96,7 +96,7 @@
     static_libs: ["libmemunreachable"],
     shared_libs: [
         "libbinder",
-        "libhwbinder",
+        "libhidlbase",
         "libutils",
     ],
     test_suites: ["device-tests"],
diff --git a/libprocessgroup/cgroup_map.cpp b/libprocessgroup/cgroup_map.cpp
index 92fcd1e..20ae2be 100644
--- a/libprocessgroup/cgroup_map.cpp
+++ b/libprocessgroup/cgroup_map.cpp
@@ -67,11 +67,14 @@
     return controller_ != nullptr;
 }
 
-bool CgroupController::IsUsable() const {
+bool CgroupController::IsUsable() {
     if (!HasValue()) return false;
 
-    uint32_t flags = ACgroupController_getFlags(controller_);
-    return (flags & CGROUPRC_CONTROLLER_FLAG_MOUNTED) != 0;
+    if (state_ == UNKNOWN) {
+        state_ = access(GetProcsFilePath("", 0, 0).c_str(), F_OK) == 0 ? USABLE : MISSING;
+    }
+
+    return state_ == USABLE;
 }
 
 std::string CgroupController::GetTasksFilePath(const std::string& rel_path) const {
@@ -160,7 +163,6 @@
         const ACgroupController* controller = ACgroupFile_getController(i);
         LOG(INFO) << "\t" << ACgroupController_getName(controller) << " ver "
                   << ACgroupController_getVersion(controller) << " path "
-                  << ACgroupController_getFlags(controller) << " flags "
                   << ACgroupController_getPath(controller);
     }
 }
diff --git a/libprocessgroup/cgroup_map.h b/libprocessgroup/cgroup_map.h
index 9350412..427d71b 100644
--- a/libprocessgroup/cgroup_map.h
+++ b/libprocessgroup/cgroup_map.h
@@ -31,20 +31,28 @@
 class CgroupController {
   public:
     // Does not own controller
-    explicit CgroupController(const ACgroupController* controller) : controller_(controller) {}
+    explicit CgroupController(const ACgroupController* controller)
+        : controller_(controller), state_(UNKNOWN) {}
 
     uint32_t version() const;
     const char* name() const;
     const char* path() const;
 
     bool HasValue() const;
-    bool IsUsable() const;
+    bool IsUsable();
 
     std::string GetTasksFilePath(const std::string& path) const;
     std::string GetProcsFilePath(const std::string& path, uid_t uid, pid_t pid) const;
     bool GetTaskGroup(int tid, std::string* group) const;
   private:
+    enum ControllerState {
+        UNKNOWN = 0,
+        USABLE = 1,
+        MISSING = 2,
+    };
+
     const ACgroupController* controller_ = nullptr;
+    ControllerState state_;
 };
 
 class CgroupMap {
diff --git a/libprocessgroup/cgrouprc/cgroup_controller.cpp b/libprocessgroup/cgrouprc/cgroup_controller.cpp
index 5a326e5..d064d31 100644
--- a/libprocessgroup/cgrouprc/cgroup_controller.cpp
+++ b/libprocessgroup/cgrouprc/cgroup_controller.cpp
@@ -27,11 +27,6 @@
     return controller->version();
 }
 
-uint32_t ACgroupController_getFlags(const ACgroupController* controller) {
-    CHECK(controller != nullptr);
-    return controller->flags();
-}
-
 const char* ACgroupController_getName(const ACgroupController* controller) {
     CHECK(controller != nullptr);
     return controller->name();
diff --git a/libprocessgroup/cgrouprc/include/android/cgrouprc.h b/libprocessgroup/cgrouprc/include/android/cgrouprc.h
index ffc9f0b..0f6a9cd 100644
--- a/libprocessgroup/cgrouprc/include/android/cgrouprc.h
+++ b/libprocessgroup/cgrouprc/include/android/cgrouprc.h
@@ -66,18 +66,11 @@
         __INTRODUCED_IN(29);
 
 /**
- * Flag bitmask used in ACgroupController_getFlags
+ * Flag bitmask to be used when ACgroupController_getFlags can be exported
  */
 #define CGROUPRC_CONTROLLER_FLAG_MOUNTED 0x1
 
 /**
- * Returns the flags bitmask of the given controller.
- * If the given controller is null, return 0.
- */
-__attribute__((warn_unused_result)) uint32_t ACgroupController_getFlags(const ACgroupController*)
-        __INTRODUCED_IN(29);
-
-/**
  * Returns the name of the given controller.
  * If the given controller is null, return nullptr.
  */
diff --git a/libprocessgroup/cgrouprc/libcgrouprc.llndk.txt b/libprocessgroup/cgrouprc/libcgrouprc.llndk.txt
index ea3df33..91df392 100644
--- a/libprocessgroup/cgrouprc/libcgrouprc.llndk.txt
+++ b/libprocessgroup/cgrouprc/libcgrouprc.llndk.txt
@@ -4,7 +4,6 @@
     ACgroupFile_getControllerCount;
     ACgroupFile_getController;
     ACgroupController_getVersion;
-    ACgroupController_getFlags;
     ACgroupController_getName;
     ACgroupController_getPath;
   local:
diff --git a/libprocessgroup/task_profiles.cpp b/libprocessgroup/task_profiles.cpp
index 40d8d90..edc316a 100644
--- a/libprocessgroup/task_profiles.cpp
+++ b/libprocessgroup/task_profiles.cpp
@@ -150,6 +150,7 @@
 }
 
 void SetCgroupAction::EnableResourceCaching() {
+    std::lock_guard<std::mutex> lock(fd_mutex_);
     if (fd_ != FDS_NOT_CACHED) {
         return;
     }
@@ -191,6 +192,7 @@
 }
 
 bool SetCgroupAction::ExecuteForProcess(uid_t uid, pid_t pid) const {
+    std::lock_guard<std::mutex> lock(fd_mutex_);
     if (IsFdValid()) {
         // fd is cached, reuse it
         if (!AddTidToCgroup(pid, fd_)) {
@@ -221,6 +223,7 @@
 }
 
 bool SetCgroupAction::ExecuteForTask(int tid) const {
+    std::lock_guard<std::mutex> lock(fd_mutex_);
     if (IsFdValid()) {
         // fd is cached, reuse it
         if (!AddTidToCgroup(tid, fd_)) {
diff --git a/libprocessgroup/task_profiles.h b/libprocessgroup/task_profiles.h
index 445647d..77bac2d 100644
--- a/libprocessgroup/task_profiles.h
+++ b/libprocessgroup/task_profiles.h
@@ -19,6 +19,7 @@
 #include <sys/cdefs.h>
 #include <sys/types.h>
 #include <map>
+#include <mutex>
 #include <string>
 #include <vector>
 
@@ -127,6 +128,7 @@
     CgroupController controller_;
     std::string path_;
     android::base::unique_fd fd_;
+    mutable std::mutex fd_mutex_;
 
     static bool IsAppDependentPath(const std::string& path);
     static bool AddTidToCgroup(int tid, int fd);
diff --git a/lmkd/lmkd.c b/lmkd/lmkd.c
index 2de7378..c2ee061 100644
--- a/lmkd/lmkd.c
+++ b/lmkd/lmkd.c
@@ -1373,8 +1373,8 @@
     set_process_group_and_prio(pid, SP_FOREGROUND, ANDROID_PRIORITY_HIGHEST);
 
     inc_killcnt(procp->oomadj);
-    ALOGI("Kill '%s' (%d), uid %d, oom_adj %d to free %ldkB",
-        taskname, pid, uid, procp->oomadj, tasksize * page_k);
+    ALOGE("Kill '%s' (%d), uid %d, oom_adj %d to free %ldkB", taskname, pid, uid, procp->oomadj,
+          tasksize * page_k);
 
     TRACE_KILL_END();
 
diff --git a/logd/tests/logd_test.cpp b/logd/tests/logd_test.cpp
index 447b067..b6c33d7 100644
--- a/logd/tests/logd_test.cpp
+++ b/logd/tests/logd_test.cpp
@@ -952,7 +952,7 @@
 void __android_log_btwrite_multiple__helper(int count) {
 #ifdef __ANDROID__
     log_time ts(CLOCK_MONOTONIC);
-
+    usleep(100);
     log_time ts1(CLOCK_MONOTONIC);
 
     // We fork to create a unique pid for the submitted log messages
diff --git a/rootdir/etc/ld.config.txt b/rootdir/etc/ld.config.txt
index 2ac54e9..84b308d 100644
--- a/rootdir/etc/ld.config.txt
+++ b/rootdir/etc/ld.config.txt
@@ -182,6 +182,7 @@
 namespace.media.links = default
 namespace.media.link.default.shared_libs  = %LLNDK_LIBRARIES%
 namespace.media.link.default.shared_libs += libbinder_ndk.so
+namespace.media.link.default.shared_libs += libcgrouprc.so
 namespace.media.link.default.shared_libs += libmediametrics.so
 namespace.media.link.default.shared_libs += %SANITIZER_RUNTIME_LIBRARIES%
 
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 1b7367c..893998c 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -345,8 +345,11 @@
     trigger early-boot
     trigger boot
 
-on post-fs
+on early-fs
+    # Once metadata has been mounted, we'll need vold to deal with userdata checkpointing
     start vold
+
+on post-fs
     exec - system system -- /system/bin/vdc checkpoint markBootAttempt
 
     # Once everything is setup, no need to modify /.