Merge "[NETD-BPF#11] libgpumem includes WaitForProgsLoaded.h"
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
index eb9a51d..7ef26bf 100644
--- a/PREUPLOAD.cfg
+++ b/PREUPLOAD.cfg
@@ -6,6 +6,7 @@
 # Only turn on clang-format check for the following subfolders.
 clang_format = --commit ${PREUPLOAD_COMMIT} --style file --extensions c,h,cc,cpp
                cmds/idlcli/
+               cmds/installd/
                cmds/servicemanager/
                include/input/
                include/powermanager/
diff --git a/cmds/atrace/atrace.cpp b/cmds/atrace/atrace.cpp
index 783a475..6459443 100644
--- a/cmds/atrace/atrace.cpp
+++ b/cmds/atrace/atrace.cpp
@@ -239,7 +239,7 @@
     } },
     { "memory",  "Memory", 0, {
         { OPT,      "events/mm_event/mm_event_record/enable" },
-        { OPT,      "events/kmem/rss_stat/enable" },
+        { OPT,      "events/synthetic/rss_stat_throttled/enable" },
         { OPT,      "events/kmem/ion_heap_grow/enable" },
         { OPT,      "events/kmem/ion_heap_shrink/enable" },
         { OPT,      "events/ion/ion_stat/enable" },
diff --git a/cmds/dumpstate/Android.bp b/cmds/dumpstate/Android.bp
index 74dbf4b..a2491e5 100644
--- a/cmds/dumpstate/Android.bp
+++ b/cmds/dumpstate/Android.bp
@@ -86,9 +86,11 @@
     shared_libs: [
         "android.hardware.dumpstate@1.0",
         "android.hardware.dumpstate@1.1",
+        "android.hardware.dumpstate-V1-ndk",
         "libziparchive",
         "libbase",
         "libbinder",
+        "libbinder_ndk",
         "libcrypto",
         "libcutils",
         "libdebuggerd_client",
diff --git a/cmds/dumpstate/DumpstateService.cpp b/cmds/dumpstate/DumpstateService.cpp
index ba25a5a..77915d5 100644
--- a/cmds/dumpstate/DumpstateService.cpp
+++ b/cmds/dumpstate/DumpstateService.cpp
@@ -192,7 +192,7 @@
     dprintf(fd, "progress:\n");
     ds_->progress_->Dump(fd, "  ");
     dprintf(fd, "args: %s\n", ds_->options_->args.c_str());
-    dprintf(fd, "bugreport_mode: %s\n", ds_->options_->bugreport_mode.c_str());
+    dprintf(fd, "bugreport_mode: %s\n", ds_->options_->bugreport_mode_string.c_str());
     dprintf(fd, "version: %s\n", ds_->version_.c_str());
     dprintf(fd, "bugreport_dir: %s\n", destination.c_str());
     dprintf(fd, "screenshot_path: %s\n", ds_->screenshot_path_.c_str());
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index eab72f4..32e680d 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -57,12 +57,15 @@
 #include <utility>
 #include <vector>
 
+#include <aidl/android/hardware/dumpstate/IDumpstateDevice.h>
 #include <android-base/file.h>
 #include <android-base/properties.h>
 #include <android-base/scopeguard.h>
 #include <android-base/stringprintf.h>
 #include <android-base/strings.h>
 #include <android-base/unique_fd.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
 #include <android/content/pm/IPackageManagerNative.h>
 #include <android/hardware/dumpstate/1.0/IDumpstateDevice.h>
 #include <android/hardware/dumpstate/1.1/IDumpstateDevice.h>
@@ -89,11 +92,10 @@
 #include "DumpstateService.h"
 #include "dumpstate.h"
 
-using IDumpstateDevice_1_0 = ::android::hardware::dumpstate::V1_0::IDumpstateDevice;
-using IDumpstateDevice_1_1 = ::android::hardware::dumpstate::V1_1::IDumpstateDevice;
-using ::android::hardware::dumpstate::V1_1::DumpstateMode;
-using ::android::hardware::dumpstate::V1_1::DumpstateStatus;
-using ::android::hardware::dumpstate::V1_1::toString;
+namespace dumpstate_hal_hidl_1_0 = android::hardware::dumpstate::V1_0;
+namespace dumpstate_hal_hidl = android::hardware::dumpstate::V1_1;
+namespace dumpstate_hal_aidl = aidl::android::hardware::dumpstate;
+
 using ::std::literals::chrono_literals::operator""ms;
 using ::std::literals::chrono_literals::operator""s;
 using ::std::placeholders::_1;
@@ -807,7 +809,7 @@
     printf("Bugreport format version: %s\n", version_.c_str());
     printf("Dumpstate info: id=%d pid=%d dry_run=%d parallel_run=%d args=%s bugreport_mode=%s\n",
            id_, pid_, PropertiesHelper::IsDryRun(), PropertiesHelper::IsParallelRun(),
-           options_->args.c_str(), options_->bugreport_mode.c_str());
+           options_->args.c_str(), options_->bugreport_mode_string.c_str());
     printf("\n");
 }
 
@@ -2199,6 +2201,194 @@
     return RunStatus::OK;
 }
 
+static dumpstate_hal_hidl::DumpstateMode GetDumpstateHalModeHidl(
+    const Dumpstate::BugreportMode bugreport_mode) {
+    switch (bugreport_mode) {
+        case Dumpstate::BugreportMode::BUGREPORT_FULL:
+            return dumpstate_hal_hidl::DumpstateMode::FULL;
+        case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
+            return dumpstate_hal_hidl::DumpstateMode::INTERACTIVE;
+        case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
+            return dumpstate_hal_hidl::DumpstateMode::REMOTE;
+        case Dumpstate::BugreportMode::BUGREPORT_WEAR:
+            return dumpstate_hal_hidl::DumpstateMode::WEAR;
+        case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
+            return dumpstate_hal_hidl::DumpstateMode::CONNECTIVITY;
+        case Dumpstate::BugreportMode::BUGREPORT_WIFI:
+            return dumpstate_hal_hidl::DumpstateMode::WIFI;
+        case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
+            return dumpstate_hal_hidl::DumpstateMode::DEFAULT;
+    }
+    return dumpstate_hal_hidl::DumpstateMode::DEFAULT;
+}
+
+static dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode GetDumpstateHalModeAidl(
+    const Dumpstate::BugreportMode bugreport_mode) {
+    switch (bugreport_mode) {
+        case Dumpstate::BugreportMode::BUGREPORT_FULL:
+            return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::FULL;
+        case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
+            return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::INTERACTIVE;
+        case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
+            return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::REMOTE;
+        case Dumpstate::BugreportMode::BUGREPORT_WEAR:
+            return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::WEAR;
+        case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
+            return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::CONNECTIVITY;
+        case Dumpstate::BugreportMode::BUGREPORT_WIFI:
+            return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::WIFI;
+        case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
+            return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::DEFAULT;
+    }
+    return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::DEFAULT;
+}
+
+static void DoDumpstateBoardHidl(
+    const sp<dumpstate_hal_hidl_1_0::IDumpstateDevice> dumpstate_hal_1_0,
+    const std::vector<::ndk::ScopedFileDescriptor>& dumpstate_fds,
+    const Dumpstate::BugreportMode bugreport_mode,
+    const size_t timeout_sec) {
+
+    using ScopedNativeHandle =
+        std::unique_ptr<native_handle_t, std::function<void(native_handle_t*)>>;
+    ScopedNativeHandle handle(native_handle_create(static_cast<int>(dumpstate_fds.size()), 0),
+                              [](native_handle_t* handle) {
+                                  // we don't close file handle's here
+                                  // via native_handle_close(handle)
+                                  // instead we let dumpstate_fds close the file handles when
+                                  // dumpstate_fds gets destroyed
+                                  native_handle_delete(handle);
+                              });
+    if (handle == nullptr) {
+        MYLOGE("Could not create native_handle for dumpstate HAL\n");
+        return;
+    }
+
+    for (size_t i = 0; i < dumpstate_fds.size(); i++) {
+        handle.get()->data[i] = dumpstate_fds[i].get();
+    }
+
+    // Prefer version 1.1 if available. New devices launching with R are no longer allowed to
+    // implement just 1.0.
+    const char* descriptor_to_kill;
+    using DumpstateBoardTask = std::packaged_task<bool()>;
+    DumpstateBoardTask dumpstate_board_task;
+    sp<dumpstate_hal_hidl::IDumpstateDevice> dumpstate_hal(
+        dumpstate_hal_hidl::IDumpstateDevice::castFrom(dumpstate_hal_1_0));
+    if (dumpstate_hal != nullptr) {
+        MYLOGI("Using IDumpstateDevice v1.1 HIDL HAL");
+
+        dumpstate_hal_hidl::DumpstateMode dumpstate_hal_mode =
+            GetDumpstateHalModeHidl(bugreport_mode);
+
+        descriptor_to_kill = dumpstate_hal_hidl::IDumpstateDevice::descriptor;
+        dumpstate_board_task =
+            DumpstateBoardTask([timeout_sec, dumpstate_hal_mode, dumpstate_hal, &handle]() -> bool {
+                ::android::hardware::Return<dumpstate_hal_hidl::DumpstateStatus> status =
+                    dumpstate_hal->dumpstateBoard_1_1(handle.get(), dumpstate_hal_mode,
+                                                      SEC_TO_MSEC(timeout_sec));
+                if (!status.isOk()) {
+                    MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str());
+                    return false;
+                } else if (status != dumpstate_hal_hidl::DumpstateStatus::OK) {
+                    MYLOGE("dumpstateBoard failed with DumpstateStatus::%s\n",
+                           dumpstate_hal_hidl::toString(status).c_str());
+                    return false;
+                }
+                return true;
+            });
+    } else {
+        MYLOGI("Using IDumpstateDevice v1.0 HIDL HAL");
+
+        descriptor_to_kill = dumpstate_hal_hidl_1_0::IDumpstateDevice::descriptor;
+        dumpstate_board_task = DumpstateBoardTask([dumpstate_hal_1_0, &handle]() -> bool {
+            ::android::hardware::Return<void> status =
+                dumpstate_hal_1_0->dumpstateBoard(handle.get());
+            if (!status.isOk()) {
+                MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str());
+                return false;
+            }
+            return true;
+        });
+    }
+    auto result = dumpstate_board_task.get_future();
+    std::thread(std::move(dumpstate_board_task)).detach();
+
+    if (result.wait_for(std::chrono::seconds(timeout_sec)) != std::future_status::ready) {
+        MYLOGE("dumpstateBoard timed out after %zus, killing dumpstate HAL\n", timeout_sec);
+        if (!android::base::SetProperty(
+                "ctl.interface_restart",
+                android::base::StringPrintf("%s/default", descriptor_to_kill))) {
+            MYLOGE("Couldn't restart dumpstate HAL\n");
+        }
+    }
+    // Wait some time for init to kill dumpstate vendor HAL
+    constexpr size_t killing_timeout_sec = 10;
+    if (result.wait_for(std::chrono::seconds(killing_timeout_sec)) != std::future_status::ready) {
+        MYLOGE(
+            "killing dumpstateBoard timed out after %zus, continue and "
+            "there might be racing in content\n",
+            killing_timeout_sec);
+    }
+}
+
+static void DoDumpstateBoardAidl(
+    const std::shared_ptr<dumpstate_hal_aidl::IDumpstateDevice> dumpstate_hal,
+    const std::vector<::ndk::ScopedFileDescriptor>& dumpstate_fds,
+    const Dumpstate::BugreportMode bugreport_mode, const size_t timeout_sec) {
+    MYLOGI("Using IDumpstateDevice AIDL HAL");
+
+    const char* descriptor_to_kill;
+    using DumpstateBoardTask = std::packaged_task<bool()>;
+    DumpstateBoardTask dumpstate_board_task;
+    dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode dumpstate_hal_mode =
+        GetDumpstateHalModeAidl(bugreport_mode);
+
+    descriptor_to_kill = dumpstate_hal_aidl::IDumpstateDevice::descriptor;
+    dumpstate_board_task = DumpstateBoardTask([dumpstate_hal, &dumpstate_fds, dumpstate_hal_mode,
+                                               timeout_sec]() -> bool {
+        auto status = dumpstate_hal->dumpstateBoard(dumpstate_fds, dumpstate_hal_mode, timeout_sec);
+
+        if (!status.isOk()) {
+            MYLOGE("dumpstateBoard failed: %s\n", status.getDescription().c_str());
+            return false;
+        }
+        return true;
+    });
+    auto result = dumpstate_board_task.get_future();
+    std::thread(std::move(dumpstate_board_task)).detach();
+
+    if (result.wait_for(std::chrono::seconds(timeout_sec)) != std::future_status::ready) {
+        MYLOGE("dumpstateBoard timed out after %zus, killing dumpstate HAL\n", timeout_sec);
+        if (!android::base::SetProperty(
+                "ctl.interface_restart",
+                android::base::StringPrintf("%s/default", descriptor_to_kill))) {
+            MYLOGE("Couldn't restart dumpstate HAL\n");
+        }
+    }
+    // Wait some time for init to kill dumpstate vendor HAL
+    constexpr size_t killing_timeout_sec = 10;
+    if (result.wait_for(std::chrono::seconds(killing_timeout_sec)) != std::future_status::ready) {
+        MYLOGE(
+            "killing dumpstateBoard timed out after %zus, continue and "
+            "there might be racing in content\n",
+            killing_timeout_sec);
+    }
+}
+
+static std::shared_ptr<dumpstate_hal_aidl::IDumpstateDevice> GetDumpstateBoardAidlService() {
+    const std::string aidl_instance_name =
+        std::string(dumpstate_hal_aidl::IDumpstateDevice::descriptor) + "/default";
+
+    if (!AServiceManager_isDeclared(aidl_instance_name.c_str())) {
+        return nullptr;
+    }
+
+    ndk::SpAIBinder dumpstateBinder(AServiceManager_waitForService(aidl_instance_name.c_str()));
+
+    return dumpstate_hal_aidl::IDumpstateDevice::fromBinder(dumpstateBinder);
+}
+
 void Dumpstate::DumpstateBoard(int out_fd) {
     dprintf(out_fd, "========================================================\n");
     dprintf(out_fd, "== Board\n");
@@ -2220,8 +2410,7 @@
     if (mount_debugfs) {
         RunCommand("mount debugfs", {"mount", "-t", "debugfs", "debugfs", "/sys/kernel/debug"},
                    AS_ROOT_20);
-        RunCommand("chmod debugfs", {"chmod", "0755", "/sys/kernel/debug"},
-                   AS_ROOT_20);
+        RunCommand("chmod debugfs", {"chmod", "0755", "/sys/kernel/debug"}, AS_ROOT_20);
     }
 
     std::vector<std::string> paths;
@@ -2233,23 +2422,31 @@
             std::bind([](std::string path) { android::os::UnlinkAndLogOnError(path); }, paths[i])));
     }
 
