Merge "storaged: Fix double ownership for HealthInfoCallback."
diff --git a/debuggerd/seccomp_policy/crash_dump.arm64.policy b/debuggerd/seccomp_policy/crash_dump.arm64.policy
index 4e8fdf9..8241f0e 100644
--- a/debuggerd/seccomp_policy/crash_dump.arm64.policy
+++ b/debuggerd/seccomp_policy/crash_dump.arm64.policy
@@ -25,7 +25,7 @@
 rt_sigprocmask: 1
 rt_sigaction: 1
 rt_tgsigqueueinfo: 1
-prctl: arg0 == PR_GET_NO_NEW_PRIVS || arg0 == 0x53564d41 || arg0 == PR_PAC_RESET_KEYS || arg0 == PR_GET_TAGGED_ADDR_CTRL || arg0 == PR_PAC_GET_ENABLED_KEYS
+prctl: arg0 == PR_GET_NO_NEW_PRIVS || arg0 == 0x53564d41 || arg0 == PR_PAC_RESET_KEYS || arg0 == 56 || arg0 == 61
 madvise: 1
 mprotect: arg2 in 0x1|0x2
 munmap: 1
diff --git a/debuggerd/seccomp_policy/crash_dump.policy.def b/debuggerd/seccomp_policy/crash_dump.policy.def
index 4eb996e..0cb8e08 100644
--- a/debuggerd/seccomp_policy/crash_dump.policy.def
+++ b/debuggerd/seccomp_policy/crash_dump.policy.def
@@ -34,7 +34,15 @@
 rt_sigaction: 1
 rt_tgsigqueueinfo: 1
 
+// this is referenced from mainline modules running on Q devices, where not all
+// of the constants used here are defined in headers, so minijail rejects them.
+// we define them here to avoid those errors.
+        // constants introduced in R
 #define PR_SET_VMA 0x53564d41
+#define PR_GET_TAGGED_ADDR_CTRL 56
+        // constants introduced in S
+#define PR_PAC_GET_ENABLED_KEYS 61
+
 #if defined(__aarch64__)
 // PR_PAC_RESET_KEYS happens on aarch64 in pthread_create path.
 prctl: arg0 == PR_GET_NO_NEW_PRIVS || arg0 == PR_SET_VMA || arg0 == PR_PAC_RESET_KEYS || arg0 == PR_GET_TAGGED_ADDR_CTRL || arg0 == PR_PAC_GET_ENABLED_KEYS
diff --git a/fastboot/device/variables.cpp b/fastboot/device/variables.cpp
index 76e9889..0cf4699 100644
--- a/fastboot/device/variables.cpp
+++ b/fastboot/device/variables.cpp
@@ -332,8 +332,8 @@
 
     auto fastboot_hal = device->fastboot_hal();
     if (!fastboot_hal) {
-        *message = "Fastboot HAL not found";
-        return false;
+        *message = "raw";
+        return true;
     }
 
     FileSystemType type;
diff --git a/fs_mgr/libsnapshot/test_helpers.cpp b/fs_mgr/libsnapshot/test_helpers.cpp
index e3e3af8..71fe124 100644
--- a/fs_mgr/libsnapshot/test_helpers.cpp
+++ b/fs_mgr/libsnapshot/test_helpers.cpp
@@ -267,8 +267,8 @@
         return AssertionFailure() << "Temp file allocated to " << big_file_->path << ", not in "
                                   << kUserDataDevice;
     }
-    uint64_t next_consume =
-            std::min(free_space_ - max_free_space, (uint64_t)std::numeric_limits<off_t>::max());
+    uint64_t next_consume = std::min(available_space_ - max_free_space,
+                                     (uint64_t)std::numeric_limits<off_t>::max());
     off_t allocated = 0;
     while (next_consume > 0 && free_space_ > max_free_space) {
         int status = fallocate(big_file_->fd, 0, allocated, next_consume);
diff --git a/init/first_stage_init.cpp b/init/first_stage_init.cpp
index 52e3995..13ee37d 100644
--- a/init/first_stage_init.cpp
+++ b/init/first_stage_init.cpp
@@ -157,7 +157,7 @@
 }
 
 #define MODULE_BASE_DIR "/lib/modules"
