Merge "healthd: *charger_test links to a.h.health@2.x statically."
diff --git a/fastboot/Android.bp b/fastboot/Android.bp
index 339f392..708a677 100644
--- a/fastboot/Android.bp
+++ b/fastboot/Android.bp
@@ -166,8 +166,10 @@
         "android.hardware.boot@1.1",
         "android.hardware.fastboot@1.1",
         "android.hardware.health@2.0",
+        "android.hardware.health-V1-ndk",
         "libasyncio",
         "libbase",
+        "libbinder_ndk",
         "libbootloader_message",
         "libcutils",
         "libext2_uuid",
@@ -183,8 +185,10 @@
     ],
 
     static_libs: [
+        "android.hardware.health-translate-ndk",
         "libc++fs",
         "libhealthhalutils",
+        "libhealthshim",
         "libsnapshot_cow",
         "libsnapshot_nobinder",
         "update_metadata-protos",
diff --git a/fastboot/device/fastboot_device.cpp b/fastboot/device/fastboot_device.cpp
index 64a934d..e6a834e 100644
--- a/fastboot/device/fastboot_device.cpp
+++ b/fastboot/device/fastboot_device.cpp
@@ -21,10 +21,12 @@
 #include <android-base/logging.h>
 #include <android-base/properties.h>
 #include <android-base/strings.h>
+#include <android/binder_manager.h>
 #include <android/hardware/boot/1.0/IBootControl.h>
 #include <android/hardware/fastboot/1.1/IFastboot.h>
 #include <fs_mgr.h>
 #include <fs_mgr/roots.h>
+#include <health-shim/shim.h>
 #include <healthhalutils/HealthHalUtils.h>
 
 #include "constants.h"
@@ -32,16 +34,36 @@
 #include "tcp_client.h"
 #include "usb_client.h"
 
+using std::string_literals::operator""s;
 using android::fs_mgr::EnsurePathUnmounted;
 using android::fs_mgr::Fstab;
 using ::android::hardware::hidl_string;
 using ::android::hardware::boot::V1_0::IBootControl;
 using ::android::hardware::boot::V1_0::Slot;
 using ::android::hardware::fastboot::V1_1::IFastboot;
-using ::android::hardware::health::V2_0::get_health_service;
 
 namespace sph = std::placeholders;
 
+std::shared_ptr<aidl::android::hardware::health::IHealth> get_health_service() {
+    using aidl::android::hardware::health::IHealth;
+    using HidlHealth = android::hardware::health::V2_0::IHealth;
+    using aidl::android::hardware::health::HealthShim;
+    auto service_name = IHealth::descriptor + "/default"s;
+    if (AServiceManager_isDeclared(service_name.c_str())) {
+        ndk::SpAIBinder binder(AServiceManager_waitForService(service_name.c_str()));
+        std::shared_ptr<IHealth> health = IHealth::fromBinder(binder);
+        if (health != nullptr) return health;
+        LOG(WARNING) << "AIDL health service is declared, but it cannot be retrieved.";
+    }
+    LOG(INFO) << "Unable to get AIDL health service, trying HIDL...";
+    android::sp<HidlHealth> hidl_health = android::hardware::health::V2_0::get_health_service();
+    if (hidl_health != nullptr) {
+        return ndk::SharedRefBase::make<HealthShim>(hidl_health);
+    }
+    LOG(WARNING) << "No health implementation is found.";
+    return nullptr;
+}
+
 FastbootDevice::FastbootDevice()
     : kCommandMap({
               {FB_CMD_SET_ACTIVE, SetActiveHandler},
diff --git a/fastboot/device/fastboot_device.h b/fastboot/device/fastboot_device.h
index 3536136..91ffce3 100644
--- a/fastboot/device/fastboot_device.h
+++ b/fastboot/device/fastboot_device.h
@@ -22,10 +22,10 @@
 #include <utility>
 #include <vector>
 
+#include <aidl/android/hardware/health/IHealth.h>
 #include <android/hardware/boot/1.0/IBootControl.h>
 #include <android/hardware/boot/1.1/IBootControl.h>
 #include <android/hardware/fastboot/1.1/IFastboot.h>
-#include <android/hardware/health/2.0/IHealth.h>
 
 #include "commands.h"
 #include "transport.h"
@@ -57,7 +57,7 @@
     android::sp<android::hardware::fastboot::V1_1::IFastboot> fastboot_hal() {
         return fastboot_hal_;
     }
-    android::sp<android::hardware::health::V2_0::IHealth> health_hal() { return health_hal_; }
+    std::shared_ptr<aidl::android::hardware::health::IHealth> health_hal() { return health_hal_; }
 
     void set_active_slot(const std::string& active_slot) { active_slot_ = active_slot; }
 
@@ -67,7 +67,7 @@
     std::unique_ptr<Transport> transport_;
     android::sp<android::hardware::boot::V1_0::IBootControl> boot_control_hal_;
     android::sp<android::hardware::boot::V1_1::IBootControl> boot1_1_;
-    android::sp<android::hardware::health::V2_0::IHealth> health_hal_;
+    std::shared_ptr<aidl::android::hardware::health::IHealth> health_hal_;
     android::sp<android::hardware::fastboot::V1_1::IFastboot> fastboot_hal_;
     std::vector<char> download_data_;
     std::string active_slot_;
diff --git a/fastboot/device/variables.cpp b/fastboot/device/variables.cpp
index ee1eed8..76e9889 100644
--- a/fastboot/device/variables.cpp
+++ b/fastboot/device/variables.cpp
@@ -26,7 +26,6 @@
 #include <android/hardware/boot/1.1/IBootControl.h>
 #include <ext4_utils/ext4_utils.h>
 #include <fs_mgr.h>
-#include <healthhalutils/HealthHalUtils.h>
 #include <liblp/liblp.h>
 
 #include "fastboot_device.h"
@@ -120,23 +119,17 @@
 }
 
 bool GetBatteryVoltageHelper(FastbootDevice* device, int32_t* battery_voltage) {
-    using android::hardware::health::V2_0::HealthInfo;
-    using android::hardware::health::V2_0::Result;
+    using aidl::android::hardware::health::HealthInfo;
 
     auto health_hal = device->health_hal();
     if (!health_hal) {
         return false;
     }
 
-    Result ret;
-    auto ret_val = health_hal->getHealthInfo([&](Result result, HealthInfo info) {
-        *battery_voltage = info.legacy.batteryVoltage;
-        ret = result;
-    });
-    if (!ret_val.isOk() || (ret != Result::SUCCESS)) {
-        return false;
-    }
-
+    HealthInfo health_info;
+    auto res = health_hal->getHealthInfo(&health_info);
+    if (!res.isOk()) return false;
+    *battery_voltage = health_info.batteryVoltageMillivolts;
     return true;
 }
 
diff --git a/fs_mgr/libsnapshot/snapuserd/Android.bp b/fs_mgr/libsnapshot/snapuserd/Android.bp
index 4d86007..84bcb94 100644
--- a/fs_mgr/libsnapshot/snapuserd/Android.bp
+++ b/fs_mgr/libsnapshot/snapuserd/Android.bp
@@ -107,6 +107,12 @@
     ramdisk_available: true,
     vendor_ramdisk_available: true,
     recovery_available: true,
+
+    // Snapuserd segfaults with ThinLTO
+    // http://b/208565717
+    lto: {
+         never: true,
+    }
 }
 
 cc_test {
@@ -181,7 +187,9 @@
         "libstorage_literals_headers",
         "libfiemap_headers",
     ],
-    test_min_api_level: 30,
+    test_options: {
+        min_shipping_api_level: 30,
+    },
     auto_gen_config: true,
     require_root: false,
 }