-    sp<IDumpstateDevice_1_0> dumpstate_device_1_0(IDumpstateDevice_1_0::getService());
-    if (dumpstate_device_1_0 == nullptr) {
-        MYLOGE("No IDumpstateDevice implementation\n");
+    // get dumpstate HAL AIDL implementation
+    std::shared_ptr<dumpstate_hal_aidl::IDumpstateDevice> dumpstate_hal_handle_aidl(
+        GetDumpstateBoardAidlService());
+    if (dumpstate_hal_handle_aidl == nullptr) {
+        MYLOGI("No IDumpstateDevice AIDL implementation\n");
+    }
+
+    // get dumpstate HAL HIDL implementation, only if AIDL HAL implementation not found
+    sp<dumpstate_hal_hidl_1_0::IDumpstateDevice> dumpstate_hal_handle_hidl_1_0 = nullptr;
+    if (dumpstate_hal_handle_aidl == nullptr) {
+        dumpstate_hal_handle_hidl_1_0 = dumpstate_hal_hidl_1_0::IDumpstateDevice::getService();
+        if (dumpstate_hal_handle_hidl_1_0 == nullptr) {
+            MYLOGI("No IDumpstateDevice HIDL implementation\n");
+        }
+    }
+
+    // if neither HIDL nor AIDL implementation found, then return
+    if (dumpstate_hal_handle_hidl_1_0 == nullptr && dumpstate_hal_handle_aidl == nullptr) {
+        MYLOGE("Could not find IDumpstateDevice implementation\n");
         return;
     }
 
-    using ScopedNativeHandle =
-            std::unique_ptr<native_handle_t, std::function<void(native_handle_t*)>>;
-    ScopedNativeHandle handle(native_handle_create(static_cast<int>(paths.size()), 0),
-                              [](native_handle_t* handle) {
-                                  native_handle_close(handle);
-                                  native_handle_delete(handle);
-                              });
-    if (handle == nullptr) {
-        MYLOGE("Could not create native_handle\n");
-        return;
-    }
+    // this is used to hold the file descriptors and when this variable goes out of scope
+    // the file descriptors are closed
+    std::vector<::ndk::ScopedFileDescriptor> dumpstate_fds;
 
     // TODO(128270426): Check for consent in between?
     for (size_t i = 0; i < paths.size(); i++) {
@@ -2262,65 +2459,26 @@
             MYLOGE("Could not open file %s: %s\n", paths[i].c_str(), strerror(errno));
             return;
         }
-        handle.get()->data[i] = fd.release();
+
+        dumpstate_fds.emplace_back(fd.release());
+        // we call fd.release() here to make sure "fd" does not get closed
+        // after "fd" goes out of scope after this block.
+        // "fd" will be closed when "dumpstate_fds" goes out of scope
+        // i.e. when we exit this function
     }
 
     // Given that bugreport is required to diagnose failures, it's better to set an arbitrary amount
     // of timeout for IDumpstateDevice than to block the rest of bugreport. In the timeout case, we
     // will kill the HAL and grab whatever it dumped in time.
     constexpr size_t timeout_sec = 30;
-    // Prefer version 1.1 if available. New devices launching with R are no longer allowed to
-    // implement just 1.0.
-    const char* descriptor_to_kill;
-    using DumpstateBoardTask = std::packaged_task<bool()>;
-    DumpstateBoardTask dumpstate_board_task;
-    sp<IDumpstateDevice_1_1> dumpstate_device_1_1(
-        IDumpstateDevice_1_1::castFrom(dumpstate_device_1_0));
-    if (dumpstate_device_1_1 != nullptr) {
-        MYLOGI("Using IDumpstateDevice v1.1");
-        descriptor_to_kill = IDumpstateDevice_1_1::descriptor;
-        dumpstate_board_task = DumpstateBoardTask([this, dumpstate_device_1_1, &handle]() -> bool {
-            ::android::hardware::Return<DumpstateStatus> status =
-                dumpstate_device_1_1->dumpstateBoard_1_1(handle.get(), options_->dumpstate_hal_mode,
-                                                         SEC_TO_MSEC(timeout_sec));
-            if (!status.isOk()) {
-                MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str());
-                return false;
-            } else if (status != DumpstateStatus::OK) {
-                MYLOGE("dumpstateBoard failed with DumpstateStatus::%s\n", toString(status).c_str());
-                return false;
-            }
-            return true;
-        });
-    } else {
-        MYLOGI("Using IDumpstateDevice v1.0");
-        descriptor_to_kill = IDumpstateDevice_1_0::descriptor;
-        dumpstate_board_task = DumpstateBoardTask([dumpstate_device_1_0, &handle]() -> bool {
-            ::android::hardware::Return<void> status =
-                dumpstate_device_1_0->dumpstateBoard(handle.get());
-            if (!status.isOk()) {
-                MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str());
-                return false;
-            }
-            return true;
-        });
-    }
-    auto result = dumpstate_board_task.get_future();
-    std::thread(std::move(dumpstate_board_task)).detach();
 