-bool LoadKernelModules(bool recovery, bool want_console, int& modules_loaded) {
+bool LoadKernelModules(bool recovery, bool want_console, bool want_parallel, int& modules_loaded) {
     struct utsname uts;
     if (uname(&uts)) {
         LOG(FATAL) << "Failed to get kernel version.";
@@ -206,7 +206,8 @@
     }
 
     Modprobe m({MODULE_BASE_DIR}, GetModuleLoadList(recovery, MODULE_BASE_DIR));
-    bool retval = m.LoadListedModules(!want_console);
+    bool retval = (want_parallel) ? m.LoadModulesParallel(std::thread::hardware_concurrency())
+                                  : m.LoadListedModules(!want_console);
     modules_loaded = m.GetModuleCount();
     if (modules_loaded > 0) {
         return retval;
@@ -319,11 +320,13 @@
     }
 
     auto want_console = ALLOW_FIRST_STAGE_CONSOLE ? FirstStageConsole(cmdline, bootconfig) : 0;
+    auto want_parallel =
+            bootconfig.find("androidboot.load_modules_parallel = \"true\"") != std::string::npos;
 
     boot_clock::time_point module_start_time = boot_clock::now();
     int module_count = 0;
     if (!LoadKernelModules(IsRecoveryMode() && !ForceNormalBoot(cmdline, bootconfig), want_console,
-                           module_count)) {
+                           want_parallel, module_count)) {
         if (want_console != FirstStageConsoleParam::DISABLED) {
             LOG(ERROR) << "Failed to load kernel modules, starting console";
         } else {
diff --git a/init/selinux.cpp b/init/selinux.cpp
index c89c5ab..be8c554 100644
--- a/init/selinux.cpp
+++ b/init/selinux.cpp
@@ -762,6 +762,7 @@
 void SelinuxRestoreContext() {
     LOG(INFO) << "Running restorecon...";
     selinux_android_restorecon("/dev", 0);
+    selinux_android_restorecon("/dev/console", 0);
     selinux_android_restorecon("/dev/kmsg", 0);
     if constexpr (WORLD_WRITABLE_KMSG) {
         selinux_android_restorecon("/dev/kmsg_debug", 0);
diff --git a/libmodprobe/TEST_MAPPING b/libmodprobe/TEST_MAPPING
index 526b1e4..888593e 100644
--- a/libmodprobe/TEST_MAPPING
+++ b/libmodprobe/TEST_MAPPING
@@ -3,5 +3,10 @@
     {
       "name": "libmodprobe_tests"
     }
+  ],
+  "hwasan-postsubmit": [
+    {
+      "name": "libmodprobe_tests"
+    }
   ]
 }
diff --git a/libmodprobe/include/modprobe/modprobe.h b/libmodprobe/include/modprobe/modprobe.h
index c934860..5d79d6a 100644
--- a/libmodprobe/include/modprobe/modprobe.h
+++ b/libmodprobe/include/modprobe/modprobe.h
@@ -16,17 +16,21 @@
 
 #pragma once
 
+#include <mutex>
 #include <set>
 #include <string>
 #include <unordered_map>
 #include <unordered_set>
 #include <vector>
 
+#include <android-base/thread_annotations.h>
+
 class Modprobe {
   public:
     Modprobe(const std::vector<std::string>&, const std::string load_file = "modules.load",
              bool use_blocklist = true);
 
+    bool LoadModulesParallel(int num_threads);
     bool LoadListedModules(bool strict = true);
     bool LoadWithAliases(const std::string& module_name, bool strict,
                          const std::string& parameters = "");
@@ -66,7 +70,9 @@
     std::vector<std::string> module_load_;
     std::unordered_map<std::string, std::string> module_options_;
     std::set<std::string> module_blocklist_;
+    std::mutex module_loaded_lock_;
     std::unordered_set<std::string> module_loaded_;
+    std::unordered_set<std::string> module_loaded_paths_;
     int module_count_ = 0;
     bool blocklist_enabled = false;
 };
diff --git a/libmodprobe/libmodprobe.cpp b/libmodprobe/libmodprobe.cpp
index 1a9d364..3054d2b 100644
--- a/libmodprobe/libmodprobe.cpp
+++ b/libmodprobe/libmodprobe.cpp
@@ -21,8 +21,10 @@
 #include <sys/syscall.h>
 
 #include <algorithm>
+#include <map>
 #include <set>
 #include <string>
+#include <thread>
 #include <vector>
 
 #include <android-base/chrono_utils.h>
@@ -437,6 +439,97 @@
     return module_blocklist_.count(canonical_name) > 0;
 }
 
+// Another option to load kernel modules. load in independent modules in parallel
+// and then load modules which only have soft dependency, third update dependency list of other
+// remaining modules, repeat these steps until all modules are loaded.
+bool Modprobe::LoadModulesParallel(int num_threads) {
+    bool ret = true;
+    std::map<std::string, std::set<std::string>> mod_with_deps;
+    std::map<std::string, std::set<std::string>> mod_with_softdeps;
+
+    // Get dependencies
+    for (const auto& module : module_load_) {
+        auto dependencies = GetDependencies(MakeCanonical(module));
+
+        for (auto dep = dependencies.rbegin(); dep != dependencies.rend(); dep++) {
+            mod_with_deps[module].emplace(*dep);
+        }
+    }
+
+    // Get soft dependencies
+    for (const auto& [it_mod, it_softdep] : module_pre_softdep_) {
+        mod_with_softdeps[MakeCanonical(it_mod)].emplace(it_softdep);
+    }
+
+    // Get soft post dependencies
+    for (const auto& [it_mod, it_softdep] : module_post_softdep_) {
+        mod_with_softdeps[MakeCanonical(it_mod)].emplace(it_softdep);
+    }
+
+    while (!mod_with_deps.empty()) {
+        std::vector<std::thread> threads;
+        std::vector<std::string> mods_path_to_load;
+        std::vector<std::string> mods_with_softdep_to_load;
+        std::mutex vector_lock;
+
+        // Find independent modules and modules only having soft dependencies
+        for (const auto& [it_mod, it_dep] : mod_with_deps) {
+            if (it_dep.size() == 1 && mod_with_softdeps[it_mod].empty()) {
+                mods_path_to_load.emplace_back(*(it_dep.begin()));
+            } else if (it_dep.size() == 1) {
+                mods_with_softdep_to_load.emplace_back(it_mod);
+            }
+        }
+
+        // Load independent modules in parallel
+        auto thread_function = [&] {
+            std::unique_lock lk(vector_lock);
+            while (!mods_path_to_load.empty()) {
+                auto mod_path_to_load = std::move(mods_path_to_load.back());
+                mods_path_to_load.pop_back();
+
+                lk.unlock();
+                ret &= Insmod(mod_path_to_load, "");
+                lk.lock();
+            }
+        };
+
+        std::generate_n(std::back_inserter(threads), num_threads,
+                        [&] { return std::thread(thread_function); });
+
+        // Wait for the threads.
+        for (auto& thread : threads) {
+            thread.join();
+        }
+
+        // Since we cannot assure if these soft dependencies tree are overlap,
+        // we loaded these modules one by one.
+        for (auto dep = mods_with_softdep_to_load.rbegin(); dep != mods_with_softdep_to_load.rend();
+             dep++) {
+            ret &= LoadWithAliases(*dep, true);
+        }
+
+        std::lock_guard guard(module_loaded_lock_);
+        // Remove loaded module form mod_with_deps and soft dependencies of other modules
+        for (const auto& module_loaded : module_loaded_) {
+            mod_with_deps.erase(module_loaded);
+
+            for (auto& [mod, softdeps] : mod_with_softdeps) {
+                softdeps.erase(module_loaded);
+            }
+        }
+
+        // Remove loaded module form dependencies of other modules which are not loaded yet
+        for (const auto& module_loaded_path : module_loaded_paths_) {
+            for (auto& [mod, deps] : mod_with_deps) {
+                deps.erase(module_loaded_path);
+            }
+        }
+    }
+
+    return ret;
+}
+
 bool Modprobe::LoadListedModules(bool strict) {
     auto ret = true;
     for (const auto& module : module_load_) {
diff --git a/libmodprobe/libmodprobe_ext.cpp b/libmodprobe/libmodprobe_ext.cpp
index fb1f5e7..94a1dc4 100644
--- a/libmodprobe/libmodprobe_ext.cpp
+++ b/libmodprobe/libmodprobe_ext.cpp
@@ -54,6 +54,8 @@
     if (ret != 0) {
         if (errno == EEXIST) {
             // Module already loaded
+            std::lock_guard guard(module_loaded_lock_);
+            module_loaded_paths_.emplace(path_name);
             module_loaded_.emplace(canonical_name);
             return true;
         }
@@ -62,6 +64,8 @@
     }
 
     LOG(INFO) << "Loaded kernel module " << path_name;
+    std::lock_guard guard(module_loaded_lock_);
+    module_loaded_paths_.emplace(path_name);
     module_loaded_.emplace(canonical_name);
     module_count_++;
     return true;
@@ -74,6 +78,7 @@
         PLOG(ERROR) << "Failed to remove module '" << module_name << "'";
         return false;
     }
+    std::lock_guard guard(module_loaded_lock_);
     module_loaded_.erase(canonical_name);
     return true;
 }
diff --git a/libmodprobe/libmodprobe_test.cpp b/libmodprobe/libmodprobe_test.cpp
index f960b61..f92a2b6 100644
--- a/libmodprobe/libmodprobe_test.cpp
+++ b/libmodprobe/libmodprobe_test.cpp
@@ -188,10 +188,11 @@
 
     EXPECT_TRUE(modules_loaded == expected_after_remove);
 
-    m = Modprobe({dir.path});
-    EXPECT_FALSE(m.LoadWithAliases("test4", true));
-    while (modules_loaded.size() > 0) EXPECT_TRUE(m.Remove(modules_loaded.front()));
-    EXPECT_TRUE(m.LoadListedModules());
+    Modprobe m2({dir.path});
+
+    EXPECT_FALSE(m2.LoadWithAliases("test4", true));
+    while (modules_loaded.size() > 0) EXPECT_TRUE(m2.Remove(modules_loaded.front()));
+    EXPECT_TRUE(m2.LoadListedModules());
 
     GTEST_LOG_(INFO) << "Expected modules loaded after enabling blocklist (in order):";
     for (auto i = expected_modules_blocklist_enabled.begin();
diff --git a/libprocessgroup/processgroup.cpp b/libprocessgroup/processgroup.cpp
index 96b5537..b0fcb5f 100644
--- a/libprocessgroup/processgroup.cpp
+++ b/libprocessgroup/processgroup.cpp
@@ -69,6 +69,23 @@
     return true;
 }
 
+static bool CgroupGetMemcgAppsPath(std::string* path) {
+    CgroupController controller = CgroupMap::GetInstance().FindController("memory");
+
+    if (!controller.HasValue()) {
+        return false;
+    }
+
+    if (path) {
+        *path = controller.path();
+        if (controller.version() == 1) {
+            *path += "/apps";
+        }
+    }
+
+    return true;
+}
+
 bool CgroupGetControllerFromPath(const std::string& path, std::string* cgroup_name) {
     auto controller = CgroupMap::GetInstance().FindControllerByPath(path);
 
@@ -199,13 +216,13 @@
     LOG(VERBOSE) << "removeAllProcessGroups()";
 
     std::vector<std::string> cgroups;
-    std::string path;
+    std::string path, memcg_apps_path;
 
     if (CgroupGetControllerPath(CGROUPV2_CONTROLLER_NAME, &path)) {
         cgroups.push_back(path);
     }
-    if (CgroupGetControllerPath("memory", &path)) {
-        cgroups.push_back(path + "/apps");
+    if (CgroupGetMemcgAppsPath(&memcg_apps_path) && memcg_apps_path != path) {
+        cgroups.push_back(memcg_apps_path);
     }
 
     for (std::string cgroup_root_path : cgroups) {
@@ -411,10 +428,11 @@
         int err = RemoveProcessGroup(cgroup, uid, initialPid, retries);
 
         if (isMemoryCgroupSupported() && UsePerAppMemcg()) {
-            std::string memory_path;
-            CgroupGetControllerPath("memory", &memory_path);
-            memory_path += "/apps";
-            if (RemoveProcessGroup(memory_path.c_str(), uid, initialPid, retries)) return -1;
+            std::string memcg_apps_path;
+            if (CgroupGetMemcgAppsPath(&memcg_apps_path) &&
+                RemoveProcessGroup(memcg_apps_path.c_str(), uid, initialPid, retries) < 0) {
+                return -1;
+            }
         }
 
         return err;
@@ -491,10 +509,12 @@
         return -EINVAL;
     }
 
-    if (isMemoryCgroupSupported() && UsePerAppMemcg()) {
-        CgroupGetControllerPath("memory", &cgroup);
-        cgroup += "/apps";
-        int ret = createProcessGroupInternal(uid, initialPid, cgroup, false);
+    if (std::string memcg_apps_path;
+        isMemoryCgroupSupported() && UsePerAppMemcg() && CgroupGetMemcgAppsPath(&memcg_apps_path)) {
+        // Note by bvanassche: passing 'false' as fourth argument below implies that the v1
+        // hierarchy is used. It is not clear to me whether the above conditions guarantee that the
+        // v1 hierarchy is used.
+        int ret = createProcessGroupInternal(uid, initialPid, memcg_apps_path, false);
         if (ret != 0) {
             return ret;
         }
diff --git a/libprocessgroup/profiles/task_profiles.json b/libprocessgroup/profiles/task_profiles.json
index b668dcb..7e03964 100644
--- a/libprocessgroup/profiles/task_profiles.json
+++ b/libprocessgroup/profiles/task_profiles.json
@@ -16,14 +16,21 @@
       "File": "top-app/cpus"
     },
     {
+      "Name": "MemStats",
+      "Controller": "memory",
+      "File": "memory.stat"
+    },
+    {
       "Name": "MemLimit",
       "Controller": "memory",
-      "File": "memory.limit_in_bytes"
+      "File": "memory.limit_in_bytes",
+      "FileV2": "memory.max"
     },
     {
       "Name": "MemSoftLimit",
       "Controller": "memory",
-      "File": "memory.soft_limit_in_bytes"
+      "File": "memory.soft_limit_in_bytes",
+      "FileV2": "memory.low"
     },
     {
       "Name": "MemSwappiness",
@@ -31,6 +38,26 @@
       "File": "memory.swappiness"
     },
     {
+      "Name": "MemUsage",
+      "Controller": "memory",
+      "File": "memory.usage_in_bytes"
+    },
+    {
+      "Name": "MemAndSwapUsage",
+      "Controller": "memory",
+      "File": "memory.memsw.usage_in_bytes"
+    },
+    {
+      "Name": "MemPressureLevel",
+      "Controller": "memory",
+      "File": "memory.pressure_level"
+    },
+    {
+      "Name": "MemCgroupEventControl",
+      "Controller": "memory",
+      "File": "cgroup.event_control"
+    },
+    {
       "Name": "UClampMin",
       "Controller": "cpu",
       "File": "cpu.uclamp.min"
diff --git a/libprocessgroup/profiles/task_profiles.proto b/libprocessgroup/profiles/task_profiles.proto
index 2a09217..ebcd9b5 100644
--- a/libprocessgroup/profiles/task_profiles.proto
+++ b/libprocessgroup/profiles/task_profiles.proto
@@ -25,12 +25,13 @@
     repeated AggregateProfiles aggregateprofiles = 3 [json_name = "AggregateProfiles"];
 }
 
-// Next: 5
+// Next: 6
 message Attribute {
     string name = 1 [json_name = "Name"];
     string controller = 2 [json_name = "Controller"];
     string file = 3 [json_name = "File"];
-    string optional = 4 [json_name = "Optional"];
+    string filev2 = 4 [json_name = "FileV2"];
+    string optional = 5 [json_name = "Optional"];
 }
 
 // Next: 3
diff --git a/libprocessgroup/setup/cgroup_map_write.cpp b/libprocessgroup/setup/cgroup_map_write.cpp
index 3121d24..992cc2e 100644
--- a/libprocessgroup/setup/cgroup_map_write.cpp
+++ b/libprocessgroup/setup/cgroup_map_write.cpp
@@ -263,8 +263,18 @@
                 return false;
             }
 
-            result = mount("none", controller->path(), "cgroup2", MS_NODEV | MS_NOEXEC | MS_NOSUID,
-                           nullptr);
+            // The memory_recursiveprot mount option has been introduced by kernel commit
+            // 8a931f801340 ("mm: memcontrol: recursive memory.low protection"; v5.7). Try first to
+            // mount with that option enabled. If mounting fails because the kernel is too old,
+            // retry without that mount option.
+            if (mount("none", controller->path(), "cgroup2", MS_NODEV | MS_NOEXEC | MS_NOSUID,
+                      "memory_recursiveprot") < 0) {
+                LOG(INFO) << "Mounting memcg with memory_recursiveprot failed. Retrying without.";
+                if (mount("none", controller->path(), "cgroup2", MS_NODEV | MS_NOEXEC | MS_NOSUID,
+                          nullptr) < 0) {
+                    PLOG(ERROR) << "Failed to mount cgroup v2";
+                }
+            }
 
             // selinux permissions change after mounting, so it's ok to change mode and owner now
             if (!ChangeDirModeAndOwner(controller->path(), descriptor.mode(), descriptor.uid(),
diff --git a/libprocessgroup/task_profiles.cpp b/libprocessgroup/task_profiles.cpp
index 4a2bf38..78a316a 100644
--- a/libprocessgroup/task_profiles.cpp
+++ b/libprocessgroup/task_profiles.cpp
@@ -129,11 +129,12 @@
         return true;
     }
 
+    const std::string& file_name =
+            controller()->version() == 2 && !file_v2_name_.empty() ? file_v2_name_ : file_name_;
     if (subgroup.empty()) {
-        *path = StringPrintf("%s/%s", controller()->path(), file_name_.c_str());
+        *path = StringPrintf("%s/%s", controller()->path(), file_name.c_str());
     } else {
-        *path = StringPrintf("%s/%s/%s", controller()->path(), subgroup.c_str(),
-                             file_name_.c_str());
+        *path = StringPrintf("%s/%s/%s", controller()->path(), subgroup.c_str(), file_name.c_str());
     }
     return true;
 }
@@ -633,12 +634,19 @@
         std::string name = attr[i]["Name"].asString();
         std::string controller_name = attr[i]["Controller"].asString();
         std::string file_attr = attr[i]["File"].asString();
+        std::string file_v2_attr = attr[i]["FileV2"].asString();
+
+        if (!file_v2_attr.empty() && file_attr.empty()) {
+            LOG(ERROR) << "Attribute " << name << " has FileV2 but no File property";
+            return false;
+        }
 
         auto controller = cg_map.FindController(controller_name);
         if (controller.HasValue()) {
             auto iter = attributes_.find(name);
             if (iter == attributes_.end()) {
-                attributes_[name] = std::make_unique<ProfileAttribute>(controller, file_attr);
+                attributes_[name] =
+                        std::make_unique<ProfileAttribute>(controller, file_attr, file_v2_attr);
             } else {
                 iter->second->Reset(controller, file_attr);
             }
diff --git a/libprocessgroup/task_profiles.h b/libprocessgroup/task_profiles.h
index 4747511..df08f65 100644
--- a/libprocessgroup/task_profiles.h
+++ b/libprocessgroup/task_profiles.h
@@ -37,8 +37,12 @@
 
 class ProfileAttribute : public IProfileAttribute {
   public:
-    ProfileAttribute(const CgroupController& controller, const std::string& file_name)
-        : controller_(controller), file_name_(file_name) {}
+    // Cgroup attributes may have different names in the v1 and v2 hierarchies. If `file_v2_name` is
+    // not empty, `file_name` is the name for the v1 hierarchy and `file_v2_name` is the name for
+    // the v2 hierarchy. If `file_v2_name` is empty, `file_name` is used for both hierarchies.
+    ProfileAttribute(const CgroupController& controller, const std::string& file_name,
+                     const std::string& file_v2_name)
+        : controller_(controller), file_name_(file_name), file_v2_name_(file_v2_name) {}
     ~ProfileAttribute() = default;
 
     const CgroupController* controller() const override { return &controller_; }
@@ -50,6 +54,7 @@
   private:
     CgroupController controller_;
     std::string file_name_;
+    std::string file_v2_name_;
 };
 
 // Abstract profile element
diff --git a/rootdir/etc/TEST_MAPPING b/rootdir/etc/TEST_MAPPING
index e4d3d5e..1c7b716 100644
--- a/rootdir/etc/TEST_MAPPING
+++ b/rootdir/etc/TEST_MAPPING
@@ -3,5 +3,10 @@
     {
       "name": "CtsBionicTestCases"
     }
+  ],
+  "hwasan-postsubmit": [
+    {
+      "name": "CtsBionicTestCases"
+    }
   ]
 }
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 404d7ae..7ad1c3c 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -1008,12 +1008,6 @@
     # module, delete if not.
     exec - system system -- /system/bin/tzdatacheck /apex/com.android.tzdata/etc/tz /data/misc/zoneinfo
 
-    # If there is no post-fs-data action in the init.<device>.rc file, you
-    # must uncomment this line, otherwise encrypted filesystems
-    # won't work.
-    # Set indication (checked by vold) that we have finished this action
-    #setprop vold.post_fs_data_done 1
-
     # sys.memfd_use set to false by default, which keeps it disabled
     # until it is confirmed that apps and vendor processes don't make
     # IOCTLs on ashmem fds any more.
diff --git a/trusty/keymaster/keymint/TEST_MAPPING b/trusty/keymaster/keymint/TEST_MAPPING
index 2400ccd..ae24fb4 100644
--- a/trusty/keymaster/keymint/TEST_MAPPING
+++ b/trusty/keymaster/keymint/TEST_MAPPING
@@ -3,5 +3,10 @@
     {
       "name" : "vts_treble_vintf_framework_test"
     }
+  ],
+  "hwasan-postsubmit" : [
+    {
+      "name" : "vts_treble_vintf_framework_test"
+    }
   ]
 }
\ No newline at end of file