diff --git a/gatekeeperd/Android.bp b/gatekeeperd/Android.bp
index a7f0c0e..0aedc58 100644
--- a/gatekeeperd/Android.bp
+++ b/gatekeeperd/Android.bp
@@ -29,7 +29,9 @@
     srcs: [
         "gatekeeperd.cpp",
     ],
-
+    defaults: [
+        "keymint_use_latest_hal_aidl_ndk_shared",
+    ],
     shared_libs: [
         "libbinder",
         "libbinder_ndk",
@@ -43,7 +45,6 @@
         "libhidlbase",
         "android.hardware.gatekeeper@1.0",
         "libgatekeeper_aidl",
-        "android.hardware.security.keymint-V1-ndk",
         "android.security.authorization-ndk",
     ],
 
diff --git a/init/README.md b/init/README.md
index ebab073..c102b1f 100644
--- a/init/README.md
+++ b/init/README.md
@@ -641,9 +641,10 @@
   configurations. Intended to be used only once when apexd notifies the mount
   event by setting `apexd.status` to ready.
 
-`restart <service>`
+`restart [--only-if-running] <service>`
 > Stops and restarts a running service, does nothing if the service is currently
-  restarting, otherwise, it just starts the service.
+  restarting, otherwise, it just starts the service. If "--only-if-running" is
+  specified, the service is only restarted if it is already running.
 
 `restorecon <path> [ <path>\* ]`
 > Restore the file named by _path_ to the security context specified
diff --git a/init/builtins.cpp b/init/builtins.cpp
index 98831e1..8045c71 100644
--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -774,8 +774,21 @@
 }
 
 static Result<void> do_restart(const BuiltinArguments& args) {
-    Service* svc = ServiceList::GetInstance().FindService(args[1]);
-    if (!svc) return Error() << "service " << args[1] << " not found";
+    bool only_if_running = false;
+    if (args.size() == 3) {
+        if (args[1] == "--only-if-running") {
+            only_if_running = true;
+        } else {
+            return Error() << "Unknown argument to restart: " << args[1];
+        }
+    }
+
+    const auto& classname = args[args.size() - 1];
+    Service* svc = ServiceList::GetInstance().FindService(classname);
+    if (!svc) return Error() << "service " << classname << " not found";
+    if (only_if_running && !svc->IsRunning()) {
+        return {};
+    }
     svc->Restart();
     return {};
 }
@@ -1453,7 +1466,7 @@
         {"update_linker_config",    {0,     0,    {false,  do_update_linker_config}}},
         {"readahead",               {1,     2,    {true,   do_readahead}}},
         {"remount_userdata",        {0,     0,    {false,  do_remount_userdata}}},
-        {"restart",                 {1,     1,    {false,  do_restart}}},
+        {"restart",                 {1,     2,    {false,  do_restart}}},
         {"restorecon",              {1,     kMax, {true,   do_restorecon}}},
         {"restorecon_recursive",    {1,     kMax, {true,   do_restorecon_recursive}}},
         {"rm",                      {1,     1,    {true,   do_rm}}},
diff --git a/libprocessgroup/profiles/task_profiles.json b/libprocessgroup/profiles/task_profiles.json
index 45d3c7c..b668dcb 100644
--- a/libprocessgroup/profiles/task_profiles.json
+++ b/libprocessgroup/profiles/task_profiles.json
@@ -651,6 +651,10 @@
     {
       "Name": "Dex2OatBootComplete",
       "Profiles": [ "Dex2oatPerformance", "LowIoPriority", "TimerSlackHigh" ]
+    },
+    {
+      "Name": "OtaProfiles",
+      "Profiles": [ "ServiceCapacityLow", "LowIoPriority", "HighEnergySaving" ]
     }
   ]
 }
diff --git a/libprocessgroup/task_profiles.cpp b/libprocessgroup/task_profiles.cpp
index e935f99..3834f91 100644
--- a/libprocessgroup/task_profiles.cpp
+++ b/libprocessgroup/task_profiles.cpp
@@ -144,30 +144,13 @@
     return true;
 }
 