-    if (result.wait_for(std::chrono::seconds(timeout_sec)) != std::future_status::ready) {
-        MYLOGE("dumpstateBoard timed out after %zus, killing dumpstate vendor HAL\n", timeout_sec);
-        if (!android::base::SetProperty(
-                "ctl.interface_restart",
-                android::base::StringPrintf("%s/default", descriptor_to_kill))) {
-            MYLOGE("Couldn't restart dumpstate HAL\n");
-        }
-    }
-    // Wait some time for init to kill dumpstate vendor HAL
-    constexpr size_t killing_timeout_sec = 10;
-    if (result.wait_for(std::chrono::seconds(killing_timeout_sec)) != std::future_status::ready) {
-        MYLOGE("killing dumpstateBoard timed out after %zus, continue and "
-               "there might be racing in content\n", killing_timeout_sec);
+    if (dumpstate_hal_handle_aidl != nullptr) {
+        DoDumpstateBoardAidl(dumpstate_hal_handle_aidl, dumpstate_fds, options_->bugreport_mode,
+                             timeout_sec);
+    } else if (dumpstate_hal_handle_hidl_1_0 != nullptr) {
+        // run HIDL HAL only if AIDL HAL not found
+        DoDumpstateBoardHidl(dumpstate_hal_handle_hidl_1_0, dumpstate_fds, options_->bugreport_mode,
+                             timeout_sec);
     }
 
     if (mount_debugfs) {
@@ -2333,9 +2491,8 @@
     auto file_sizes = std::make_unique<ssize_t[]>(paths.size());
     for (size_t i = 0; i < paths.size(); i++) {
         struct stat s;
-        if (fstat(handle.get()->data[i], &s) == -1) {
-            MYLOGE("Failed to fstat %s: %s\n", kDumpstateBoardFiles[i].c_str(),
-                   strerror(errno));
+        if (fstat(dumpstate_fds[i].get(), &s) == -1) {
+            MYLOGE("Failed to fstat %s: %s\n", kDumpstateBoardFiles[i].c_str(), strerror(errno));
             file_sizes[i] = -1;
             continue;
         }
@@ -2574,40 +2731,35 @@
                                bool is_screenshot_requested) {
     // Modify com.android.shell.BugreportProgressService#isDefaultScreenshotRequired as well for
     // default system screenshots.
-    options->bugreport_mode = ModeToString(mode);
+    options->bugreport_mode = mode;
+    options->bugreport_mode_string = ModeToString(mode);
     switch (mode) {
         case Dumpstate::BugreportMode::BUGREPORT_FULL:
             options->do_screenshot = is_screenshot_requested;
-            options->dumpstate_hal_mode = DumpstateMode::FULL;
             break;
         case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
             // Currently, the dumpstate binder is only used by Shell to update progress.
             options->do_progress_updates = true;
             options->do_screenshot = is_screenshot_requested;
-            options->dumpstate_hal_mode = DumpstateMode::INTERACTIVE;
             break;
         case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
             options->do_vibrate = false;
             options->is_remote_mode = true;
             options->do_screenshot = false;
-            options->dumpstate_hal_mode = DumpstateMode::REMOTE;
             break;
         case Dumpstate::BugreportMode::BUGREPORT_WEAR:
             options->do_progress_updates = true;
             options->do_screenshot = is_screenshot_requested;
-            options->dumpstate_hal_mode = DumpstateMode::WEAR;
             break;
         // TODO(b/148168577) rename TELEPHONY everywhere to CONNECTIVITY.
         case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
             options->telephony_only = true;
             options->do_progress_updates = true;
             options->do_screenshot = false;
-            options->dumpstate_hal_mode = DumpstateMode::CONNECTIVITY;
             break;
         case Dumpstate::BugreportMode::BUGREPORT_WIFI:
             options->wifi_only = true;
             options->do_screenshot = false;
-            options->dumpstate_hal_mode = DumpstateMode::WIFI;
             break;
         case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
             break;
@@ -2618,13 +2770,14 @@
     MYLOGI(
         "do_vibrate: %d stream_to_socket: %d progress_updates_to_socket: %d do_screenshot: %d "
         "is_remote_mode: %d show_header_only: %d telephony_only: %d "
-        "wifi_only: %d do_progress_updates: %d fd: %d bugreport_mode: %s dumpstate_hal_mode: %s "
+        "wifi_only: %d do_progress_updates: %d fd: %d bugreport_mode: %s "
         "limited_only: %d args: %s\n",
         options.do_vibrate, options.stream_to_socket, options.progress_updates_to_socket,
         options.do_screenshot, options.is_remote_mode, options.show_header_only,
         options.telephony_only, options.wifi_only,
-        options.do_progress_updates, options.bugreport_fd.get(), options.bugreport_mode.c_str(),
-        toString(options.dumpstate_hal_mode).c_str(), options.limited_only, options.args.c_str());
+        options.do_progress_updates, options.bugreport_fd.get(),
+        options.bugreport_mode_string.c_str(),
+        options.limited_only, options.args.c_str());
 }
 
 void Dumpstate::DumpOptions::Initialize(BugreportMode bugreport_mode,
@@ -2838,7 +2991,7 @@
     }
 
     MYLOGI("dumpstate info: id=%d, args='%s', bugreport_mode= %s bugreport format version: %s\n",
-           id_, options_->args.c_str(), options_->bugreport_mode.c_str(), version_.c_str());
+           id_, options_->args.c_str(), options_->bugreport_mode_string.c_str(), version_.c_str());
 
     do_early_screenshot_ = options_->do_progress_updates;
 
diff --git a/cmds/dumpstate/dumpstate.h b/cmds/dumpstate/dumpstate.h
index 3722383..773e292 100644
--- a/cmds/dumpstate/dumpstate.h
+++ b/cmds/dumpstate/dumpstate.h
@@ -25,6 +25,7 @@
 #include <string>
 #include <vector>
 
+#include <aidl/android/hardware/dumpstate/IDumpstateDevice.h>
 #include <android-base/macros.h>
 #include <android-base/unique_fd.h>
 #include <android/hardware/dumpstate/1.1/types.h>
@@ -400,19 +401,18 @@
         bool limited_only = false;
         // Whether progress updates should be published.
         bool do_progress_updates = false;
-        // The mode we'll use when calling IDumpstateDevice::dumpstateBoard.
+        // this is used to derive dumpstate HAL bug report mode
         // TODO(b/148168577) get rid of the AIDL values, replace them with the HAL values instead.
         // The HAL is actually an API surface that can be validated, while the AIDL is not (@hide).
-        ::android::hardware::dumpstate::V1_1::DumpstateMode dumpstate_hal_mode =
-            ::android::hardware::dumpstate::V1_1::DumpstateMode::DEFAULT;
+        BugreportMode bugreport_mode = Dumpstate::BugreportMode::BUGREPORT_DEFAULT;
         // File descriptor to output zip file. Takes precedence over out_dir.
         android::base::unique_fd bugreport_fd;
         // File descriptor to screenshot file.
         android::base::unique_fd screenshot_fd;
         // Custom output directory.
         std::string out_dir;
-        // Bugreport mode of the bugreport.
-        std::string bugreport_mode;
+        // Bugreport mode of the bugreport as a string
+        std::string bugreport_mode_string;
         // Command-line arguments as string
         std::string args;
         // Notification title and description
diff --git a/cmds/dumpstate/tests/dumpstate_test.cpp b/cmds/dumpstate/tests/dumpstate_test.cpp
index db508b5..42beb2b 100644
--- a/cmds/dumpstate/tests/dumpstate_test.cpp
+++ b/cmds/dumpstate/tests/dumpstate_test.cpp
@@ -33,6 +33,7 @@
 #include <unistd.h>
 #include <thread>
 
+#include <aidl/android/hardware/dumpstate/IDumpstateDevice.h>
 #include <android-base/file.h>
 #include <android-base/properties.h>
 #include <android-base/stringprintf.h>
@@ -47,6 +48,7 @@
 namespace os {
 namespace dumpstate {
 
+using DumpstateDeviceAidl = ::aidl::android::hardware::dumpstate::IDumpstateDevice;
 using ::android::hardware::dumpstate::V1_1::DumpstateMode;
 using ::testing::EndsWith;
 using ::testing::Eq;
@@ -186,7 +188,6 @@
     EXPECT_FALSE(options_.do_progress_updates);
     EXPECT_FALSE(options_.is_remote_mode);
     EXPECT_FALSE(options_.limited_only);
-    EXPECT_EQ(options_.dumpstate_hal_mode, DumpstateMode::DEFAULT);
 }
 
 TEST_F(DumpOptionsTest, InitializeAdbBugreport) {
@@ -210,7 +211,6 @@
     EXPECT_FALSE(options_.is_remote_mode);
     EXPECT_FALSE(options_.stream_to_socket);
     EXPECT_FALSE(options_.limited_only);
-    EXPECT_EQ(options_.dumpstate_hal_mode, DumpstateMode::DEFAULT);
 }
 
 TEST_F(DumpOptionsTest, InitializeAdbShellBugreport) {
@@ -234,13 +234,11 @@
     EXPECT_FALSE(options_.do_progress_updates);
     EXPECT_FALSE(options_.is_remote_mode);
     EXPECT_FALSE(options_.limited_only);
-    EXPECT_EQ(options_.dumpstate_hal_mode, DumpstateMode::DEFAULT);
 }
 
 TEST_F(DumpOptionsTest, InitializeFullBugReport) {
     options_.Initialize(Dumpstate::BugreportMode::BUGREPORT_FULL, fd, fd, true);
     EXPECT_TRUE(options_.do_screenshot);
-    EXPECT_EQ(options_.dumpstate_hal_mode, DumpstateMode::FULL);
 
     // Other options retain default values
     EXPECT_TRUE(options_.do_vibrate);
@@ -256,7 +254,6 @@
     options_.Initialize(Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE, fd, fd, true);
     EXPECT_TRUE(options_.do_progress_updates);
     EXPECT_TRUE(options_.do_screenshot);
-    EXPECT_EQ(options_.dumpstate_hal_mode, DumpstateMode::INTERACTIVE);
 
     // Other options retain default values
     EXPECT_TRUE(options_.do_vibrate);
@@ -272,7 +269,6 @@
     EXPECT_TRUE(options_.is_remote_mode);
     EXPECT_FALSE(options_.do_vibrate);
     EXPECT_FALSE(options_.do_screenshot);
-    EXPECT_EQ(options_.dumpstate_hal_mode, DumpstateMode::REMOTE);
 
     // Other options retain default values
     EXPECT_FALSE(options_.progress_updates_to_socket);
@@ -286,7 +282,7 @@
     options_.Initialize(Dumpstate::BugreportMode::BUGREPORT_WEAR, fd, fd, true);
     EXPECT_TRUE(options_.do_screenshot);
     EXPECT_TRUE(options_.do_progress_updates);
-    EXPECT_EQ(options_.dumpstate_hal_mode, DumpstateMode::WEAR);
+
 
     // Other options retain default values
     EXPECT_TRUE(options_.do_vibrate);
@@ -302,7 +298,6 @@
     EXPECT_FALSE(options_.do_screenshot);
     EXPECT_TRUE(options_.telephony_only);
     EXPECT_TRUE(options_.do_progress_updates);
-    EXPECT_EQ(options_.dumpstate_hal_mode, DumpstateMode::CONNECTIVITY);
 
     // Other options retain default values
     EXPECT_TRUE(options_.do_vibrate);
@@ -317,7 +312,6 @@
     options_.Initialize(Dumpstate::BugreportMode::BUGREPORT_WIFI, fd, fd, false);
     EXPECT_FALSE(options_.do_screenshot);
     EXPECT_TRUE(options_.wifi_only);
-    EXPECT_EQ(options_.dumpstate_hal_mode, DumpstateMode::WIFI);
 
     // Other options retain default values
     EXPECT_TRUE(options_.do_vibrate);
@@ -354,7 +348,6 @@
     EXPECT_FALSE(options_.do_progress_updates);
     EXPECT_FALSE(options_.is_remote_mode);
     EXPECT_FALSE(options_.stream_to_socket);
-    EXPECT_EQ(options_.dumpstate_hal_mode, DumpstateMode::DEFAULT);
 }
 
 TEST_F(DumpOptionsTest, InitializeDefaultBugReport) {
@@ -371,7 +364,6 @@
 
     EXPECT_EQ(status, Dumpstate::RunStatus::OK);
     EXPECT_TRUE(options_.do_screenshot);
-    EXPECT_EQ(options_.dumpstate_hal_mode, DumpstateMode::DEFAULT);
 
     // Other options retain default values
     EXPECT_TRUE(options_.do_vibrate);
@@ -408,7 +400,6 @@
     EXPECT_FALSE(options_.do_progress_updates);
     EXPECT_FALSE(options_.is_remote_mode);
     EXPECT_FALSE(options_.limited_only);
-    EXPECT_EQ(options_.dumpstate_hal_mode, DumpstateMode::DEFAULT);
 }
 
 TEST_F(DumpOptionsTest, InitializePartial2) {
@@ -436,7 +427,6 @@
     EXPECT_FALSE(options_.stream_to_socket);
     EXPECT_FALSE(options_.progress_updates_to_socket);
     EXPECT_FALSE(options_.limited_only);
-    EXPECT_EQ(options_.dumpstate_hal_mode, DumpstateMode::DEFAULT);
 }
 
 TEST_F(DumpOptionsTest, InitializeHelp) {
diff --git a/cmds/installd/Android.bp b/cmds/installd/Android.bp
index 3f180d9..faa8485 100644
--- a/cmds/installd/Android.bp
+++ b/cmds/installd/Android.bp
@@ -45,6 +45,7 @@
         "libprocessgroup",
         "libselinux",
         "libutils",
+        "libziparchive",
         "server_configurable_flags",
     ],
     static_libs: [
@@ -267,6 +268,7 @@
         "libprocessgroup",
         "libselinux",
         "libutils",
+        "libziparchive",
         "server_configurable_flags",
     ],
 }
diff --git a/cmds/installd/CacheItem.cpp b/cmds/installd/CacheItem.cpp
index e29ff4c..27690a3 100644
--- a/cmds/installd/CacheItem.cpp
+++ b/cmds/installd/CacheItem.cpp
@@ -116,6 +116,7 @@
                 break;
             }
         }