-bool SetCgroupAction::IsAppDependentPath(const std::string& path) {
-    return path.find("<uid>", 0) != std::string::npos || path.find("<pid>", 0) != std::string::npos;
-}
-
-SetCgroupAction::SetCgroupAction(const CgroupController& c, const std::string& p)
-    : controller_(c), path_(p) {
-    // file descriptors for app-dependent paths can't be cached
-    if (IsAppDependentPath(path_)) {
-        // file descriptor is not cached
-        fd_.reset(FDS_APP_DEPENDENT);
-        return;
-    }
-
-    // file descriptor can be cached later on request
-    fd_.reset(FDS_NOT_CACHED);
-}
-
-void SetCgroupAction::EnableResourceCaching() {
+void CachedFdProfileAction::EnableResourceCaching() {
     std::lock_guard<std::mutex> lock(fd_mutex_);
     if (fd_ != FDS_NOT_CACHED) {
         return;
     }
 
-    std::string tasks_path = controller_.GetTasksFilePath(path_);
+    std::string tasks_path = GetPath();
 
     if (access(tasks_path.c_str(), W_OK) != 0) {
         // file is not accessible
@@ -185,7 +168,7 @@
     fd_ = std::move(fd);
 }
 
-void SetCgroupAction::DropResourceCaching() {
+void CachedFdProfileAction::DropResourceCaching() {
     std::lock_guard<std::mutex> lock(fd_mutex_);
     if (fd_ == FDS_NOT_CACHED) {
         return;
@@ -194,6 +177,26 @@
     fd_.reset(FDS_NOT_CACHED);
 }
 
+bool CachedFdProfileAction::IsAppDependentPath(const std::string& path) {
+    return path.find("<uid>", 0) != std::string::npos || path.find("<pid>", 0) != std::string::npos;
+}
+
+void CachedFdProfileAction::InitFd(const std::string& path) {
+    // file descriptors for app-dependent paths can't be cached
+    if (IsAppDependentPath(path)) {
+        // file descriptor is not cached
+        fd_.reset(FDS_APP_DEPENDENT);
+        return;
+    }
+    // file descriptor can be cached later on request
+    fd_.reset(FDS_NOT_CACHED);
+}
+
+SetCgroupAction::SetCgroupAction(const CgroupController& c, const std::string& p)
+    : controller_(c), path_(p) {
+    InitFd(controller_.GetTasksFilePath(path_));
+}
+
 bool SetCgroupAction::AddTidToCgroup(int tid, int fd, const char* controller_name) {
     if (tid <= 0) {
         return true;
@@ -270,7 +273,7 @@
     std::string tasks_path = controller()->GetTasksFilePath(path_);
     unique_fd tmp_fd(TEMP_FAILURE_RETRY(open(tasks_path.c_str(), O_WRONLY | O_CLOEXEC)));
     if (tmp_fd < 0) {
-        PLOG(WARNING) << "Failed to open " << tasks_path << ": " << strerror(errno);
+        PLOG(WARNING) << "Failed to open " << tasks_path;
         return false;
     }
     if (!AddTidToCgroup(tid, tmp_fd, controller()->name())) {
@@ -281,37 +284,73 @@
     return true;
 }
 
-bool WriteFileAction::ExecuteForProcess(uid_t uid, pid_t pid) const {
-    std::string filepath(filepath_), value(value_);
+WriteFileAction::WriteFileAction(const std::string& path, const std::string& value,
+                                 bool logfailures)
+    : path_(path), value_(value), logfailures_(logfailures) {
+    InitFd(path_);
+}
 
-    filepath = StringReplace(filepath, "<uid>", std::to_string(uid), true);
-    filepath = StringReplace(filepath, "<pid>", std::to_string(pid), true);
-    value = StringReplace(value, "<uid>", std::to_string(uid), true);
-    value = StringReplace(value, "<pid>", std::to_string(pid), true);
+bool WriteFileAction::WriteValueToFile(const std::string& value, const std::string& path,
+                                       bool logfailures) {
+    // Use WriteStringToFd instead of WriteStringToFile because the latter will open file with
+    // O_TRUNC which causes kernfs_mutex contention
+    unique_fd tmp_fd(TEMP_FAILURE_RETRY(open(path.c_str(), O_WRONLY | O_CLOEXEC)));
 
-    if (!WriteStringToFile(value, filepath)) {
-        if (logfailures_) PLOG(ERROR) << "Failed to write '" << value << "' to " << filepath;
+    if (tmp_fd < 0) {
+        if (logfailures) PLOG(WARNING) << "Failed to open " << path;
+        return false;
+    }
+
+    if (!WriteStringToFd(value, tmp_fd)) {
+        if (logfailures) PLOG(ERROR) << "Failed to write '" << value << "' to " << path;
         return false;
     }
 
     return true;
 }
 
+bool WriteFileAction::ExecuteForProcess(uid_t uid, pid_t pid) const {
+    std::lock_guard<std::mutex> lock(fd_mutex_);
+    std::string value(value_);
+    std::string path(path_);
+
+    value = StringReplace(value, "<uid>", std::to_string(uid), true);
+    value = StringReplace(value, "<pid>", std::to_string(pid), true);
+    path = StringReplace(path, "<uid>", std::to_string(uid), true);
+    path = StringReplace(path, "<pid>", std::to_string(pid), true);
+
+    return WriteValueToFile(value, path, logfailures_);
+}
+
 bool WriteFileAction::ExecuteForTask(int tid) const {
-    std::string filepath(filepath_), value(value_);
+    std::lock_guard<std::mutex> lock(fd_mutex_);
+    std::string value(value_);
     int uid = getuid();
 
-    filepath = StringReplace(filepath, "<uid>", std::to_string(uid), true);
-    filepath = StringReplace(filepath, "<pid>", std::to_string(tid), true);
     value = StringReplace(value, "<uid>", std::to_string(uid), true);
     value = StringReplace(value, "<pid>", std::to_string(tid), true);
 
-    if (!WriteStringToFile(value, filepath)) {
-        if (logfailures_) PLOG(ERROR) << "Failed to write '" << value << "' to " << filepath;
+    if (IsFdValid()) {
+        // fd is cached, reuse it
+        if (!WriteStringToFd(value, fd_)) {
+            if (logfailures_) PLOG(ERROR) << "Failed to write '" << value << "' to " << path_;
+            return false;
+        }
+        return true;
+    }
+
+    if (fd_ == FDS_INACCESSIBLE) {
+        // no permissions to access the file, ignore
+        return true;
+    }
+
+    if (fd_ == FDS_APP_DEPENDENT) {
+        // application-dependent path can't be used with tid
+        PLOG(ERROR) << "Application profile can't be applied to a thread";
         return false;
     }
 
-    return true;
+    return WriteValueToFile(value, path_, logfailures_);
 }
 
 bool ApplyProfileAction::ExecuteForProcess(uid_t uid, pid_t pid) const {
diff --git a/libprocessgroup/task_profiles.h b/libprocessgroup/task_profiles.h
index 97c38f4..278892d 100644
--- a/libprocessgroup/task_profiles.h
+++ b/libprocessgroup/task_profiles.h
@@ -108,50 +108,67 @@
     std::string value_;
 };
 
-// Set cgroup profile element
-class SetCgroupAction : public ProfileAction {
+// Abstract profile element for cached fd
+class CachedFdProfileAction : public ProfileAction {
   public:
-    SetCgroupAction(const CgroupController& c, const std::string& p);
-
-    virtual bool ExecuteForProcess(uid_t uid, pid_t pid) const;
-    virtual bool ExecuteForTask(int tid) const;
     virtual void EnableResourceCaching();
     virtual void DropResourceCaching();
 
-    const CgroupController* controller() const { return &controller_; }
-    std::string path() const { return path_; }
-
-  private:
+  protected:
     enum FdState {
         FDS_INACCESSIBLE = -1,
         FDS_APP_DEPENDENT = -2,
         FDS_NOT_CACHED = -3,
     };
 
-    CgroupController controller_;
-    std::string path_;
     android::base::unique_fd fd_;
     mutable std::mutex fd_mutex_;
 
     static bool IsAppDependentPath(const std::string& path);
-    static bool AddTidToCgroup(int tid, int fd, const char* controller_name);
 
+    void InitFd(const std::string& path);
     bool IsFdValid() const { return fd_ > FDS_INACCESSIBLE; }
+
+    virtual const std::string GetPath() const = 0;
 };
 
-// Write to file action
-class WriteFileAction : public ProfileAction {
+// Set cgroup profile element
+class SetCgroupAction : public CachedFdProfileAction {
   public:
-    WriteFileAction(const std::string& filepath, const std::string& value,
-                    bool logfailures) noexcept
-        : filepath_(filepath), value_(value), logfailures_(logfailures) {}
+    SetCgroupAction(const CgroupController& c, const std::string& p);
 
     virtual bool ExecuteForProcess(uid_t uid, pid_t pid) const;
     virtual bool ExecuteForTask(int tid) const;
 
+    const CgroupController* controller() const { return &controller_; }
+
+  protected:
+    const std::string GetPath() const override { return controller_.GetTasksFilePath(path_); }
+
   private:
-    std::string filepath_, value_;
+    CgroupController controller_;
+    std::string path_;
+
+    static bool AddTidToCgroup(int tid, int fd, const char* controller_name);
+};
+
+// Write to file action
+class WriteFileAction : public CachedFdProfileAction {
+  public:
+    WriteFileAction(const std::string& path, const std::string& value, bool logfailures);
+
+    virtual bool ExecuteForProcess(uid_t uid, pid_t pid) const;
+    virtual bool ExecuteForTask(int tid) const;
+
+  protected:
+    const std::string GetPath() const override { return path_; }
+
+  private:
+    std::string path_, value_;
     bool logfailures_;
+
+    static bool WriteValueToFile(const std::string& value, const std::string& path,
+                                 bool logfailures);
 };
 
 class TaskProfile {
diff --git a/libutils/Threads.cpp b/libutils/Threads.cpp
index 6e293c7..3bf5779 100644
--- a/libutils/Threads.cpp
+++ b/libutils/Threads.cpp
@@ -317,10 +317,7 @@
     if (pri >= ANDROID_PRIORITY_BACKGROUND) {
         rc = SetTaskProfiles(tid, {"SCHED_SP_SYSTEM"}, true) ? 0 : -1;
     } else if (curr_pri >= ANDROID_PRIORITY_BACKGROUND) {
-        SchedPolicy policy = SP_FOREGROUND;
-        // Change to the sched policy group of the process.
-        get_sched_policy(getpid(), &policy);
-        rc = SetTaskProfiles(tid, {get_sched_policy_profile_name(policy)}, true) ? 0 : -1;
+        rc = SetTaskProfiles(tid, {"SCHED_SP_FOREGROUND"}, true) ? 0 : -1;
     }
 
     if (rc) {
diff --git a/storaged/Android.bp b/storaged/Android.bp
index b557dee..7960af3 100644
--- a/storaged/Android.bp
+++ b/storaged/Android.bp
@@ -24,8 +24,10 @@
     shared_libs: [
         "android.hardware.health@1.0",
         "android.hardware.health@2.0",
+        "android.hardware.health-V1-ndk",
         "libbase",
         "libbinder",
+        "libbinder_ndk",
         "libcutils",
         "libhidlbase",
         "liblog",
@@ -35,6 +37,12 @@
         "packagemanager_aidl-cpp",
     ],
 
+    static_libs: [
+        "android.hardware.health-translate-ndk",
+        "libhealthhalutils",
+        "libhealthshim",
+    ],
+
     cflags: [
         "-Wall",
         "-Werror",
@@ -67,7 +75,6 @@
         ":storaged_aidl_private",
     ],
 
-    static_libs: ["libhealthhalutils"],
     header_libs: ["libbatteryservice_headers"],
 
     logtags: ["EventLogTags.logtags"],
@@ -90,7 +97,6 @@
     srcs: ["main.cpp"],
 
     static_libs: [
-        "libhealthhalutils",
         "libstoraged",
     ],
 }
@@ -107,9 +113,11 @@
     srcs: ["tests/storaged_test.cpp"],
 
     static_libs: [
-        "libhealthhalutils",
         "libstoraged",
     ],
+    test_suites: [
+        "general-tests",
+    ],
 }
 
 // AIDL interface between storaged and framework.jar
diff --git a/storaged/include/storaged.h b/storaged/include/storaged.h
index 79b5d41..e120271 100644
--- a/storaged/include/storaged.h
+++ b/storaged/include/storaged.h
@@ -28,6 +28,7 @@
 
 #include <utils/Mutex.h>
 
+#include <aidl/android/hardware/health/IHealth.h>
 #include <android/hardware/health/2.0/IHealth.h>
 
 #define FRIEND_TEST(test_case_name, test_name) \
@@ -67,6 +68,8 @@
 // UID IO threshold in bytes
 #define DEFAULT_PERIODIC_CHORES_UID_IO_THRESHOLD ( 1024 * 1024 * 1024ULL )
 
+class storaged_t;
+
 struct storaged_config {
     int periodic_chores_interval_unit;
     int periodic_chores_interval_disk_stats_publish;
@@ -75,15 +78,33 @@
     int event_time_check_usec;  // check how much cputime spent in event loop
 };
 
-class storaged_t : public android::hardware::health::V2_0::IHealthInfoCallback,
-                   public android::hardware::hidl_death_recipient {
+struct HealthServicePair {
+    std::shared_ptr<aidl::android::hardware::health::IHealth> aidl_health;
+    android::sp<android::hardware::health::V2_0::IHealth> hidl_health;
+    static HealthServicePair get();
+};
+
+class hidl_health_death_recipient : public android::hardware::hidl_death_recipient {
+  public:
+    hidl_health_death_recipient(const android::sp<android::hardware::health::V2_0::IHealth>& health)
+        : mHealth(health) {}
+    void serviceDied(uint64_t cookie, const wp<::android::hidl::base::V1_0::IBase>& who);
+
+  private:
+    android::sp<android::hardware::health::V2_0::IHealth> mHealth;
+};
+
+class storaged_t : public RefBase {
   private:
     time_t mTimer;
     storaged_config mConfig;
     unique_ptr<disk_stats_monitor> mDsm;
     uid_monitor mUidm;
     time_t mStarttime;
-    sp<android::hardware::health::V2_0::IHealth> health;
+    std::shared_ptr<aidl::android::hardware::health::IHealth> health;
+    sp<android::hardware::hidl_death_recipient> hidl_death_recp;
+    ndk::ScopedAIBinder_DeathRecipient aidl_death_recp;
+    shared_ptr<aidl::android::hardware::health::IHealthInfoCallback> aidl_health_callback;
     unique_ptr<storage_info_t> storage_info;
     static const uint32_t current_version;
     Mutex proto_lock;
@@ -135,10 +156,6 @@
     void add_user_ce(userid_t user_id);
     void remove_user_ce(userid_t user_id);
 
-    virtual ::android::hardware::Return<void> healthInfoChanged(
-        const ::android::hardware::health::V2_0::HealthInfo& info);
-    void serviceDied(uint64_t cookie, const wp<::android::hidl::base::V1_0::IBase>& who);
-
     void report_storage_info();
 
     void flush_protos(unordered_map<int, StoragedProto>* protos);
diff --git a/storaged/include/storaged_diskstats.h b/storaged/include/storaged_diskstats.h
index 0b93ba6..3996ef6 100644
--- a/storaged/include/storaged_diskstats.h
+++ b/storaged/include/storaged_diskstats.h
@@ -19,7 +19,7 @@
 
 #include <stdint.h>
 
-#include <android/hardware/health/2.0/IHealth.h>
+#include <aidl/android/hardware/health/IHealth.h>
 
 // number of attributes diskstats has
 #define DISK_STATS_SIZE ( 11 )
@@ -162,7 +162,7 @@
     const double mSigma;
     struct disk_perf mMean;
     struct disk_perf mStd;
-    android::sp<android::hardware::health::V2_0::IHealth> mHealth;
+    std::shared_ptr<aidl::android::hardware::health::IHealth> mHealth;
 
     void update_mean();
     void update_std();
@@ -173,14 +173,15 @@
     void update(struct disk_stats* stats);
 
 public:
-  disk_stats_monitor(const android::sp<android::hardware::health::V2_0::IHealth>& healthService,
+  disk_stats_monitor(const std::shared_ptr<aidl::android::hardware::health::IHealth>& healthService,
                      uint32_t window_size = 5, double sigma = 1.0)
       : DISK_STATS_PATH(
-            healthService != nullptr
-                ? nullptr
-                : (access(MMC_DISK_STATS_PATH, R_OK) == 0
-                       ? MMC_DISK_STATS_PATH
-                       : (access(SDA_DISK_STATS_PATH, R_OK) == 0 ? SDA_DISK_STATS_PATH : nullptr))),
+                healthService != nullptr
+                        ? nullptr
+                        : (access(MMC_DISK_STATS_PATH, R_OK) == 0
+                                   ? MMC_DISK_STATS_PATH
+                                   : (access(SDA_DISK_STATS_PATH, R_OK) == 0 ? SDA_DISK_STATS_PATH
+                                                                             : nullptr))),
         mPrevious(),
         mAccumulate(),
         mAccumulate_pub(),
diff --git a/storaged/include/storaged_info.h b/storaged/include/storaged_info.h
index 9c3d0e7..83c97ad 100644
--- a/storaged/include/storaged_info.h
+++ b/storaged/include/storaged_info.h
@@ -21,7 +21,7 @@
 
 #include <chrono>
 
-#include <android/hardware/health/2.0/IHealth.h>
+#include <aidl/android/hardware/health/IHealth.h>
 #include <utils/Mutex.h>
 
 #include "storaged.h"
@@ -71,8 +71,8 @@
 
   public:
     static storage_info_t* get_storage_info(
-        const sp<android::hardware::health::V2_0::IHealth>& healthService);
-    virtual ~storage_info_t() {};
+            const shared_ptr<aidl::android::hardware::health::IHealth>& healthService);
+    virtual ~storage_info_t(){};
     virtual void report() {};
     void load_perf_history_proto(const IOPerfHistory& perf_history);
     void refresh(IOPerfHistory* perf_history);
@@ -105,14 +105,14 @@
 
 class health_storage_info_t : public storage_info_t {
   private:
-    using IHealth = hardware::health::V2_0::IHealth;
-    using StorageInfo = hardware::health::V2_0::StorageInfo;
+    using IHealth = aidl::android::hardware::health::IHealth;
+    using StorageInfo = aidl::android::hardware::health::StorageInfo;
 
-    sp<IHealth> mHealth;
+    shared_ptr<IHealth> mHealth;
     void set_values_from_hal_storage_info(const StorageInfo& halInfo);
 
   public:
-    health_storage_info_t(const sp<IHealth>& service) : mHealth(service){};
+    health_storage_info_t(const shared_ptr<IHealth>& service) : mHealth(service){};
     virtual ~health_storage_info_t() {}
     virtual void report();
 };
diff --git a/storaged/storaged.cpp b/storaged/storaged.cpp
index b7aa89f..fb855f7 100644
--- a/storaged/storaged.cpp
+++ b/storaged/storaged.cpp
@@ -28,12 +28,16 @@
 #include <sstream>
 #include <string>
 
+#include <aidl/android/hardware/health/BnHealthInfoCallback.h>
 #include <android-base/file.h>
 #include <android-base/logging.h>
 #include <android-base/unique_fd.h>
+#include <android/binder_ibinder.h>
+#include <android/binder_manager.h>
 #include <android/hidl/manager/1.0/IServiceManager.h>
 #include <batteryservice/BatteryServiceConstants.h>
 #include <cutils/properties.h>
+#include <health-shim/shim.h>
 #include <healthhalutils/HealthHalUtils.h>
 #include <hidl/HidlTransportSupport.h>
 #include <hwbinder/IPCThreadState.h>
@@ -64,26 +68,59 @@
 
 const uint32_t storaged_t::current_version = 4;
 
+using aidl::android::hardware::health::BatteryStatus;
+using aidl::android::hardware::health::BnHealthInfoCallback;
+using aidl::android::hardware::health::HealthInfo;
+using aidl::android::hardware::health::IHealth;
+using aidl::android::hardware::health::IHealthInfoCallback;
 using android::hardware::interfacesEqual;
-using android::hardware::Return;
-using android::hardware::health::V1_0::BatteryStatus;
-using android::hardware::health::V1_0::toString;
 using android::hardware::health::V2_0::get_health_service;
-using android::hardware::health::V2_0::HealthInfo;
-using android::hardware::health::V2_0::IHealth;
-using android::hardware::health::V2_0::Result;
 using android::hidl::manager::V1_0::IServiceManager;
+using HidlHealth = android::hardware::health::V2_0::IHealth;
+using aidl::android::hardware::health::HealthShim;
+using ndk::ScopedAIBinder_DeathRecipient;
+using ndk::ScopedAStatus;
 
+HealthServicePair HealthServicePair::get() {
+    HealthServicePair ret;
+    auto service_name = IHealth::descriptor + "/default"s;
+    if (AServiceManager_isDeclared(service_name.c_str())) {
+        ndk::SpAIBinder binder(AServiceManager_waitForService(service_name.c_str()));
+        ret.aidl_health = IHealth::fromBinder(binder);
+        if (ret.aidl_health == nullptr) {
+            LOG(WARNING) << "AIDL health service is declared, but it cannot be retrieved.";
+        }
+    }
+    if (ret.aidl_health == nullptr) {
+        LOG(INFO) << "Unable to get AIDL health service, trying HIDL...";
+        ret.hidl_health = get_health_service();
+        if (ret.hidl_health != nullptr) {
+            ret.aidl_health = ndk::SharedRefBase::make<HealthShim>(ret.hidl_health);
+        }
+    }
+    if (ret.aidl_health == nullptr) {
+        LOG(WARNING) << "health: failed to find IHealth service";
+        return {};
+    }
+    return ret;
+}
 
 inline charger_stat_t is_charger_on(BatteryStatus prop) {
     return (prop == BatteryStatus::CHARGING || prop == BatteryStatus::FULL) ?
         CHARGER_ON : CHARGER_OFF;
 }
 
-Return<void> storaged_t::healthInfoChanged(const HealthInfo& props) {
-    mUidm.set_charger_state(is_charger_on(props.legacy.batteryStatus));
-    return android::hardware::Void();
-}
+class HealthInfoCallback : public BnHealthInfoCallback {
+  public:
+    HealthInfoCallback(uid_monitor* uidm) : mUidm(uidm) {}
+    ScopedAStatus healthInfoChanged(const HealthInfo& info) override {
+        mUidm->set_charger_state(is_charger_on(info.batteryStatus));
+        return ScopedAStatus::ok();
+    }
+
+  private:
+    uid_monitor* mUidm;
+};
 
 void storaged_t::init() {
     init_health_service();
@@ -91,42 +128,59 @@
     storage_info.reset(storage_info_t::get_storage_info(health));
 }
 
+static void onHealthBinderDied(void*) {
+    LOG(ERROR) << "health service died, exiting";
+    android::hardware::IPCThreadState::self()->stopProcess();
+    exit(1);
+}
+
 void storaged_t::init_health_service() {
     if (!mUidm.enabled())
         return;
 
-    health = get_health_service();
-    if (health == NULL) {
-        LOG(WARNING) << "health: failed to find IHealth service";
-        return;
-    }
+    auto [aidlHealth, hidlHealth] = HealthServicePair::get();
+    health = aidlHealth;
+    if (health == nullptr) return;
 
     BatteryStatus status = BatteryStatus::UNKNOWN;
-    auto ret = health->getChargeStatus([&](Result r, BatteryStatus v) {
-        if (r != Result::SUCCESS) {
-            LOG(WARNING) << "health: cannot get battery status " << toString(r);
-            return;
-        }
-        if (v == BatteryStatus::UNKNOWN) {
-            LOG(WARNING) << "health: invalid battery status";
-        }
-        status = v;
-    });
+    auto ret = health->getChargeStatus(&status);
     if (!ret.isOk()) {
-        LOG(WARNING) << "health: get charge status transaction error " << ret.description();
+        LOG(WARNING) << "health: cannot get battery status: " << ret.getDescription();
+    }
+    if (status == BatteryStatus::UNKNOWN) {
+        LOG(WARNING) << "health: invalid battery status";
     }
 
     mUidm.init(is_charger_on(status));
     // register listener after init uid_monitor
-    health->registerCallback(this);
-    health->linkToDeath(this, 0 /* cookie */);
+    aidl_health_callback = std::make_shared<HealthInfoCallback>(&mUidm);
+    ret = health->registerCallback(aidl_health_callback);
+    if (!ret.isOk()) {
+        LOG(WARNING) << "health: failed to register callback: " << ret.getDescription();
+    }
+
+    if (hidlHealth != nullptr) {
+        hidl_death_recp = new hidl_health_death_recipient(hidlHealth);
+        auto ret = hidlHealth->linkToDeath(hidl_death_recp, 0 /* cookie */);
+        if (!ret.isOk()) {
+            LOG(WARNING) << "Failed to link to death (HIDL): " << ret.description();
+        }
+    } else {
+        aidl_death_recp =
+                ScopedAIBinder_DeathRecipient(AIBinder_DeathRecipient_new(onHealthBinderDied));
+        auto ret = AIBinder_linkToDeath(health->asBinder().get(), aidl_death_recp.get(),
+                                        nullptr /* cookie */);
+        if (ret != STATUS_OK) {
+            LOG(WARNING) << "Failed to link to death (AIDL): "
+                         << ScopedAStatus(AStatus_fromStatus(ret)).getDescription();
+        }
+    }
 }
 
-void storaged_t::serviceDied(uint64_t cookie, const wp<::android::hidl::base::V1_0::IBase>& who) {
-    if (health != NULL && interfacesEqual(health, who.promote())) {
-        LOG(ERROR) << "health service died, exiting";
-        android::hardware::IPCThreadState::self()->stopProcess();
-        exit(1);
+void hidl_health_death_recipient::serviceDied(uint64_t cookie,
+                                              const wp<::android::hidl::base::V1_0::IBase>& who) {
+    if (mHealth != nullptr && interfacesEqual(mHealth, who.promote())) {
+        onHealthBinderDied(reinterpret_cast<void*>(cookie));
     } else {
         LOG(ERROR) << "unknown service died";
     }
diff --git a/storaged/storaged_diskstats.cpp b/storaged/storaged_diskstats.cpp
index 52bd4e0..1eae5a1 100644
--- a/storaged/storaged_diskstats.cpp
+++ b/storaged/storaged_diskstats.cpp
@@ -30,11 +30,8 @@
 
 namespace {
 
-using android::sp;
-using android::hardware::health::V2_0::DiskStats;
-using android::hardware::health::V2_0::IHealth;
-using android::hardware::health::V2_0::Result;
-using android::hardware::health::V2_0::toString;
+using aidl::android::hardware::health::DiskStats;
+using aidl::android::hardware::health::IHealth;
 
 #ifdef DEBUG
 void log_debug_disk_perf(struct disk_perf* perf, const char* type) {
@@ -121,39 +118,30 @@
     dst->io_in_queue = src.ioInQueue;
 }
 
-bool get_disk_stats_from_health_hal(const sp<IHealth>& service, struct disk_stats* stats) {
+bool get_disk_stats_from_health_hal(const std::shared_ptr<IHealth>& service,
+                                    struct disk_stats* stats) {
     struct timespec ts;
     if (!get_time(&ts)) {
         return false;
     }
 
-    bool success = false;
-    auto ret = service->getDiskStats([&success, stats](auto result, const auto& halStats) {
-        if (result == Result::NOT_SUPPORTED) {
-            LOG(DEBUG) << "getDiskStats is not supported on health HAL.";
-            return;
+    std::vector<DiskStats> halStats;
+    auto ret = service->getDiskStats(&halStats);
+    if (ret.isOk()) {
+        if (halStats.size() > 0) {
+            convert_hal_disk_stats(stats, halStats[0]);
+            init_disk_stats_other(ts, stats);
+            return true;
         }
-        if (result != Result::SUCCESS || halStats.size() == 0) {
-            LOG(ERROR) << "getDiskStats failed with result " << toString(result) << " and size "
-                       << halStats.size();
-            return;
-        }
-
-        convert_hal_disk_stats(stats, halStats[0]);
-        success = true;
-    });
-
-    if (!ret.isOk()) {
-        LOG(ERROR) << "getDiskStats failed with " << ret.description();
+        LOG(ERROR) << "getDiskStats succeeded but size is 0";
         return false;
     }
-
-    if (!success) {
+    if (ret.getExceptionCode() == EX_UNSUPPORTED_OPERATION) {
+        LOG(DEBUG) << "getDiskStats is not supported on health HAL.";
         return false;
     }
-
-    init_disk_stats_other(ts, stats);
-    return true;
+    LOG(ERROR) << "getDiskStats failed with " << ret.getDescription();
+    return false;
 }
 
 struct disk_perf get_disk_perf(struct disk_stats* stats)
diff --git a/storaged/storaged_info.cpp b/storaged/storaged_info.cpp
index bb21829..3e646e0 100644
--- a/storaged/storaged_info.cpp
+++ b/storaged/storaged_info.cpp
@@ -36,9 +36,8 @@
 using namespace android::base;
 using namespace storaged_proto;
 
-using android::hardware::health::V2_0::IHealth;
-using android::hardware::health::V2_0::Result;
-using android::hardware::health::V2_0::StorageInfo;
+using aidl::android::hardware::health::IHealth;
+using aidl::android::hardware::health::StorageInfo;
 
 const string emmc_info_t::emmc_sysfs = "/sys/bus/mmc/devices/mmc0:0001/";
 const char* emmc_info_t::emmc_ver_str[9] = {
@@ -57,7 +56,7 @@
 
 } // namespace
 
-storage_info_t* storage_info_t::get_storage_info(const sp<IHealth>& healthService) {
+storage_info_t* storage_info_t::get_storage_info(const shared_ptr<IHealth>& healthService) {
     if (healthService != nullptr) {
         return new health_storage_info_t(healthService);
     }
@@ -326,23 +325,22 @@
 }
 
 void health_storage_info_t::report() {
-    auto ret = mHealth->getStorageInfo([this](auto result, const auto& halInfos) {
-        if (result == Result::NOT_SUPPORTED) {
-            LOG(DEBUG) << "getStorageInfo is not supported on health HAL.";
+    vector<StorageInfo> halInfos;
+    auto ret = mHealth->getStorageInfo(&halInfos);
+    if (ret.isOk()) {
+        if (halInfos.size() != 0) {
+            set_values_from_hal_storage_info(halInfos[0]);
+            publish();
             return;
         }
-        if (result != Result::SUCCESS || halInfos.size() == 0) {
-            LOG(ERROR) << "getStorageInfo failed with result " << toString(result) << " and size "
-                       << halInfos.size();
-            return;
-        }
-        set_values_from_hal_storage_info(halInfos[0]);
-        publish();
-    });
-
-    if (!ret.isOk()) {
-        LOG(ERROR) << "getStorageInfo failed with " << ret.description();
+        LOG(ERROR) << "getStorageInfo succeeded but size is 0";
+        return;
     }
+    if (ret.getExceptionCode() == EX_UNSUPPORTED_OPERATION) {
+        LOG(DEBUG) << "getStorageInfo is not supported on health HAL.";
+        return;
+    }
+    LOG(ERROR) << "getStorageInfo failed with " << ret.getDescription();
 }
 
 void health_storage_info_t::set_values_from_hal_storage_info(const StorageInfo& halInfo) {
diff --git a/storaged/tests/storaged_test.cpp b/storaged/tests/storaged_test.cpp
index 64009c2..bb71bf3 100644
--- a/storaged/tests/storaged_test.cpp
+++ b/storaged/tests/storaged_test.cpp
@@ -25,6 +25,7 @@
 
 #include <gtest/gtest.h>
 
+#include <aidl/android/hardware/health/IHealth.h>
 #include <healthhalutils/HealthHalUtils.h>
 #include <storaged.h>               // data structures
 #include <storaged_utils.h>         // functions to test
@@ -64,20 +65,23 @@
 } // namespace
 
 // the return values of the tested functions should be the expected ones
-const char* DISK_STATS_PATH;
+const char* get_disk_stats_path() {
+    if (access(MMC_DISK_STATS_PATH, R_OK) >= 0) {
+        return MMC_DISK_STATS_PATH;
+    } else if (access(SDA_DISK_STATS_PATH, R_OK) >= 0) {
+        return SDA_DISK_STATS_PATH;
+    } else {
+        return nullptr;
+    }
+}
 TEST(storaged_test, retvals) {
     struct disk_stats stats;
     memset(&stats, 0, sizeof(struct disk_stats));
 
-    if (access(MMC_DISK_STATS_PATH, R_OK) >= 0) {
-        DISK_STATS_PATH = MMC_DISK_STATS_PATH;
-    } else if (access(SDA_DISK_STATS_PATH, R_OK) >= 0) {
-        DISK_STATS_PATH = SDA_DISK_STATS_PATH;
-    } else {
-        return;
-    }
+    auto disk_stats_path = get_disk_stats_path();
+    if (disk_stats_path == nullptr) GTEST_SKIP();
 
-    EXPECT_TRUE(parse_disk_stats(DISK_STATS_PATH, &stats));
+    EXPECT_TRUE(parse_disk_stats(disk_stats_path, &stats));
 
     struct disk_stats old_stats;
     memset(&old_stats, 0, sizeof(struct disk_stats));
@@ -92,7 +96,9 @@
 
 TEST(storaged_test, disk_stats) {
     struct disk_stats stats = {};
-    ASSERT_TRUE(parse_disk_stats(DISK_STATS_PATH, &stats));
+    auto disk_stats_path = get_disk_stats_path();
+    if (disk_stats_path == nullptr) GTEST_SKIP();
+    ASSERT_TRUE(parse_disk_stats(disk_stats_path, &stats));
 
     // every entry of stats (except io_in_flight) should all be greater than 0
     for (uint i = 0; i < DISK_STATS_SIZE; ++i) {
@@ -103,7 +109,7 @@
     // accumulation of the increments should be the same with the overall increment
     struct disk_stats base = {}, tmp = {}, curr, acc = {}, inc[5];
     for (uint i = 0; i < 5; ++i) {
-        ASSERT_TRUE(parse_disk_stats(DISK_STATS_PATH, &curr));
+        ASSERT_TRUE(parse_disk_stats(disk_stats_path, &curr));
         if (i == 0) {
             base = curr;
             tmp = curr;
@@ -235,9 +241,7 @@
 }
 
 TEST(storaged_test, disk_stats_monitor) {
-    using android::hardware::health::V2_0::get_health_service;
-
-    auto healthService = get_health_service();
+    auto [healthService, hidlHealth] = HealthServicePair::get();
 
     // asserting that there is one file for diskstats
     ASSERT_TRUE(healthService != nullptr || access(MMC_DISK_STATS_PATH, R_OK) >= 0 ||
@@ -246,6 +250,13 @@
     // testing if detect() will return the right value
     disk_stats_monitor dsm_detect{healthService};
     ASSERT_TRUE(dsm_detect.enabled());
+
+    // Even if enabled(), healthService may not support disk stats. Check if it is supported.
+    std::vector<aidl::android::hardware::health::DiskStats> halStats;
+    if (healthService->getDiskStats(&halStats).getExceptionCode() == EX_UNSUPPORTED_OPERATION) {
+        GTEST_SKIP();
+    }
+
     // feed monitor with constant perf data for io perf baseline
     // using constant perf is reasonable since the functionality of stream_stats
     // has already been tested
diff --git a/trusty/keymaster/Android.bp b/trusty/keymaster/Android.bp
index 99d9e56..0e916ef 100644
--- a/trusty/keymaster/Android.bp
+++ b/trusty/keymaster/Android.bp
@@ -105,8 +105,10 @@
         "keymint/TrustySharedSecret.cpp",
         "keymint/service.cpp",
     ],
+    defaults: [
+        "keymint_use_latest_hal_aidl_ndk_shared",
+    ],
     shared_libs: [
-        "android.hardware.security.keymint-V1-ndk",
         "android.hardware.security.secureclock-V1-ndk",
         "android.hardware.security.sharedsecret-V1-ndk",
         "lib_android_keymaster_keymint_utils",