+	fts_close(fts);
     } else {
         if (tombstone) {
             if (truncate(path.c_str(), 0) != 0) {
diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp
index 39ef0b5..373a70a 100644
--- a/cmds/installd/InstalldNativeService.cpp
+++ b/cmds/installd/InstalldNativeService.cpp
@@ -77,6 +77,8 @@
 #define LOG_TAG "installd"
 #endif
 
+// #define GRANULAR_LOCKS
+
 using android::base::ParseUint;
 using android::base::StringPrintf;
 using std::endl;
@@ -265,6 +267,104 @@
     }                                                       \
 }
 
+#ifdef GRANULAR_LOCKS
+
+/**
+ * This class obtains in constructor and keeps the local strong pointer to the RefLock.
+ * On destruction, it checks if there are any other strong pointers, and remove the map entry if
+ * this was the last one.
+ */
+template <class Key, class Mutex>
+struct LocalLockHolder {
+    using WeakPointer = std::weak_ptr<Mutex>;
+    using StrongPointer = std::shared_ptr<Mutex>;
+    using Map = std::unordered_map<Key, WeakPointer>;
+    using MapLock = std::recursive_mutex;
+
+    LocalLockHolder(Key key, Map& map, MapLock& mapLock)
+          : mKey(std::move(key)), mMap(map), mMapLock(mapLock) {
+        std::lock_guard lock(mMapLock);
+        auto& weakPtr = mMap[mKey];
+
+        // Check if the RefLock is still alive.
+        mRefLock = weakPtr.lock();
+        if (!mRefLock) {
+            // Create a new lock.
+            mRefLock = std::make_shared<Mutex>();
+            weakPtr = mRefLock;
+        }
+    }
+    LocalLockHolder(LocalLockHolder&& other) noexcept
+          : mKey(std::move(other.mKey)),
+            mMap(other.mMap),
+            mMapLock(other.mMapLock),
+            mRefLock(std::move(other.mRefLock)) {
+        other.mRefLock.reset();
+    }
+    ~LocalLockHolder() {
+        if (!mRefLock) {
+            return;
+        }
+
+        std::lock_guard lock(mMapLock);
+        // Clear the strong pointer.
+        mRefLock.reset();
+        auto found = mMap.find(mKey);
+        if (found == mMap.end()) {
+            return;
+        }
+        const auto& weakPtr = found->second;
+        // If this was the last pointer then it's ok to remove the map entry.
+        if (weakPtr.expired()) {
+            mMap.erase(found);
+        }
+    }
+
+    void lock() { mRefLock->lock(); }
+    void unlock() { mRefLock->unlock(); }
+    void lock_shared() { mRefLock->lock_shared(); }
+    void unlock_shared() { mRefLock->unlock_shared(); }
+
+private:
+    Key mKey;
+    Map& mMap;
+    MapLock& mMapLock;
+    StrongPointer mRefLock;
+};
+
+using UserLock = LocalLockHolder<userid_t, std::shared_mutex>;
+using UserWriteLockGuard = std::unique_lock<UserLock>;
+using UserReadLockGuard = std::shared_lock<UserLock>;
+
+using PackageLock = LocalLockHolder<std::string, std::recursive_mutex>;
+using PackageLockGuard = std::lock_guard<PackageLock>;
+
+#define LOCK_USER()                                     \
+    UserLock localUserLock(userId, mUserIdLock, mLock); \
+    UserWriteLockGuard userLock(localUserLock)
+
+#define LOCK_USER_READ()                                \
+    UserLock localUserLock(userId, mUserIdLock, mLock); \
+    UserReadLockGuard userLock(localUserLock)
+
+#define LOCK_PACKAGE()                                                  \
+    PackageLock localPackageLock(packageName, mPackageNameLock, mLock); \
+    PackageLockGuard packageLock(localPackageLock)
+
+#define LOCK_PACKAGE_USER() \
+    LOCK_USER_READ();       \
+    LOCK_PACKAGE()
+
+#else
+
+#define LOCK_USER() std::lock_guard lock(mLock)
+#define LOCK_PACKAGE() std::lock_guard lock(mLock)
+#define LOCK_PACKAGE_USER() \
+    (void)userId;           \
+    std::lock_guard lock(mLock)
+
+#endif // GRANULAR_LOCKS
+
 }  // namespace
 
 status_t InstalldNativeService::start() {
@@ -288,8 +388,6 @@
         return PERMISSION_DENIED;
     }
 
-    std::lock_guard<std::recursive_mutex> lock(mLock);
-
     {
         std::lock_guard<std::recursive_mutex> lock(mMountsLock);
         dprintf(fd, "Storage mounts:\n");
@@ -543,14 +641,13 @@
     return ok();
 }
 
-binder::Status InstalldNativeService::createAppData(const std::optional<std::string>& uuid,
-        const std::string& packageName, int32_t userId, int32_t flags, int32_t appId,
-        int32_t previousAppId, const std::string& seInfo, int32_t targetSdkVersion,
-        int64_t* _aidl_return) {
+binder::Status InstalldNativeService::createAppDataLocked(
+        const std::optional<std::string>& uuid, const std::string& packageName, int32_t userId,
+        int32_t flags, int32_t appId, int32_t previousAppId, const std::string& seInfo,
+        int32_t targetSdkVersion, int64_t* _aidl_return) {
     ENFORCE_UID(AID_SYSTEM);
     CHECK_ARGUMENT_UUID(uuid);
     CHECK_ARGUMENT_PACKAGE_NAME(packageName);
-    std::lock_guard<std::recursive_mutex> lock(mLock);
 
     const char* uuid_ = uuid ? uuid->c_str() : nullptr;
     const char* pkgname = packageName.c_str();
@@ -619,10 +716,22 @@
 }
 
 binder::Status InstalldNativeService::createAppData(
+        const std::optional<std::string>& uuid, const std::string& packageName, int32_t userId,
+        int32_t flags, int32_t appId, int32_t previousAppId, const std::string& seInfo,
+        int32_t targetSdkVersion, int64_t* _aidl_return) {
+    ENFORCE_UID(AID_SYSTEM);
+    CHECK_ARGUMENT_UUID(uuid);
+    CHECK_ARGUMENT_PACKAGE_NAME(packageName);
+    LOCK_PACKAGE_USER();
+    return createAppDataLocked(uuid, packageName, userId, flags, appId, previousAppId, seInfo,
+                               targetSdkVersion, _aidl_return);
+}
+
+binder::Status InstalldNativeService::createAppData(
         const android::os::CreateAppDataArgs& args,
         android::os::CreateAppDataResult* _aidl_return) {
     ENFORCE_UID(AID_SYSTEM);
-    std::lock_guard<std::recursive_mutex> lock(mLock);
+    // Locking is performed depeer in the callstack.
 
     int64_t ceDataInode = -1;
     auto status = createAppData(args.uuid, args.packageName, args.userId, args.flags, args.appId,
@@ -637,7 +746,7 @@
         const std::vector<android::os::CreateAppDataArgs>& args,
         std::vector<android::os::CreateAppDataResult>* _aidl_return) {
     ENFORCE_UID(AID_SYSTEM);
-    std::lock_guard<std::recursive_mutex> lock(mLock);
+    // Locking is performed depeer in the callstack.
 
     std::vector<android::os::CreateAppDataResult> results;
     for (const auto &arg : args) {
@@ -654,7 +763,7 @@
     ENFORCE_UID(AID_SYSTEM);
     CHECK_ARGUMENT_UUID(uuid);
     CHECK_ARGUMENT_PACKAGE_NAME(packageName);
-    std::lock_guard<std::recursive_mutex> lock(mLock);
+    LOCK_PACKAGE_USER();
 
     const char* uuid_ = uuid ? uuid->c_str() : nullptr;
     const char* pkgname = packageName.c_str();
@@ -698,7 +807,7 @@
         const std::string& profileName) {
     ENFORCE_UID(AID_SYSTEM);
     CHECK_ARGUMENT_PACKAGE_NAME(packageName);
-    std::lock_guard<std::recursive_mutex> lock(mLock);
+    LOCK_PACKAGE();
 
     binder::Status res = ok();
     if (!clear_primary_reference_profile(packageName, profileName)) {
@@ -715,7 +824,7 @@
     ENFORCE_UID(AID_SYSTEM);
     CHECK_ARGUMENT_UUID(uuid);
     CHECK_ARGUMENT_PACKAGE_NAME(packageName);
-    std::lock_guard<std::recursive_mutex> lock(mLock);
+    LOCK_PACKAGE_USER();
 
     const char* uuid_ = uuid ? uuid->c_str() : nullptr;
     const char* pkgname = packageName.c_str();
@@ -812,7 +921,7 @@
 binder::Status InstalldNativeService::destroyAppProfiles(const std::string& packageName) {
     ENFORCE_UID(AID_SYSTEM);
     CHECK_ARGUMENT_PACKAGE_NAME(packageName);
-    std::lock_guard<std::recursive_mutex> lock(mLock);
+    LOCK_PACKAGE();
 
     binder::Status res = ok();
     std::vector<userid_t> users = get_known_users(/*volume_uuid*/ nullptr);
@@ -832,7 +941,7 @@
     ENFORCE_UID(AID_SYSTEM);
     CHECK_ARGUMENT_UUID(uuid);
     CHECK_ARGUMENT_PACKAGE_NAME(packageName);
-    std::lock_guard<std::recursive_mutex> lock(mLock);
+    LOCK_PACKAGE_USER();
 
     const char* uuid_ = uuid ? uuid->c_str() : nullptr;
     const char* pkgname = packageName.c_str();
@@ -903,15 +1012,15 @@
         int32_t flags) {
     ENFORCE_UID(AID_SYSTEM);
     CHECK_ARGUMENT_UUID(uuid);
-    std::lock_guard<std::recursive_mutex> lock(mLock);
 
     const char* uuid_ = uuid ? uuid->c_str() : nullptr;
-    for (auto user : get_known_users(uuid_)) {
+    for (auto userId : get_known_users(uuid_)) {
+        LOCK_USER();
         ATRACE_BEGIN("fixup user");
         FTS* fts;
         FTSENT* p;
-        auto ce_path = create_data_user_ce_path(uuid_, user);
-        auto de_path = create_data_user_de_path(uuid_, user);
+        auto ce_path = create_data_user_ce_path(uuid_, userId);
+        auto de_path = create_data_user_de_path(uuid_, userId);
         char *argv[] = { (char*) ce_path.c_str(), (char*) de_path.c_str(), nullptr };
         if (!(fts = fts_open(argv, FTS_PHYSICAL | FTS_NOCHDIR | FTS_XDEV, nullptr))) {
             return error("Failed to fts_open");
@@ -1018,14 +1127,14 @@
     return logwrap_fork_execvp(ARRAY_SIZE(argv), argv, nullptr, false, LOG_ALOG, false, nullptr);
 }
 
-binder::Status InstalldNativeService::snapshotAppData(
-        const std::optional<std::string>& volumeUuid,
-        const std::string& packageName, int32_t user, int32_t snapshotId,
-        int32_t storageFlags, int64_t* _aidl_return) {
+binder::Status InstalldNativeService::snapshotAppData(const std::optional<std::string>& volumeUuid,
+                                                      const std::string& packageName,
+                                                      int32_t userId, int32_t snapshotId,
+                                                      int32_t storageFlags, int64_t* _aidl_return) {
     ENFORCE_UID(AID_SYSTEM);
     CHECK_ARGUMENT_UUID_IS_TEST_OR_NULL(volumeUuid);
     CHECK_ARGUMENT_PACKAGE_NAME(packageName);
-    std::lock_guard<std::recursive_mutex> lock(mLock);
+    LOCK_PACKAGE_USER();
 
     const char* volume_uuid = volumeUuid ? volumeUuid->c_str() : nullptr;
     const char* package_name = packageName.c_str();
@@ -1038,19 +1147,19 @@
     bool clear_ce_on_exit = false;
     bool clear_de_on_exit = false;
 
-    auto deleter = [&clear_ce_on_exit, &clear_de_on_exit, &volume_uuid, &user, &package_name,
-            &snapshotId] {
+    auto deleter = [&clear_ce_on_exit, &clear_de_on_exit, &volume_uuid, &userId, &package_name,
+                    &snapshotId] {
         if (clear_de_on_exit) {
-            auto to = create_data_misc_de_rollback_package_path(volume_uuid, user, snapshotId,
-                    package_name);
+            auto to = create_data_misc_de_rollback_package_path(volume_uuid, userId, snapshotId,
+                                                                package_name);
             if (delete_dir_contents(to.c_str(), 1, nullptr) != 0) {
                 LOG(WARNING) << "Failed to delete app data snapshot: " << to;
             }
         }
 
         if (clear_ce_on_exit) {
-            auto to = create_data_misc_ce_rollback_package_path(volume_uuid, user, snapshotId,
-                    package_name);
+            auto to = create_data_misc_ce_rollback_package_path(volume_uuid, userId, snapshotId,
+                                                                package_name);
             if (delete_dir_contents(to.c_str(), 1, nullptr) != 0) {
                 LOG(WARNING) << "Failed to delete app data snapshot: " << to;
             }
@@ -1060,10 +1169,11 @@
     auto scope_guard = android::base::make_scope_guard(deleter);
 
     if (storageFlags & FLAG_STORAGE_DE) {
-        auto from = create_data_user_de_package_path(volume_uuid, user, package_name);
-        auto to = create_data_misc_de_rollback_path(volume_uuid, user, snapshotId);
-        auto rollback_package_path = create_data_misc_de_rollback_package_path(volume_uuid, user,
-            snapshotId, package_name);
+        auto from = create_data_user_de_package_path(volume_uuid, userId, package_name);
+        auto to = create_data_misc_de_rollback_path(volume_uuid, userId, snapshotId);
+        auto rollback_package_path =
+                create_data_misc_de_rollback_package_path(volume_uuid, userId, snapshotId,
+                                                          package_name);
 
         int rc = create_dir_if_needed(to.c_str(), kRollbackFolderMode);
         if (rc != 0) {
@@ -1087,15 +1197,15 @@
     }
 
     // The app may not have any data at all, in which case it's OK to skip here.
-    auto from_ce = create_data_user_ce_package_path(volume_uuid, user, package_name);
+    auto from_ce = create_data_user_ce_package_path(volume_uuid, userId, package_name);
     if (access(from_ce.c_str(), F_OK) != 0) {
         LOG(INFO) << "Missing source " << from_ce;
         return ok();
     }
 
     // ce_data_inode is not needed when FLAG_CLEAR_CACHE_ONLY is set.
-    binder::Status clear_cache_result = clearAppData(volumeUuid, packageName, user,
-            storageFlags | FLAG_CLEAR_CACHE_ONLY, 0);
+    binder::Status clear_cache_result =
+            clearAppData(volumeUuid, packageName, userId, storageFlags | FLAG_CLEAR_CACHE_ONLY, 0);
     if (!clear_cache_result.isOk()) {
         // It should be fine to continue snapshot if we for some reason failed
         // to clear cache.
@@ -1103,8 +1213,9 @@
     }
 
     // ce_data_inode is not needed when FLAG_CLEAR_CODE_CACHE_ONLY is set.
-    binder::Status clear_code_cache_result = clearAppData(volumeUuid, packageName, user,
-            storageFlags | FLAG_CLEAR_CODE_CACHE_ONLY, 0);
+    binder::Status clear_code_cache_result =
+            clearAppData(volumeUuid, packageName, userId, storageFlags | FLAG_CLEAR_CODE_CACHE_ONLY,
+                         0);
     if (!clear_code_cache_result.isOk()) {
         // It should be fine to continue snapshot if we for some reason failed
         // to clear code_cache.
@@ -1112,10 +1223,11 @@
     }
 
     if (storageFlags & FLAG_STORAGE_CE) {
-        auto from = create_data_user_ce_package_path(volume_uuid, user, package_name);
-        auto to = create_data_misc_ce_rollback_path(volume_uuid, user, snapshotId);
-        auto rollback_package_path = create_data_misc_ce_rollback_package_path(volume_uuid, user,
-            snapshotId, package_name);
+        auto from = create_data_user_ce_package_path(volume_uuid, userId, package_name);
+        auto to = create_data_misc_ce_rollback_path(volume_uuid, userId, snapshotId);
+        auto rollback_package_path =
+                create_data_misc_ce_rollback_package_path(volume_uuid, userId, snapshotId,
+                                                          package_name);
 
         int rc = create_dir_if_needed(to.c_str(), kRollbackFolderMode);
         if (rc != 0) {
@@ -1134,8 +1246,9 @@
             return res;
         }
         if (_aidl_return != nullptr) {
-            auto ce_snapshot_path = create_data_misc_ce_rollback_package_path(volume_uuid, user,
-                    snapshotId, package_name);
+            auto ce_snapshot_path =
+                    create_data_misc_ce_rollback_package_path(volume_uuid, userId, snapshotId,
+                                                              package_name);
             rc = get_path_inode(ce_snapshot_path, reinterpret_cast<ino_t*>(_aidl_return));
             if (rc != 0) {
                 res = error(rc, "Failed to get_path_inode for " + ce_snapshot_path);
@@ -1150,20 +1263,20 @@
 
 binder::Status InstalldNativeService::restoreAppDataSnapshot(
         const std::optional<std::string>& volumeUuid, const std::string& packageName,
-        const int32_t appId, const std::string& seInfo, const int32_t user,
+        const int32_t appId, const std::string& seInfo, const int32_t userId,
         const int32_t snapshotId, int32_t storageFlags) {
     ENFORCE_UID(AID_SYSTEM);
     CHECK_ARGUMENT_UUID_IS_TEST_OR_NULL(volumeUuid);
     CHECK_ARGUMENT_PACKAGE_NAME(packageName);
-    std::lock_guard<std::recursive_mutex> lock(mLock);
+    LOCK_PACKAGE_USER();
 
     const char* volume_uuid = volumeUuid ? volumeUuid->c_str() : nullptr;
     const char* package_name = packageName.c_str();
 
-    auto from_ce = create_data_misc_ce_rollback_package_path(volume_uuid,
-            user, snapshotId, package_name);
-    auto from_de = create_data_misc_de_rollback_package_path(volume_uuid,
-            user, snapshotId, package_name);
+    auto from_ce = create_data_misc_ce_rollback_package_path(volume_uuid, userId, snapshotId,
+                                                             package_name);
+    auto from_de = create_data_misc_de_rollback_package_path(volume_uuid, userId, snapshotId,
+                                                             package_name);
 
     const bool needs_ce_rollback = (storageFlags & FLAG_STORAGE_CE) &&
         (access(from_ce.c_str(), F_OK) == 0);
@@ -1183,14 +1296,14 @@
     // It's fine to pass 0 as ceDataInode here, because restoreAppDataSnapshot
     // can only be called when user unlocks the phone, meaning that CE user data
     // is decrypted.
-    binder::Status res = clearAppData(volumeUuid, packageName, user, storageFlags,
-            0 /* ceDataInode */);
+    binder::Status res =
+            clearAppData(volumeUuid, packageName, userId, storageFlags, 0 /* ceDataInode */);
     if (!res.isOk()) {
         return res;
     }
 
     if (needs_ce_rollback) {
-        auto to_ce = create_data_user_ce_path(volume_uuid, user);
+        auto to_ce = create_data_user_ce_path(volume_uuid, userId);
         int rc = copy_directory_recursive(from_ce.c_str(), to_ce.c_str());
         if (rc != 0) {
             res = error(rc, "Failed copying " + from_ce + " to " + to_ce);
@@ -1200,11 +1313,11 @@
     }
 
     if (needs_de_rollback) {
-        auto to_de = create_data_user_de_path(volume_uuid, user);
+        auto to_de = create_data_user_de_path(volume_uuid, userId);
         int rc = copy_directory_recursive(from_de.c_str(), to_de.c_str());
         if (rc != 0) {
             if (needs_ce_rollback) {
-                auto ce_data = create_data_user_ce_package_path(volume_uuid, user, package_name);
+                auto ce_data = create_data_user_ce_package_path(volume_uuid, userId, package_name);
                 LOG(WARNING) << "de_data rollback failed. Erasing rolled back ce_data " << ce_data;
                 if (delete_dir_contents(ce_data.c_str(), 1, nullptr) != 0) {
                     LOG(WARNING) << "Failed to delete rolled back ce_data " << ce_data;
@@ -1217,24 +1330,24 @@
     }
 
     // Finally, restore the SELinux label on the app data.
-    return restoreconAppData(volumeUuid, packageName, user, storageFlags, appId, seInfo);
+    return restoreconAppData(volumeUuid, packageName, userId, storageFlags, appId, seInfo);
 }
 
 binder::Status InstalldNativeService::destroyAppDataSnapshot(
-        const std::optional<std::string> &volumeUuid, const std::string& packageName,
-        const int32_t user, const int64_t ceSnapshotInode, const int32_t snapshotId,
+        const std::optional<std::string>& volumeUuid, const std::string& packageName,
+        const int32_t userId, const int64_t ceSnapshotInode, const int32_t snapshotId,
         int32_t storageFlags) {
     ENFORCE_UID(AID_SYSTEM);
     CHECK_ARGUMENT_UUID_IS_TEST_OR_NULL(volumeUuid);
     CHECK_ARGUMENT_PACKAGE_NAME(packageName);
-    std::lock_guard<std::recursive_mutex> lock(mLock);
+    LOCK_PACKAGE_USER();
 
     const char* volume_uuid = volumeUuid ? volumeUuid->c_str() : nullptr;
     const char* package_name = packageName.c_str();
 
     if (storageFlags & FLAG_STORAGE_DE) {
-        auto de_snapshot_path = create_data_misc_de_rollback_package_path(volume_uuid,
-                user, snapshotId, package_name);
+        auto de_snapshot_path = create_data_misc_de_rollback_package_path(volume_uuid, userId,
+                                                                          snapshotId, package_name);
 
         int res = delete_dir_contents_and_dir(de_snapshot_path, true /* ignore_if_missing */);
         if (res != 0) {
@@ -1243,8 +1356,9 @@
     }
 
     if (storageFlags & FLAG_STORAGE_CE) {
-        auto ce_snapshot_path = create_data_misc_ce_rollback_package_path(volume_uuid,
-                user, snapshotId, package_name, ceSnapshotInode);
+        auto ce_snapshot_path =
+                create_data_misc_ce_rollback_package_path(volume_uuid, userId, snapshotId,
+                                                          package_name, ceSnapshotInode);
         int res = delete_dir_contents_and_dir(ce_snapshot_path, true /* ignore_if_missing */);
         if (res != 0) {
             return error(res, "Failed clearing snapshot " + ce_snapshot_path);
@@ -1254,15 +1368,15 @@
 }
 
 binder::Status InstalldNativeService::destroyCeSnapshotsNotSpecified(
-        const std::optional<std::string> &volumeUuid, const int32_t user,
+        const std::optional<std::string>& volumeUuid, const int32_t userId,
         const std::vector<int32_t>& retainSnapshotIds) {
     ENFORCE_UID(AID_SYSTEM);
     CHECK_ARGUMENT_UUID_IS_TEST_OR_NULL(volumeUuid);
-    std::lock_guard<std::recursive_mutex> lock(mLock);
+    LOCK_USER();
 
     const char* volume_uuid = volumeUuid ? volumeUuid->c_str() : nullptr;
 
-    auto base_path = create_data_misc_ce_rollback_base_path(volume_uuid, user);
+    auto base_path = create_data_misc_ce_rollback_base_path(volume_uuid, userId);
 
     std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(base_path.c_str()), closedir);
     if (!dir) {
@@ -1280,8 +1394,8 @@
         if (parse_ok &&
                 std::find(retainSnapshotIds.begin(), retainSnapshotIds.end(),
                           snapshot_id) == retainSnapshotIds.end()) {
-            auto rollback_path = create_data_misc_ce_rollback_path(
-                volume_uuid, user, snapshot_id);
+            auto rollback_path =
+                    create_data_misc_ce_rollback_path(volume_uuid, userId, snapshot_id);
             int res = delete_dir_contents_and_dir(rollback_path, true /* ignore_if_missing */);
             if (res != 0) {
                 return error(res, "Failed clearing snapshot " + rollback_path);
@@ -1299,7 +1413,7 @@
     CHECK_ARGUMENT_UUID(fromUuid);
     CHECK_ARGUMENT_UUID(toUuid);
     CHECK_ARGUMENT_PACKAGE_NAME(packageName);
-    std::lock_guard<std::recursive_mutex> lock(mLock);
+    LOCK_PACKAGE();
 
     const char* from_uuid = fromUuid ? fromUuid->c_str() : nullptr;
     const char* to_uuid = toUuid ? toUuid->c_str() : nullptr;
@@ -1327,24 +1441,25 @@
     }
 
     // Copy private data for all known users
-    for (auto user : users) {
+    for (auto userId : users) {
+        LOCK_USER();
 
         // Data source may not exist for all users; that's okay
-        auto from_ce = create_data_user_ce_package_path(from_uuid, user, package_name);
+        auto from_ce = create_data_user_ce_package_path(from_uuid, userId, package_name);
         if (access(from_ce.c_str(), F_OK) != 0) {
             LOG(INFO) << "Missing source " << from_ce;
             continue;
         }
 
-        if (!createAppData(toUuid, packageName, user, FLAG_STORAGE_CE | FLAG_STORAGE_DE, appId,
-                /* previousAppId */ -1, seInfo, targetSdkVersion, nullptr).isOk()) {
+        if (!createAppDataLocked(toUuid, packageName, userId, FLAG_STORAGE_CE | FLAG_STORAGE_DE,
+                                 appId, /* previousAppId */ -1, seInfo, targetSdkVersion, nullptr)
+                     .isOk()) {
             res = error("Failed to create package target");
             goto fail;
         }
-
         {
-            auto from = create_data_user_de_package_path(from_uuid, user, package_name);
-            auto to = create_data_user_de_path(to_uuid, user);
+            auto from = create_data_user_de_package_path(from_uuid, userId, package_name);
+            auto to = create_data_user_de_path(to_uuid, userId);
 
             int rc = copy_directory_recursive(from.c_str(), to.c_str());
             if (rc != 0) {
@@ -1353,8 +1468,8 @@
             }
         }
         {
-            auto from = create_data_user_ce_package_path(from_uuid, user, package_name);
-            auto to = create_data_user_ce_path(to_uuid, user);
+            auto from = create_data_user_ce_package_path(from_uuid, userId, package_name);
+            auto to = create_data_user_ce_path(to_uuid, userId);
 
             int rc = copy_directory_recursive(from.c_str(), to.c_str());
             if (rc != 0) {
@@ -1363,8 +1478,9 @@
             }
         }
 
-        if (!restoreconAppData(toUuid, packageName, user, FLAG_STORAGE_CE | FLAG_STORAGE_DE,
-                appId, seInfo).isOk()) {
+        if (!restoreconAppDataLocked(toUuid, packageName, userId, FLAG_STORAGE_CE | FLAG_STORAGE_DE,
+                                     appId, seInfo)
+                     .isOk()) {
             res = error("Failed to restorecon");
             goto fail;
         }
@@ -1382,15 +1498,16 @@
             LOG(WARNING) << "Failed to rollback " << to_app_package_path;
         }
     }
-    for (auto user : users) {
+    for (auto userId : users) {
+        LOCK_USER();
         {
-            auto to = create_data_user_de_package_path(to_uuid, user, package_name);
+            auto to = create_data_user_de_package_path(to_uuid, userId, package_name);
             if (delete_dir_contents(to.c_str(), 1, nullptr) != 0) {
                 LOG(WARNING) << "Failed to rollback " << to;
             }
         }
         {
-            auto to = create_data_user_ce_package_path(to_uuid, user, package_name);
+            auto to = create_data_user_ce_package_path(to_uuid, userId, package_name);
             if (delete_dir_contents(to.c_str(), 1, nullptr) != 0) {
                 LOG(WARNING) << "Failed to rollback " << to;
             }
@@ -1403,7 +1520,7 @@
         int32_t userId, int32_t userSerial ATTRIBUTE_UNUSED, int32_t flags) {
     ENFORCE_UID(AID_SYSTEM);
     CHECK_ARGUMENT_UUID(uuid);
-    std::lock_guard<std::recursive_mutex> lock(mLock);
+    LOCK_USER();
 
     const char* uuid_ = uuid ? uuid->c_str() : nullptr;
     if (flags & FLAG_STORAGE_DE) {
@@ -1421,7 +1538,7 @@
         int32_t userId, int32_t flags) {
     ENFORCE_UID(AID_SYSTEM);
     CHECK_ARGUMENT_UUID(uuid);
-    std::lock_guard<std::recursive_mutex> lock(mLock);
+    LOCK_USER();
 
     const char* uuid_ = uuid ? uuid->c_str() : nullptr;
     binder::Status res = ok();
@@ -1458,7 +1575,9 @@
         int64_t targetFreeBytes, int64_t cacheReservedBytes, int32_t flags) {
     ENFORCE_UID(AID_SYSTEM);
     CHECK_ARGUMENT_UUID(uuid);
-    std::lock_guard<std::recursive_mutex> lock(mLock);
+#ifndef GRANULAR_LOCKS
+    std::lock_guard lock(mLock);
+#endif // !GRANULAR_LOCKS
 
     auto uuidString = uuid.value_or("");
     const char* uuid_ = uuid ? uuid->c_str() : nullptr;
@@ -1485,13 +1604,24 @@
 
         // 1. Create trackers for every known UID
         ATRACE_BEGIN("create");
+        const auto users = get_known_users(uuid_);
+#ifdef GRANULAR_LOCKS
+        std::vector<UserLock> userLocks;
+        userLocks.reserve(users.size());
+        std::vector<UserWriteLockGuard> lockGuards;
+        lockGuards.reserve(users.size());
+#endif // GRANULAR_LOCKS
         std::unordered_map<uid_t, std::shared_ptr<CacheTracker>> trackers;
-        for (auto user : get_known_users(uuid_)) {
+        for (auto userId : users) {
+#ifdef GRANULAR_LOCKS
+            userLocks.emplace_back(userId, mUserIdLock, mLock);
+            lockGuards.emplace_back(userLocks.back());
+#endif // GRANULAR_LOCKS
             FTS *fts;
             FTSENT *p;
-            auto ce_path = create_data_user_ce_path(uuid_, user);
-            auto de_path = create_data_user_de_path(uuid_, user);
-            auto media_path = findDataMediaPath(uuid, user) + "/Android/data/";
+            auto ce_path = create_data_user_ce_path(uuid_, userId);
+            auto de_path = create_data_user_de_path(uuid_, userId);
+            auto media_path = findDataMediaPath(uuid, userId) + "/Android/data/";
             char *argv[] = { (char*) ce_path.c_str(), (char*) de_path.c_str(),
                     (char*) media_path.c_str(), nullptr };
             if (!(fts = fts_open(argv, FTS_PHYSICAL | FTS_NOCHDIR | FTS_XDEV, nullptr))) {
@@ -1627,7 +1757,6 @@
         const std::string& instructionSet) {
     ENFORCE_UID(AID_SYSTEM);
     CHECK_ARGUMENT_PATH(codePath);
-    std::lock_guard<std::recursive_mutex> lock(mLock);
 
     char dex_path[PKG_PATH_MAX];
 
@@ -2343,7 +2472,7 @@
         CHECK_ARGUMENT_PACKAGE_NAME(packageName);
     }
 #ifdef ENABLE_STORAGE_CRATES
-    std::lock_guard<std::recursive_mutex> lock(mLock);
+    LOCK_PACKAGE_USER();
 
     auto retVector = std::vector<std::optional<CrateMetadata>>();
     const char* uuid_ = uuid ? uuid->c_str() : nullptr;
@@ -2389,7 +2518,7 @@
     ENFORCE_UID(AID_SYSTEM);
     CHECK_ARGUMENT_UUID(uuid);
 #ifdef ENABLE_STORAGE_CRATES
-    std::lock_guard<std::recursive_mutex> lock(mLock);
+    LOCK_USER();
 
     const char* uuid_ = uuid ? uuid->c_str() : nullptr;
     auto retVector = std::vector<std::optional<CrateMetadata>>();
@@ -2446,7 +2575,7 @@
     ENFORCE_UID(AID_SYSTEM);
     CHECK_ARGUMENT_PACKAGE_NAME(packageName);
     CHECK_ARGUMENT_PATH(codePath);
-    std::lock_guard<std::recursive_mutex> lock(mLock);
+    LOCK_PACKAGE();
 
     *_aidl_return = dump_profiles(uid, packageName, profileName, codePath);
     return ok();
@@ -2458,7 +2587,7 @@
         bool* _aidl_return) {
     ENFORCE_UID(AID_SYSTEM);
     CHECK_ARGUMENT_PACKAGE_NAME(packageName);
-    std::lock_guard<std::recursive_mutex> lock(mLock);
+    LOCK_PACKAGE();
     *_aidl_return = copy_system_profile(systemProfile, packageUid, packageName, profileName);
     return ok();
 }
@@ -2468,7 +2597,7 @@
         const std::string& profileName, int* _aidl_return) {
     ENFORCE_UID(AID_SYSTEM);
     CHECK_ARGUMENT_PACKAGE_NAME(packageName);
-    std::lock_guard<std::recursive_mutex> lock(mLock);
+    LOCK_PACKAGE();
 
     *_aidl_return = analyze_primary_profiles(uid, packageName, profileName);
     return ok();
@@ -2479,7 +2608,7 @@
         const std::string& classpath, bool* _aidl_return) {
     ENFORCE_UID(AID_SYSTEM);
     CHECK_ARGUMENT_PACKAGE_NAME(packageName);
-    std::lock_guard<std::recursive_mutex> lock(mLock);
+    LOCK_PACKAGE();
 
     *_aidl_return = create_profile_snapshot(appId, packageName, profileName, classpath);
     return ok();
@@ -2489,7 +2618,7 @@
         const std::string& profileName) {
     ENFORCE_UID(AID_SYSTEM);
     CHECK_ARGUMENT_PACKAGE_NAME(packageName);
-    std::lock_guard<std::recursive_mutex> lock(mLock);
+    LOCK_PACKAGE();
 
     std::string snapshot = create_snapshot_profile_path(packageName, profileName);
     if ((unlink(snapshot.c_str()) != 0) && (errno != ENOENT)) {
@@ -2520,7 +2649,8 @@
     }
     CHECK_ARGUMENT_PATH(outputPath);
     CHECK_ARGUMENT_PATH(dexMetadataPath);
-    std::lock_guard<std::recursive_mutex> lock(mLock);
+    const auto userId = multiuser_get_user_id(uid);
+    LOCK_PACKAGE_USER();
 
     const char* oat_dir = getCStr(outputPath);
     const char* instruction_set = instructionSet.c_str();
@@ -2571,7 +2701,7 @@
     CHECK_ARGUMENT_UUID(uuid);
     CHECK_ARGUMENT_PACKAGE_NAME(packageName);
     CHECK_ARGUMENT_PATH(nativeLibPath32);
-    std::lock_guard<std::recursive_mutex> lock(mLock);
+    LOCK_PACKAGE_USER();
 
     const char* uuid_ = uuid ? uuid->c_str() : nullptr;
     const char* pkgname = packageName.c_str();
@@ -2662,7 +2792,16 @@
     ENFORCE_UID(AID_SYSTEM);
     CHECK_ARGUMENT_UUID(uuid);
     CHECK_ARGUMENT_PACKAGE_NAME(packageName);
-    std::lock_guard<std::recursive_mutex> lock(mLock);
+    LOCK_PACKAGE_USER();
+    return restoreconAppDataLocked(uuid, packageName, userId, flags, appId, seInfo);
+}
+
+binder::Status InstalldNativeService::restoreconAppDataLocked(
+        const std::optional<std::string>& uuid, const std::string& packageName, int32_t userId,
+        int32_t flags, int32_t appId, const std::string& seInfo) {
+    ENFORCE_UID(AID_SYSTEM);
+    CHECK_ARGUMENT_UUID(uuid);
+    CHECK_ARGUMENT_PACKAGE_NAME(packageName);
 
     binder::Status res = ok();
 
@@ -2692,7 +2831,7 @@
         const std::string& instructionSet) {
     ENFORCE_UID(AID_SYSTEM);
     CHECK_ARGUMENT_PATH(oatDir);
-    std::lock_guard<std::recursive_mutex> lock(mLock);
+    LOCK_PACKAGE();
 
     const char* oat_dir = oatDir.c_str();
     const char* instruction_set = instructionSet.c_str();
@@ -2717,7 +2856,7 @@
 binder::Status InstalldNativeService::rmPackageDir(const std::string& packageDir) {
     ENFORCE_UID(AID_SYSTEM);
     CHECK_ARGUMENT_PATH(packageDir);
-    std::lock_guard<std::recursive_mutex> lock(mLock);
+    LOCK_PACKAGE();
 
     if (validate_apk_path(packageDir.c_str())) {
         return error("Invalid path " + packageDir);
@@ -2733,7 +2872,7 @@
     ENFORCE_UID(AID_SYSTEM);
     CHECK_ARGUMENT_PATH(fromBase);
     CHECK_ARGUMENT_PATH(toBase);
-    std::lock_guard<std::recursive_mutex> lock(mLock);
+    LOCK_PACKAGE();
 
     const char* relative_path = relativePath.c_str();
     const char* from_base = fromBase.c_str();
@@ -2763,7 +2902,7 @@
     ENFORCE_UID(AID_SYSTEM);
     CHECK_ARGUMENT_PATH(apkPath);
     CHECK_ARGUMENT_PATH(outputPath);
-    std::lock_guard<std::recursive_mutex> lock(mLock);
+    LOCK_PACKAGE();
 
     const char* apk_path = apkPath.c_str();
     const char* instruction_set = instructionSet.c_str();
@@ -2779,7 +2918,7 @@
     ENFORCE_UID(AID_SYSTEM);
     CHECK_ARGUMENT_PATH(apkPath);
     CHECK_ARGUMENT_PATH(outputPath);
-    std::lock_guard<std::recursive_mutex> lock(mLock);
+    LOCK_PACKAGE();
 
     const char* apk_path = apkPath.c_str();
     const char* instruction_set = instructionSet.c_str();
@@ -2812,7 +2951,7 @@
         android::base::unique_fd verityInputAshmem, int32_t contentSize) {
     ENFORCE_UID(AID_SYSTEM);
     CHECK_ARGUMENT_PATH(filePath);
-    std::lock_guard<std::recursive_mutex> lock(mLock);
+    LOCK_PACKAGE();
 
     if (!android::base::GetBoolProperty(kPropApkVerityMode, false)) {
         return ok();
@@ -2894,7 +3033,7 @@
         const std::vector<uint8_t>& expectedHash) {
     ENFORCE_UID(AID_SYSTEM);
     CHECK_ARGUMENT_PATH(filePath);
-    std::lock_guard<std::recursive_mutex> lock(mLock);
+    LOCK_PACKAGE();
 
     if (!android::base::GetBoolProperty(kPropApkVerityMode, false)) {
         return ok();
@@ -2933,7 +3072,8 @@
     CHECK_ARGUMENT_UUID(volumeUuid);
     CHECK_ARGUMENT_PACKAGE_NAME(packageName);
     CHECK_ARGUMENT_PATH(dexPath);
-    std::lock_guard<std::recursive_mutex> lock(mLock);
+    const auto userId = multiuser_get_user_id(uid);
+    LOCK_PACKAGE_USER();
 
     bool result = android::installd::reconcile_secondary_dex_file(
             dexPath, packageName, uid, isas, volumeUuid, storage_flag, _aidl_return);
@@ -3013,8 +3153,9 @@
 
     const char* uuid_ = uuid->c_str();
 
+    std::lock_guard<std::recursive_mutex> lock(mMountsLock);
+
     std::string mirrorVolCePath(StringPrintf("%s/%s", kDataMirrorCePath, uuid_));
-    std::lock_guard<std::recursive_mutex> lock(mLock);
     if (fs_prepare_dir(mirrorVolCePath.c_str(), 0711, AID_SYSTEM, AID_SYSTEM) != 0) {
         return error("Failed to create CE mirror");
     }
@@ -3083,8 +3224,9 @@
     std::string mirrorCeVolPath(StringPrintf("%s/%s", kDataMirrorCePath, uuid_));
     std::string mirrorDeVolPath(StringPrintf("%s/%s", kDataMirrorDePath, uuid_));
 
+    std::lock_guard<std::recursive_mutex> lock(mMountsLock);
+
     // Unmount CE storage
-    std::lock_guard<std::recursive_mutex> lock(mLock);
     if (TEMP_FAILURE_RETRY(umount(mirrorCeVolPath.c_str())) != 0) {
         if (errno != ENOENT) {
             res = error(StringPrintf("Failed to umount %s %s", mirrorCeVolPath.c_str(),
@@ -3133,7 +3275,7 @@
     ENFORCE_UID(AID_SYSTEM);
     CHECK_ARGUMENT_PACKAGE_NAME(packageName);
     CHECK_ARGUMENT_PATH(codePath);
-    std::lock_guard<std::recursive_mutex> lock(mLock);
+    LOCK_PACKAGE_USER();
 
     *_aidl_return = prepare_app_profile(packageName, userId, appId, profileName, codePath,
         dexMetadata);
diff --git a/cmds/installd/InstalldNativeService.h b/cmds/installd/InstalldNativeService.h
index 8cfda01..09581bb 100644
--- a/cmds/installd/InstalldNativeService.h
+++ b/cmds/installd/InstalldNativeService.h
@@ -21,8 +21,9 @@
 #include <inttypes.h>
 #include <unistd.h>
 
-#include <vector>
+#include <shared_mutex>
 #include <unordered_map>
+#include <vector>
 
 #include <android-base/macros.h>
 #include <binder/BinderService.h>
@@ -49,6 +50,11 @@
             const std::string& packageName, int32_t userId, int32_t flags, int32_t appId,
             int32_t previousAppId, const std::string& seInfo, int32_t targetSdkVersion,
             int64_t* _aidl_return);
+    binder::Status createAppDataLocked(const std::optional<std::string>& uuid,
+                                       const std::string& packageName, int32_t userId,
+                                       int32_t flags, int32_t appId, int32_t previousAppId,
+                                       const std::string& seInfo, int32_t targetSdkVersion,
+                                       int64_t* _aidl_return);
 
     binder::Status createAppData(
             const android::os::CreateAppDataArgs& args,
@@ -60,6 +66,9 @@
     binder::Status restoreconAppData(const std::optional<std::string>& uuid,
             const std::string& packageName, int32_t userId, int32_t flags, int32_t appId,
             const std::string& seInfo);
+    binder::Status restoreconAppDataLocked(const std::optional<std::string>& uuid,
+                                           const std::string& packageName, int32_t userId,
+                                           int32_t flags, int32_t appId, const std::string& seInfo);
     binder::Status migrateAppData(const std::optional<std::string>& uuid,
             const std::string& packageName, int32_t userId, int32_t flags);
     binder::Status clearAppData(const std::optional<std::string>& uuid,
@@ -181,6 +190,8 @@
 
 private:
     std::recursive_mutex mLock;
+    std::unordered_map<userid_t, std::weak_ptr<std::shared_mutex>> mUserIdLock;
+    std::unordered_map<std::string, std::weak_ptr<std::recursive_mutex>> mPackageNameLock;
 
     std::recursive_mutex mMountsLock;
     std::recursive_mutex mQuotasLock;
diff --git a/cmds/installd/dexopt.cpp b/cmds/installd/dexopt.cpp
index f3ec63f..2bcf2d4 100644
--- a/cmds/installd/dexopt.cpp
+++ b/cmds/installd/dexopt.cpp
@@ -52,6 +52,7 @@
 #include <server_configurable_flags/get_flags.h>
 #include <system/thread_defs.h>
 #include <utils/Mutex.h>
+#include <ziparchive/zip_archive.h>
 
 #include "dexopt.h"
 #include "dexopt_return_codes.h"
@@ -459,8 +460,8 @@
     });
 }
 
-static unique_fd open_spnashot_profile(uid_t uid, const std::string& package_name,
-        const std::string& location) {
+static unique_fd open_snapshot_profile(uid_t uid, const std::string& package_name,
+                                       const std::string& location) {
     std::string profile = create_snapshot_profile_path(package_name, location);
     return open_profile(uid, profile, O_CREAT | O_RDWR | O_TRUNC,  S_IRUSR | S_IWUSR);
 }
@@ -2562,7 +2563,7 @@
                                         const std::string& classpath) {
     int app_shared_gid = multiuser_get_shared_gid(/*user_id*/ 0, app_id);
 
-    unique_fd snapshot_fd = open_spnashot_profile(AID_SYSTEM, package_name, profile_name);
+    unique_fd snapshot_fd = open_snapshot_profile(AID_SYSTEM, package_name, profile_name);
     if (snapshot_fd < 0) {
         return false;
     }
@@ -2636,7 +2637,7 @@
     }
 
     // Open and create the snapshot profile.
-    unique_fd snapshot_fd = open_spnashot_profile(AID_SYSTEM, package_name, profile_name);
+    unique_fd snapshot_fd = open_snapshot_profile(AID_SYSTEM, package_name, profile_name);
 
     // Collect all non empty profiles.
     // The collection will traverse all applications profiles and find the non empty files.
@@ -2738,6 +2739,20 @@
     }
 }
 
+static bool check_profile_exists_in_dexmetadata(const std::string& dex_metadata) {
+    ZipArchiveHandle zip = nullptr;
+    if (OpenArchive(dex_metadata.c_str(), &zip) != 0) {
+        PLOG(ERROR) << "Failed to open dm '" << dex_metadata << "'";
+        return false;
+    }
+
+    ZipEntry64 entry;
+    int result = FindEntry(zip, "primary.prof", &entry);
+    CloseArchive(zip);
+
+    return result != 0 ? false : true;
+}
+
 bool prepare_app_profile(const std::string& package_name,
                          userid_t user_id,
                          appid_t app_id,
@@ -2754,7 +2769,7 @@
     }
 
     // Check if we need to install the profile from the dex metadata.
-    if (!dex_metadata) {
+    if (!dex_metadata || !check_profile_exists_in_dexmetadata(dex_metadata->c_str())) {
         return true;
     }
 
diff --git a/cmds/installd/tests/Android.bp b/cmds/installd/tests/Android.bp
index 7082017..13e15ca 100644
--- a/cmds/installd/tests/Android.bp
+++ b/cmds/installd/tests/Android.bp
@@ -48,6 +48,7 @@
         "libasync_safe",
         "libdiskusage",
         "libinstalld",
+        "libziparchive",
         "liblog",
         "liblogwrap",
     ],
@@ -89,6 +90,7 @@
         "libasync_safe",
         "libdiskusage",
         "libinstalld",
+        "libziparchive",
         "liblog",
         "liblogwrap",
     ],
diff --git a/cmds/installd/tests/installd_cache_test.cpp b/cmds/installd/tests/installd_cache_test.cpp
index 863cdfe..72f5f4b 100644
--- a/cmds/installd/tests/installd_cache_test.cpp
+++ b/cmds/installd/tests/installd_cache_test.cpp
@@ -122,6 +122,7 @@
 
         service = new InstalldNativeService();
         testUuid = kTestUuid;
+        system("rm -rf /data/local/tmp/user");
         system("mkdir -p /data/local/tmp/user/0");
     }
 
diff --git a/cmds/installd/tests/installd_service_test.cpp b/cmds/installd/tests/installd_service_test.cpp
index 1e7559d..8edb3bf 100644
--- a/cmds/installd/tests/installd_service_test.cpp
+++ b/cmds/installd/tests/installd_service_test.cpp
@@ -107,6 +107,7 @@
 
         service = new InstalldNativeService();
         testUuid = kTestUuid;
+        system("rm -rf /data/local/tmp/user");
         system("mkdir -p /data/local/tmp/user/0");
 
         init_globals_from_data_and_root();
diff --git a/cmds/servicemanager/ServiceManager.cpp b/cmds/servicemanager/ServiceManager.cpp
index 4e44ac7..4374abe 100644
--- a/cmds/servicemanager/ServiceManager.cpp
+++ b/cmds/servicemanager/ServiceManager.cpp
@@ -28,6 +28,9 @@
 
 #ifndef VENDORSERVICEMANAGER
 #include <vintf/VintfObject.h>
+#ifdef __ANDROID_RECOVERY__
+#include <vintf/VintfObjectRecovery.h>
+#endif // __ANDROID_RECOVERY__
 #include <vintf/constants.h>
 #endif  // !VENDORSERVICEMANAGER
 
@@ -37,16 +40,33 @@
 namespace android {
 
 #ifndef VENDORSERVICEMANAGER
+
 struct ManifestWithDescription {
     std::shared_ptr<const vintf::HalManifest> manifest;
     const char* description;
 };
+static std::vector<ManifestWithDescription> GetManifestsWithDescription() {
+#ifdef __ANDROID_RECOVERY__
+    auto vintfObject = vintf::VintfObjectRecovery::GetInstance();
+    if (vintfObject == nullptr) {
+        LOG(ERROR) << "NULL VintfObjectRecovery!";
+        return {};
+    }
+    return {ManifestWithDescription{vintfObject->getRecoveryHalManifest(), "recovery"}};
+#else
+    auto vintfObject = vintf::VintfObject::GetInstance();
+    if (vintfObject == nullptr) {
+        LOG(ERROR) << "NULL VintfObject!";
+        return {};
+    }
+    return {ManifestWithDescription{vintfObject->getDeviceHalManifest(), "device"},
+            ManifestWithDescription{vintfObject->getFrameworkHalManifest(), "framework"}};
+#endif
+}
+
 // func true -> stop search and forEachManifest will return true
 static bool forEachManifest(const std::function<bool(const ManifestWithDescription&)>& func) {
-    for (const ManifestWithDescription& mwd : {
-            ManifestWithDescription{ vintf::VintfObject::GetDeviceHalManifest(), "device" },
-            ManifestWithDescription{ vintf::VintfObject::GetFrameworkHalManifest(), "framework" },
-        }) {
+    for (const ManifestWithDescription& mwd : GetManifestsWithDescription()) {
         if (mwd.manifest == nullptr) {
           LOG(ERROR) << "NULL VINTF MANIFEST!: " << mwd.description;
           // note, we explicitly do not retry here, so that we can detect VINTF
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp
index 8270ae5..d8101fa 100644
--- a/libs/binder/Android.bp
+++ b/libs/binder/Android.bp
@@ -202,7 +202,7 @@
     sanitize: {
         misc_undefined: ["integer"],
     },
-    min_sdk_version: "29",
+    min_sdk_version: "30",
 
     tidy: true,
     tidy_flags: [
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index 8f4f0f0..7027a4b 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -824,7 +824,7 @@
 
     const size_t padded = pad_size(len);
 
-    // sanity check for integer overflow
+    // check for integer overflow
     if (mDataPos+padded < mDataPos) {
         return nullptr;
     }
diff --git a/libs/binder/ndk/include_cpp/android/binder_auto_utils.h b/libs/binder/ndk/include_cpp/android/binder_auto_utils.h
index 0ad400b..c903998 100644
--- a/libs/binder/ndk/include_cpp/android/binder_auto_utils.h
+++ b/libs/binder/ndk/include_cpp/android/binder_auto_utils.h
@@ -365,6 +365,8 @@
     ScopedFileDescriptor(ScopedFileDescriptor&&) = default;
     ScopedFileDescriptor& operator=(ScopedFileDescriptor&&) = default;
 
+    ScopedFileDescriptor dup() const { return ScopedFileDescriptor(::dup(get())); }
+
     bool operator!=(const ScopedFileDescriptor& rhs) const { return get() != rhs.get(); }
     bool operator<(const ScopedFileDescriptor& rhs) const { return get() < rhs.get(); }
     bool operator<=(const ScopedFileDescriptor& rhs) const { return get() <= rhs.get(); }
diff --git a/libs/binder/rust/src/binder.rs b/libs/binder/rust/src/binder.rs
index d09ac83..3d2eddf 100644
--- a/libs/binder/rust/src/binder.rs
+++ b/libs/binder/rust/src/binder.rs
@@ -1027,16 +1027,20 @@
 #[macro_export]
 macro_rules! declare_binder_enum {
     {
+        $( #[$attr:meta] )*
         $enum:ident : [$backing:ty; $size:expr] {
             $( $name:ident = $value:expr, )*
         }
     } => {
+        $( #[$attr] )*
         #[derive(Debug, Default, Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Hash)]
+        #[allow(missing_docs)]
         pub struct $enum(pub $backing);
         impl $enum {
-            $( pub const $name: Self = Self($value); )*
+            $( #[allow(missing_docs)] pub const $name: Self = Self($value); )*
 
             #[inline(always)]
+            #[allow(missing_docs)]
             pub const fn enum_values() -> [Self; $size] {
                 [$(Self::$name),*]
             }
diff --git a/libs/binder/rust/tests/integration.rs b/libs/binder/rust/tests/integration.rs
index 1fd2ead..40359b4 100644
--- a/libs/binder/rust/tests/integration.rs
+++ b/libs/binder/rust/tests/integration.rs
@@ -16,7 +16,7 @@
 
 //! Rust Binder crate integration tests
 
-use binder::declare_binder_interface;
+use binder::{declare_binder_enum, declare_binder_interface};
 use binder::parcel::BorrowedParcel;
 use binder::{
     Binder, BinderFeatures, IBinderInternal, Interface, StatusCode, ThreadState, TransactionCode,
@@ -294,6 +294,23 @@
 
 impl ITestSameDescriptor for Binder<BnTestSameDescriptor> {}
 
+declare_binder_enum! {
+    TestEnum : [i32; 3] {
+        FOO = 1,
+        BAR = 2,
+        BAZ = 3,
+    }
+}
+
+declare_binder_enum! {
+    #[deprecated(since = "1.0.0")]
+    TestDeprecatedEnum : [i32; 3] {
+        FOO = 1,
+        BAR = 2,
+        BAZ = 3,
+    }
+}
+
 #[cfg(test)]
 mod tests {
     use selinux_bindgen as selinux_sys;
diff --git a/vulkan/libvulkan/api.cpp b/vulkan/libvulkan/api.cpp
index d1cd397..fa3b260 100644
--- a/vulkan/libvulkan/api.cpp
+++ b/vulkan/libvulkan/api.cpp
@@ -965,6 +965,13 @@
     VkResult result = EnumerateDeviceExtensionProperties(physical_dev, nullptr,
                                                          &count, nullptr);
     if (result == VK_SUCCESS && count) {
+        // Work-around a race condition during Android start-up, that can result
+        // in the second call to EnumerateDeviceExtensionProperties having
+        // another extension.  That causes the second call to return
+        // VK_INCOMPLETE.  A work-around is to add 1 to "count" and ask for one
+        // more extension property.  See: http://anglebug.com/6715 and
+        // internal-to-Google b/206733351.
+        count++;
         driver_extensions_ = AllocateDriverExtensionArray(count);
         result = (driver_extensions_)
                      ? EnumerateDeviceExtensionProperties(
diff --git a/vulkan/libvulkan/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp
index 2715587..8c54a0e 100644
--- a/vulkan/libvulkan/swapchain.cpp
+++ b/vulkan/libvulkan/swapchain.cpp
@@ -537,30 +537,6 @@
     }
 }
 
-int get_min_buffer_count(ANativeWindow* window,
-                         uint32_t* out_min_buffer_count) {
-    constexpr int kExtraBuffers = 2;
-
-    int err;
-    int min_undequeued_buffers;
-    err = window->query(window, NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
-                        &min_undequeued_buffers);
-    if (err != android::OK || min_undequeued_buffers < 0) {
-        ALOGE(
-            "NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS query failed: %s (%d) "
-            "value=%d",
-            strerror(-err), err, min_undequeued_buffers);
-        if (err == android::OK) {
-            err = android::UNKNOWN_ERROR;
-        }
-        return err;
-    }
-
-    *out_min_buffer_count =
-        static_cast<uint32_t>(min_undequeued_buffers + kExtraBuffers);
-    return android::OK;
-}
-
 }  // anonymous namespace
 
 VKAPI_ATTR
@@ -675,7 +651,7 @@
               strerror(-err), err);
         return VK_ERROR_SURFACE_LOST_KHR;
     }
-    capabilities->minImageCount = max_buffer_count == 1 ? 1 : 2;
+    capabilities->minImageCount = std::min(max_buffer_count, 3);
     capabilities->maxImageCount = static_cast<uint32_t>(max_buffer_count);
 
     capabilities->currentExtent =
@@ -872,13 +848,18 @@
 
     int err;
     int query_value;
-    uint32_t min_buffer_count;
     ANativeWindow* window = SurfaceFromHandle(surface)->window.get();
 
-    err = get_min_buffer_count(window, &min_buffer_count);
-    if (err != android::OK) {
+    err = window->query(window, NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
+                        &query_value);
+    if (err != android::OK || query_value < 0) {
+        ALOGE(
+            "NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS query failed: %s (%d) "
+            "value=%d",
+            strerror(-err), err, query_value);
         return VK_ERROR_SURFACE_LOST_KHR;
     }
+    uint32_t min_undequeued_buffers = static_cast<uint32_t>(query_value);
 
     err = window->query(window, NATIVE_WINDOW_MAX_BUFFER_COUNT, &query_value);
     if (err != android::OK || query_value < 0) {
@@ -889,7 +870,7 @@
     uint32_t max_buffer_count = static_cast<uint32_t>(query_value);
 
     std::vector<VkPresentModeKHR> present_modes;
-    if (min_buffer_count < max_buffer_count)
+    if (min_undequeued_buffers + 1 < max_buffer_count)
         present_modes.push_back(VK_PRESENT_MODE_MAILBOX_KHR);
     present_modes.push_back(VK_PRESENT_MODE_FIFO_KHR);
 
@@ -1210,14 +1191,19 @@
         }
     }
 
-    uint32_t min_buffer_count;
-    err = get_min_buffer_count(window, &min_buffer_count);
-    if (err != android::OK) {
+    int query_value;
+    err = window->query(window, NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
+                        &query_value);
+    if (err != android::OK || query_value < 0) {
+        ALOGE("window->query failed: %s (%d) value=%d", strerror(-err), err,
+              query_value);
         return VK_ERROR_SURFACE_LOST_KHR;
     }
-
-    uint32_t num_images =
-        std::max(min_buffer_count, create_info->minImageCount);
+    uint32_t min_undequeued_buffers = static_cast<uint32_t>(query_value);
+    const auto mailbox_num_images = std::max(3u, create_info->minImageCount);
+    const auto requested_images =
+        swap_interval ? create_info->minImageCount : mailbox_num_images;
+    uint32_t num_images = requested_images - 1 + min_undequeued_buffers;
 
     // Lower layer insists that we have at least two buffers. This is wasteful
     // and we'd like to relax it in the shared case, but not all the pieces are