Update HintManager to use NDK backend

- Update HintManager and its aidl types to use NDK backend
- Switch HintManager to using PowerHAL's WorkDuration
- Update SDK WorkDuration.java to no longer be parcelable,
    since it isn't being sent over binders anymore.
- Remove duplicate WorkDuration in powermanager in favor of PowerHAL's

Bug: 315894228
Test: atest HintManagerServiceTest
Test: atest PerformanceHintNativeTestCases
Test: atest PerformanceHintManagerTest
Change-Id: Ibc5a3aa96e73a225fce980811694ee02bdabb963
diff --git a/native/android/Android.bp b/native/android/Android.bp
index 752ebdf..0cfb237 100644
--- a/native/android/Android.bp
+++ b/native/android/Android.bp
@@ -83,6 +83,7 @@
         "libinput",
         "libutils",
         "libbinder",
+        "libbinder_ndk",
         "libui",
         "libgui",
         "libharfbuzz_ng", // Only for including hb.h via minikin
@@ -100,6 +101,7 @@
         "android.hardware.configstore-utils",
         "android.os.flags-aconfig-cc",
         "libnativedisplay",
+        "libfmq",
     ],
 
     static_libs: [
diff --git a/native/android/performance_hint.cpp b/native/android/performance_hint.cpp
index 279f9d6..8227bdb 100644
--- a/native/android/performance_hint.cpp
+++ b/native/android/performance_hint.cpp
@@ -18,15 +18,15 @@
 
 #include <aidl/android/hardware/power/SessionHint.h>
 #include <aidl/android/hardware/power/SessionMode.h>
+#include <aidl/android/hardware/power/SessionTag.h>
+#include <aidl/android/hardware/power/WorkDuration.h>
+#include <aidl/android/os/IHintManager.h>
+#include <aidl/android/os/IHintSession.h>
 #include <android-base/stringprintf.h>
-#include <android/WorkDuration.h>
-#include <android/os/IHintManager.h>
-#include <android/os/IHintSession.h>
+#include <android/binder_manager.h>
+#include <android/binder_status.h>
 #include <android/performance_hint.h>
 #include <android/trace.h>
-#include <binder/Binder.h>
-#include <binder/IBinder.h>
-#include <binder/IServiceManager.h>
 #include <inttypes.h>
 #include <performance_hint_private.h>
 #include <utils/SystemClock.h>
@@ -37,22 +37,25 @@
 #include <vector>
 
 using namespace android;
-using namespace android::os;
+using namespace aidl::android::os;
 
 using namespace std::chrono_literals;
 
-using AidlSessionHint = aidl::android::hardware::power::SessionHint;
-using AidlSessionMode = aidl::android::hardware::power::SessionMode;
+using HalSessionHint = aidl::android::hardware::power::SessionHint;
+using HalSessionMode = aidl::android::hardware::power::SessionMode;
+using HalWorkDuration = aidl::android::hardware::power::WorkDuration;
+
 using android::base::StringPrintf;
 
 struct APerformanceHintSession;
 
 constexpr int64_t SEND_HINT_TIMEOUT = std::chrono::nanoseconds(100ms).count();
+struct AWorkDuration : public HalWorkDuration {};
 
 struct APerformanceHintManager {
 public:
     static APerformanceHintManager* getInstance();
-    APerformanceHintManager(sp<IHintManager> service, int64_t preferredRateNanos);
+    APerformanceHintManager(std::shared_ptr<IHintManager> service, int64_t preferredRateNanos);
     APerformanceHintManager() = delete;
     ~APerformanceHintManager() = default;
 
@@ -61,17 +64,28 @@
     int64_t getPreferredRateNanos() const;
 
 private:
-    static APerformanceHintManager* create(sp<IHintManager> iHintManager);
+    // Necessary to create an empty binder object
+    static void* tokenStubOnCreate(void*) {
+        return nullptr;
+    }
+    static void tokenStubOnDestroy(void*) {}
+    static binder_status_t tokenStubOnTransact(AIBinder*, transaction_code_t, const AParcel*,
+                                               AParcel*) {
+        return STATUS_OK;
+    }
 
-    sp<IHintManager> mHintManager;
-    const sp<IBinder> mToken = sp<BBinder>::make();
+    static APerformanceHintManager* create(std::shared_ptr<IHintManager> iHintManager);
+
+    std::shared_ptr<IHintManager> mHintManager;
+    ndk::SpAIBinder mToken;
     const int64_t mPreferredRateNanos;
 };
 
 struct APerformanceHintSession {
 public:
-    APerformanceHintSession(sp<IHintManager> hintManager, sp<IHintSession> session,
-                            int64_t preferredRateNanos, int64_t targetDurationNanos);
+    APerformanceHintSession(std::shared_ptr<IHintManager> hintManager,
+                            std::shared_ptr<IHintSession> session, int64_t preferredRateNanos,
+                            int64_t targetDurationNanos);
     APerformanceHintSession() = delete;
     ~APerformanceHintSession();
 
@@ -86,10 +100,10 @@
 private:
     friend struct APerformanceHintManager;
 
-    int reportActualWorkDurationInternal(WorkDuration* workDuration);
+    int reportActualWorkDurationInternal(AWorkDuration* workDuration);
 
-    sp<IHintManager> mHintManager;
-    sp<IHintSession> mHintSession;
+    std::shared_ptr<IHintManager> mHintManager;
+    std::shared_ptr<IHintSession> mHintSession;
     // HAL preferred update rate
     const int64_t mPreferredRateNanos;
     // Target duration for choosing update rate
@@ -101,7 +115,7 @@
     // Last hint reported from sendHint indexed by hint value
     std::vector<int64_t> mLastHintSentTimestamp;
     // Cached samples
-    std::vector<WorkDuration> mActualWorkDurations;
+    std::vector<HalWorkDuration> mActualWorkDurations;
     std::string mSessionName;
     static int32_t sIDCounter;
     // The most recent set of thread IDs
@@ -114,19 +128,24 @@
     void traceTargetDuration(int64_t targetDuration);
 };
 
-static IHintManager* gIHintManagerForTesting = nullptr;
+static std::shared_ptr<IHintManager>* gIHintManagerForTesting = nullptr;
 static APerformanceHintManager* gHintManagerForTesting = nullptr;
 int32_t APerformanceHintSession::sIDCounter = 0;
 
 // ===================================== APerformanceHintManager implementation
-APerformanceHintManager::APerformanceHintManager(sp<IHintManager> manager,
+APerformanceHintManager::APerformanceHintManager(std::shared_ptr<IHintManager> manager,
                                                  int64_t preferredRateNanos)
-      : mHintManager(std::move(manager)), mPreferredRateNanos(preferredRateNanos) {}
+      : mHintManager(std::move(manager)), mPreferredRateNanos(preferredRateNanos) {
+    static AIBinder_Class* tokenBinderClass =
+            AIBinder_Class_define("phm_token", tokenStubOnCreate, tokenStubOnDestroy,
+                                  tokenStubOnTransact);
+    mToken = ndk::SpAIBinder(AIBinder_new(tokenBinderClass, nullptr));
+}
 
 APerformanceHintManager* APerformanceHintManager::getInstance() {
     if (gHintManagerForTesting) return gHintManagerForTesting;
     if (gIHintManagerForTesting) {
-        APerformanceHintManager* manager = create(gIHintManagerForTesting);
+        APerformanceHintManager* manager = create(*gIHintManagerForTesting);
         gIHintManagerForTesting = nullptr;
         return manager;
     }
@@ -134,20 +153,19 @@
     return instance;
 }
 
-APerformanceHintManager* APerformanceHintManager::create(sp<IHintManager> manager) {
+APerformanceHintManager* APerformanceHintManager::create(std::shared_ptr<IHintManager> manager) {
     if (!manager) {
-        manager = interface_cast<IHintManager>(
-                defaultServiceManager()->checkService(String16("performance_hint")));
+        manager = IHintManager::fromBinder(
+                ndk::SpAIBinder(AServiceManager_waitForService("performance_hint")));
     }
     if (manager == nullptr) {
         ALOGE("%s: PerformanceHint service is not ready ", __FUNCTION__);
         return nullptr;
     }
     int64_t preferredRateNanos = -1L;
-    binder::Status ret = manager->getHintSessionPreferredRate(&preferredRateNanos);
+    ndk::ScopedAStatus ret = manager->getHintSessionPreferredRate(&preferredRateNanos);
     if (!ret.isOk()) {
-        ALOGE("%s: PerformanceHint cannot get preferred rate. %s", __FUNCTION__,
-              ret.exceptionMessage().c_str());
+        ALOGE("%s: PerformanceHint cannot get preferred rate. %s", __FUNCTION__, ret.getMessage());
         return nullptr;
     }
     if (preferredRateNanos <= 0) {
@@ -159,8 +177,8 @@
 APerformanceHintSession* APerformanceHintManager::createSession(
         const int32_t* threadIds, size_t size, int64_t initialTargetWorkDurationNanos) {
     std::vector<int32_t> tids(threadIds, threadIds + size);
-    sp<IHintSession> session;
-    binder::Status ret =
+    std::shared_ptr<IHintSession> session;
+    ndk::ScopedAStatus ret =
             mHintManager->createHintSession(mToken, tids, initialTargetWorkDurationNanos, &session);
     if (!ret.isOk() || !session) {
         return nullptr;
@@ -179,8 +197,8 @@
 
 // ===================================== APerformanceHintSession implementation
 
-APerformanceHintSession::APerformanceHintSession(sp<IHintManager> hintManager,
-                                                 sp<IHintSession> session,
+APerformanceHintSession::APerformanceHintSession(std::shared_ptr<IHintManager> hintManager,
+                                                 std::shared_ptr<IHintSession> session,
                                                  int64_t preferredRateNanos,
                                                  int64_t targetDurationNanos)
       : mHintManager(hintManager),
@@ -189,17 +207,17 @@
         mTargetDurationNanos(targetDurationNanos),
         mFirstTargetMetTimestamp(0),
         mLastTargetMetTimestamp(0) {
-    const std::vector<AidlSessionHint> sessionHintRange{ndk::enum_range<AidlSessionHint>().begin(),
-                                                        ndk::enum_range<AidlSessionHint>().end()};
+    const std::vector<HalSessionHint> sessionHintRange{ndk::enum_range<HalSessionHint>().begin(),
+                                                       ndk::enum_range<HalSessionHint>().end()};
 
     mLastHintSentTimestamp = std::vector<int64_t>(sessionHintRange.size(), 0);
     mSessionName = android::base::StringPrintf("ADPF Session %" PRId32, ++sIDCounter);
 }
 
 APerformanceHintSession::~APerformanceHintSession() {
-    binder::Status ret = mHintSession->close();
+    ndk::ScopedAStatus ret = mHintSession->close();
     if (!ret.isOk()) {
-        ALOGE("%s: HintSession close failed: %s", __FUNCTION__, ret.exceptionMessage().c_str());
+        ALOGE("%s: HintSession close failed: %s", __FUNCTION__, ret.getMessage());
     }
 }
 
@@ -208,10 +226,10 @@
         ALOGE("%s: targetDurationNanos must be positive", __FUNCTION__);
         return EINVAL;
     }
-    binder::Status ret = mHintSession->updateTargetWorkDuration(targetDurationNanos);
+    ndk::ScopedAStatus ret = mHintSession->updateTargetWorkDuration(targetDurationNanos);
     if (!ret.isOk()) {
         ALOGE("%s: HintSession updateTargetWorkDuration failed: %s", __FUNCTION__,
-              ret.exceptionMessage().c_str());
+              ret.getMessage());
         return EPIPE;
     }
     mTargetDurationNanos = targetDurationNanos;
@@ -228,9 +246,12 @@
 }
 
 int APerformanceHintSession::reportActualWorkDuration(int64_t actualDurationNanos) {
-    WorkDuration workDuration(0, actualDurationNanos, actualDurationNanos, 0);
+    HalWorkDuration workDuration{.durationNanos = actualDurationNanos,
+                                 .workPeriodStartTimestampNanos = 0,
+                                 .cpuDurationNanos = actualDurationNanos,
+                                 .gpuDurationNanos = 0};
 
-    return reportActualWorkDurationInternal(&workDuration);
+    return reportActualWorkDurationInternal(static_cast<AWorkDuration*>(&workDuration));
 }
 
 int APerformanceHintSession::sendHint(SessionHint hint) {
@@ -238,17 +259,17 @@
         ALOGE("%s: invalid session hint %d", __FUNCTION__, hint);
         return EINVAL;
     }
-    int64_t now = elapsedRealtimeNano();
+    int64_t now = uptimeNanos();
 
     // Limit sendHint to a pre-detemined rate for safety
     if (now < (mLastHintSentTimestamp[hint] + SEND_HINT_TIMEOUT)) {
         return 0;
     }
 
-    binder::Status ret = mHintSession->sendHint(hint);
+    ndk::ScopedAStatus ret = mHintSession->sendHint(hint);
 
     if (!ret.isOk()) {
-        ALOGE("%s: HintSession sendHint failed: %s", __FUNCTION__, ret.exceptionMessage().c_str());
+        ALOGE("%s: HintSession sendHint failed: %s", __FUNCTION__, ret.getMessage());
         return EPIPE;
     }
     mLastHintSentTimestamp[hint] = now;
@@ -261,12 +282,12 @@
         return EINVAL;
     }
     std::vector<int32_t> tids(threadIds, threadIds + size);
-    binder::Status ret = mHintManager->setHintSessionThreads(mHintSession, tids);
+    ndk::ScopedAStatus ret = mHintManager->setHintSessionThreads(mHintSession, tids);
     if (!ret.isOk()) {
-        ALOGE("%s: failed: %s", __FUNCTION__, ret.exceptionMessage().c_str());
-        if (ret.exceptionCode() == binder::Status::Exception::EX_ILLEGAL_ARGUMENT) {
+        ALOGE("%s: failed: %s", __FUNCTION__, ret.getMessage());
+        if (ret.getExceptionCode() == EX_ILLEGAL_ARGUMENT) {
             return EINVAL;
-        } else if (ret.exceptionCode() == binder::Status::Exception::EX_SECURITY) {
+        } else if (ret.getExceptionCode() == EX_SECURITY) {
             return EPERM;
         }
         return EPIPE;
@@ -279,9 +300,9 @@
 
 int APerformanceHintSession::getThreadIds(int32_t* const threadIds, size_t* size) {
     std::vector<int32_t> tids;
-    binder::Status ret = mHintManager->getHintSessionThreadIds(mHintSession, &tids);
+    ndk::ScopedAStatus ret = mHintManager->getHintSessionThreadIds(mHintSession, &tids);
     if (!ret.isOk()) {
-        ALOGE("%s: failed: %s", __FUNCTION__, ret.exceptionMessage().c_str());
+        ALOGE("%s: failed: %s", __FUNCTION__, ret.getMessage());
         return EPIPE;
     }
 
@@ -301,28 +322,27 @@
 }
 
 int APerformanceHintSession::setPreferPowerEfficiency(bool enabled) {
-    binder::Status ret =
-            mHintSession->setMode(static_cast<int32_t>(AidlSessionMode::POWER_EFFICIENCY), enabled);
+    ndk::ScopedAStatus ret =
+            mHintSession->setMode(static_cast<int32_t>(HalSessionMode::POWER_EFFICIENCY), enabled);
 
     if (!ret.isOk()) {
         ALOGE("%s: HintSession setPreferPowerEfficiency failed: %s", __FUNCTION__,
-              ret.exceptionMessage().c_str());
+              ret.getMessage());
         return EPIPE;
     }
     tracePowerEfficient(enabled);
     return OK;
 }
 
-int APerformanceHintSession::reportActualWorkDuration(AWorkDuration* aWorkDuration) {
-    WorkDuration* workDuration = static_cast<WorkDuration*>(aWorkDuration);
+int APerformanceHintSession::reportActualWorkDuration(AWorkDuration* workDuration) {
     return reportActualWorkDurationInternal(workDuration);
 }
 
-int APerformanceHintSession::reportActualWorkDurationInternal(WorkDuration* workDuration) {
-    int64_t actualTotalDurationNanos = workDuration->actualTotalDurationNanos;
+int APerformanceHintSession::reportActualWorkDurationInternal(AWorkDuration* workDuration) {
+    int64_t actualTotalDurationNanos = workDuration->durationNanos;
     int64_t now = uptimeNanos();
-    workDuration->timestampNanos = now;
-    traceActualDuration(workDuration->actualTotalDurationNanos);
+    workDuration->timeStampNanos = now;
+    traceActualDuration(workDuration->durationNanos);
     mActualWorkDurations.push_back(std::move(*workDuration));
 
     if (actualTotalDurationNanos >= mTargetDurationNanos) {
@@ -346,14 +366,14 @@
         mLastTargetMetTimestamp = now;
     }
 
-    binder::Status ret = mHintSession->reportActualWorkDuration2(mActualWorkDurations);
+    ndk::ScopedAStatus ret = mHintSession->reportActualWorkDuration2(mActualWorkDurations);
     if (!ret.isOk()) {
         ALOGE("%s: HintSession reportActualWorkDuration failed: %s", __FUNCTION__,
-              ret.exceptionMessage().c_str());
+              ret.getMessage());
         mFirstTargetMetTimestamp = 0;
         mLastTargetMetTimestamp = 0;
         traceBatchSize(mActualWorkDurations.size());
-        return ret.exceptionCode() == binder::Status::EX_ILLEGAL_ARGUMENT ? EINVAL : EPIPE;
+        return ret.getExceptionCode() == EX_ILLEGAL_ARGUMENT ? EINVAL : EPIPE;
     }
     mActualWorkDurations.clear();
     traceBatchSize(0);
@@ -481,18 +501,16 @@
                                                AWorkDuration* workDurationPtr) {
     VALIDATE_PTR(session)
     VALIDATE_PTR(workDurationPtr)
-    WorkDuration& workDuration = *static_cast<WorkDuration*>(workDurationPtr);
-    VALIDATE_INT(workDuration.workPeriodStartTimestampNanos, > 0)
-    VALIDATE_INT(workDuration.actualTotalDurationNanos, > 0)
-    VALIDATE_INT(workDuration.actualCpuDurationNanos, >= 0)
-    VALIDATE_INT(workDuration.actualGpuDurationNanos, >= 0)
-    VALIDATE_INT(workDuration.actualGpuDurationNanos + workDuration.actualCpuDurationNanos, > 0)
+    VALIDATE_INT(workDurationPtr->durationNanos, > 0)
+    VALIDATE_INT(workDurationPtr->workPeriodStartTimestampNanos, > 0)
+    VALIDATE_INT(workDurationPtr->cpuDurationNanos, >= 0)
+    VALIDATE_INT(workDurationPtr->gpuDurationNanos, >= 0)
+    VALIDATE_INT(workDurationPtr->gpuDurationNanos + workDurationPtr->cpuDurationNanos, > 0)
     return session->reportActualWorkDuration(workDurationPtr);
 }
 
 AWorkDuration* AWorkDuration_create() {
-    WorkDuration* workDuration = new WorkDuration();
-    return static_cast<AWorkDuration*>(workDuration);
+    return new AWorkDuration();
 }
 
 void AWorkDuration_release(AWorkDuration* aWorkDuration) {
@@ -500,37 +518,36 @@
     delete aWorkDuration;
 }
 
-void AWorkDuration_setWorkPeriodStartTimestampNanos(AWorkDuration* aWorkDuration,
-                                                    int64_t workPeriodStartTimestampNanos) {
-    VALIDATE_PTR(aWorkDuration)
-    WARN_INT(workPeriodStartTimestampNanos, > 0)
-    static_cast<WorkDuration*>(aWorkDuration)->workPeriodStartTimestampNanos =
-            workPeriodStartTimestampNanos;
-}
-
 void AWorkDuration_setActualTotalDurationNanos(AWorkDuration* aWorkDuration,
                                                int64_t actualTotalDurationNanos) {
     VALIDATE_PTR(aWorkDuration)
     WARN_INT(actualTotalDurationNanos, > 0)
-    static_cast<WorkDuration*>(aWorkDuration)->actualTotalDurationNanos = actualTotalDurationNanos;
+    aWorkDuration->durationNanos = actualTotalDurationNanos;
+}
+
+void AWorkDuration_setWorkPeriodStartTimestampNanos(AWorkDuration* aWorkDuration,
+                                                    int64_t workPeriodStartTimestampNanos) {
+    VALIDATE_PTR(aWorkDuration)
+    WARN_INT(workPeriodStartTimestampNanos, > 0)
+    aWorkDuration->workPeriodStartTimestampNanos = workPeriodStartTimestampNanos;
 }
 
 void AWorkDuration_setActualCpuDurationNanos(AWorkDuration* aWorkDuration,
                                              int64_t actualCpuDurationNanos) {
     VALIDATE_PTR(aWorkDuration)
     WARN_INT(actualCpuDurationNanos, >= 0)
-    static_cast<WorkDuration*>(aWorkDuration)->actualCpuDurationNanos = actualCpuDurationNanos;
+    aWorkDuration->cpuDurationNanos = actualCpuDurationNanos;
 }
 
 void AWorkDuration_setActualGpuDurationNanos(AWorkDuration* aWorkDuration,
                                              int64_t actualGpuDurationNanos) {
     VALIDATE_PTR(aWorkDuration)
     WARN_INT(actualGpuDurationNanos, >= 0)
-    static_cast<WorkDuration*>(aWorkDuration)->actualGpuDurationNanos = actualGpuDurationNanos;
+    aWorkDuration->gpuDurationNanos = actualGpuDurationNanos;
 }
 
 void APerformanceHint_setIHintManagerForTesting(void* iManager) {
     delete gHintManagerForTesting;
     gHintManagerForTesting = nullptr;
-    gIHintManagerForTesting = static_cast<IHintManager*>(iManager);
+    gIHintManagerForTesting = static_cast<std::shared_ptr<IHintManager>*>(iManager);
 }
diff --git a/native/android/tests/performance_hint/Android.bp b/native/android/tests/performance_hint/Android.bp
index fdc1bc6..608d5d8 100644
--- a/native/android/tests/performance_hint/Android.bp
+++ b/native/android/tests/performance_hint/Android.bp
@@ -39,6 +39,7 @@
         "libandroid",
         "liblog",
         "libbinder",
+        "libbinder_ndk",
         "libpowermanager",
         "libutils",
     ],
diff --git a/native/android/tests/performance_hint/PerformanceHintNativeTest.cpp b/native/android/tests/performance_hint/PerformanceHintNativeTest.cpp
index 4553b49..bfbe34e 100644
--- a/native/android/tests/performance_hint/PerformanceHintNativeTest.cpp
+++ b/native/android/tests/performance_hint/PerformanceHintNativeTest.cpp
@@ -16,11 +16,11 @@
 
 #define LOG_TAG "PerformanceHintNativeTest"
 
-#include <android/WorkDuration.h>
-#include <android/os/IHintManager.h>
-#include <android/os/IHintSession.h>
+#include <aidl/android/hardware/power/WorkDuration.h>
+#include <aidl/android/os/IHintManager.h>
+#include <android/binder_manager.h>
+#include <android/binder_status.h>
 #include <android/performance_hint.h>
-#include <binder/IBinder.h>
 #include <gmock/gmock.h>
 #include <gtest/gtest.h>
 #include <performance_hint_private.h>
@@ -28,48 +28,54 @@
 #include <memory>
 #include <vector>
 
-using android::binder::Status;
-using android::os::IHintManager;
-using android::os::IHintSession;
+using aidl::android::hardware::power::WorkDuration;
+using aidl::android::os::IHintManager;
+using aidl::android::os::IHintSession;
+using ndk::ScopedAStatus;
+using ndk::SpAIBinder;
 
 using namespace android;
 using namespace testing;
 
 class MockIHintManager : public IHintManager {
 public:
-    MOCK_METHOD(Status, createHintSession,
-                (const sp<IBinder>& token, const ::std::vector<int32_t>& tids,
-                 int64_t durationNanos, ::android::sp<IHintSession>* _aidl_return),
+    MOCK_METHOD(ScopedAStatus, createHintSession,
+                (const SpAIBinder& token, const ::std::vector<int32_t>& tids, int64_t durationNanos,
+                 std::shared_ptr<IHintSession>* _aidl_return),
                 (override));
-    MOCK_METHOD(Status, getHintSessionPreferredRate, (int64_t * _aidl_return), (override));
-    MOCK_METHOD(Status, setHintSessionThreads,
-                (const sp<IHintSession>& hintSession, const ::std::vector<int32_t>& tids),
+    MOCK_METHOD(ScopedAStatus, getHintSessionPreferredRate, (int64_t * _aidl_return), (override));
+    MOCK_METHOD(ScopedAStatus, setHintSessionThreads,
+                (const std::shared_ptr<IHintSession>& hintSession,
+                 const ::std::vector<int32_t>& tids),
                 (override));
-    MOCK_METHOD(Status, getHintSessionThreadIds,
-                (const sp<IHintSession>& hintSession, ::std::vector<int32_t>* tids), (override));
-    MOCK_METHOD(IBinder*, onAsBinder, (), (override));
+    MOCK_METHOD(ScopedAStatus, getHintSessionThreadIds,
+                (const std::shared_ptr<IHintSession>& hintSession, ::std::vector<int32_t>* tids),
+                (override));
+    MOCK_METHOD(SpAIBinder, asBinder, (), (override));
+    MOCK_METHOD(bool, isRemote, (), (override));
 };
 
 class MockIHintSession : public IHintSession {
 public:
-    MOCK_METHOD(Status, updateTargetWorkDuration, (int64_t targetDurationNanos), (override));
-    MOCK_METHOD(Status, reportActualWorkDuration,
+    MOCK_METHOD(ScopedAStatus, updateTargetWorkDuration, (int64_t targetDurationNanos), (override));
+    MOCK_METHOD(ScopedAStatus, reportActualWorkDuration,
                 (const ::std::vector<int64_t>& actualDurationNanos,
                  const ::std::vector<int64_t>& timeStampNanos),
                 (override));
-    MOCK_METHOD(Status, sendHint, (int32_t hint), (override));
-    MOCK_METHOD(Status, setMode, (int32_t mode, bool enabled), (override));
-    MOCK_METHOD(Status, close, (), (override));
-    MOCK_METHOD(IBinder*, onAsBinder, (), (override));
-    MOCK_METHOD(Status, reportActualWorkDuration2,
-                (const ::std::vector<android::os::WorkDuration>& workDurations), (override));
+    MOCK_METHOD(ScopedAStatus, sendHint, (int32_t hint), (override));
+    MOCK_METHOD(ScopedAStatus, setMode, (int32_t mode, bool enabled), (override));
+    MOCK_METHOD(ScopedAStatus, close, (), (override));
+    MOCK_METHOD(ScopedAStatus, reportActualWorkDuration2,
+                (const ::std::vector<WorkDuration>& workDurations), (override));
+    MOCK_METHOD(SpAIBinder, asBinder, (), (override));
+    MOCK_METHOD(bool, isRemote, (), (override));
 };
 
 class PerformanceHintTest : public Test {
 public:
     void SetUp() override {
-        mMockIHintManager = new StrictMock<MockIHintManager>();
-        APerformanceHint_setIHintManagerForTesting(mMockIHintManager);
+        mMockIHintManager = ndk::SharedRefBase::make<NiceMock<MockIHintManager>>();
+        APerformanceHint_setIHintManagerForTesting(&mMockIHintManager);
     }
 
     void TearDown() override {
@@ -79,15 +85,50 @@
     }
 
     APerformanceHintManager* createManager() {
-        EXPECT_CALL(*mMockIHintManager, getHintSessionPreferredRate(_))
-                .Times(Exactly(1))
-                .WillRepeatedly(DoAll(SetArgPointee<0>(123L), Return(Status())));
+        ON_CALL(*mMockIHintManager, getHintSessionPreferredRate(_))
+                .WillByDefault(DoAll(SetArgPointee<0>(123L), [] { return ScopedAStatus::ok(); }));
         return APerformanceHint_getManager();
     }
+    APerformanceHintSession* createSession(APerformanceHintManager* manager,
+                                           int64_t targetDuration = 56789L) {
+        mMockSession = ndk::SharedRefBase::make<NiceMock<MockIHintSession>>();
 
-    StrictMock<MockIHintManager>* mMockIHintManager = nullptr;
+        std::vector<int32_t> tids;
+        tids.push_back(1);
+        tids.push_back(2);
+
+        ON_CALL(*mMockIHintManager, createHintSession(_, Eq(tids), Eq(targetDuration), _))
+                .WillByDefault(DoAll(SetArgPointee<3>(std::shared_ptr<IHintSession>(mMockSession)),
+                                     [] { return ScopedAStatus::ok(); }));
+        ON_CALL(*mMockIHintManager, setHintSessionThreads(_, _)).WillByDefault([] {
+            return ScopedAStatus::ok();
+        });
+        ON_CALL(*mMockSession, sendHint(_)).WillByDefault([] { return ScopedAStatus::ok(); });
+        ON_CALL(*mMockSession, setMode(_, _)).WillByDefault([] { return ScopedAStatus::ok(); });
+        ON_CALL(*mMockSession, close()).WillByDefault([] { return ScopedAStatus::ok(); });
+        ON_CALL(*mMockSession, updateTargetWorkDuration(_)).WillByDefault([] {
+            return ScopedAStatus::ok();
+        });
+        ON_CALL(*mMockSession, reportActualWorkDuration(_, _)).WillByDefault([] {
+            return ScopedAStatus::ok();
+        });
+        ON_CALL(*mMockSession, reportActualWorkDuration2(_)).WillByDefault([] {
+            return ScopedAStatus::ok();
+        });
+
+        return APerformanceHint_createSession(manager, tids.data(), tids.size(), targetDuration);
+    }
+
+    std::shared_ptr<NiceMock<MockIHintManager>> mMockIHintManager = nullptr;
+    std::shared_ptr<NiceMock<MockIHintSession>> mMockSession = nullptr;
 };
 
+bool equalsWithoutTimestamp(WorkDuration lhs, WorkDuration rhs) {
+    return lhs.workPeriodStartTimestampNanos == rhs.workPeriodStartTimestampNanos &&
+            lhs.cpuDurationNanos == rhs.cpuDurationNanos &&
+            lhs.gpuDurationNanos == rhs.gpuDurationNanos && lhs.durationNanos == rhs.durationNanos;
+}
+
 TEST_F(PerformanceHintTest, TestGetPreferredUpdateRateNanos) {
     APerformanceHintManager* manager = createManager();
     int64_t preferredUpdateRateNanos = APerformanceHint_getPreferredUpdateRateNanos(manager);
@@ -96,25 +137,11 @@
 
 TEST_F(PerformanceHintTest, TestSession) {
     APerformanceHintManager* manager = createManager();
-
-    std::vector<int32_t> tids;
-    tids.push_back(1);
-    tids.push_back(2);
-    int64_t targetDuration = 56789L;
-
-    StrictMock<MockIHintSession>* iSession = new StrictMock<MockIHintSession>();
-    sp<IHintSession> session_sp(iSession);
-
-    EXPECT_CALL(*mMockIHintManager, createHintSession(_, Eq(tids), Eq(targetDuration), _))
-            .Times(Exactly(1))
-            .WillRepeatedly(DoAll(SetArgPointee<3>(std::move(session_sp)), Return(Status())));
-
-    APerformanceHintSession* session =
-            APerformanceHint_createSession(manager, tids.data(), tids.size(), targetDuration);
+    APerformanceHintSession* session = createSession(manager);
     ASSERT_TRUE(session);
 
     int64_t targetDurationNanos = 10;
-    EXPECT_CALL(*iSession, updateTargetWorkDuration(Eq(targetDurationNanos))).Times(Exactly(1));
+    EXPECT_CALL(*mMockSession, updateTargetWorkDuration(Eq(targetDurationNanos))).Times(Exactly(1));
     int result = APerformanceHint_updateTargetWorkDuration(session, targetDurationNanos);
     EXPECT_EQ(0, result);
 
@@ -122,8 +149,7 @@
     int64_t actualDurationNanos = 20;
     std::vector<int64_t> actualDurations;
     actualDurations.push_back(20);
-    EXPECT_CALL(*iSession, reportActualWorkDuration(Eq(actualDurations), _)).Times(Exactly(1));
-    EXPECT_CALL(*iSession, reportActualWorkDuration2(_)).Times(Exactly(1));
+    EXPECT_CALL(*mMockSession, reportActualWorkDuration2(_)).Times(Exactly(1));
     result = APerformanceHint_reportActualWorkDuration(session, actualDurationNanos);
     EXPECT_EQ(0, result);
 
@@ -133,114 +159,70 @@
     EXPECT_EQ(EINVAL, result);
 
     SessionHint hintId = SessionHint::CPU_LOAD_RESET;
-    EXPECT_CALL(*iSession, sendHint(Eq(hintId))).Times(Exactly(1));
+    EXPECT_CALL(*mMockSession, sendHint(Eq(hintId))).Times(Exactly(1));
     result = APerformanceHint_sendHint(session, hintId);
     EXPECT_EQ(0, result);
     usleep(110000); // Sleep for longer than the update timeout.
-    EXPECT_CALL(*iSession, sendHint(Eq(hintId))).Times(Exactly(1));
+    EXPECT_CALL(*mMockSession, sendHint(Eq(hintId))).Times(Exactly(1));
     result = APerformanceHint_sendHint(session, hintId);
     EXPECT_EQ(0, result);
     // Expect to get rate limited if we try to send faster than the limiter allows
-    EXPECT_CALL(*iSession, sendHint(Eq(hintId))).Times(Exactly(0));
+    EXPECT_CALL(*mMockSession, sendHint(Eq(hintId))).Times(Exactly(0));
     result = APerformanceHint_sendHint(session, hintId);
     EXPECT_EQ(0, result);
 
     result = APerformanceHint_sendHint(session, static_cast<SessionHint>(-1));
     EXPECT_EQ(EINVAL, result);
 
-    EXPECT_CALL(*iSession, close()).Times(Exactly(1));
+    EXPECT_CALL(*mMockSession, close()).Times(Exactly(1));
     APerformanceHint_closeSession(session);
 }
 
 TEST_F(PerformanceHintTest, SetThreads) {
     APerformanceHintManager* manager = createManager();
 
-    std::vector<int32_t> tids;
-    tids.push_back(1);
-    tids.push_back(2);
-    int64_t targetDuration = 56789L;
-
-    StrictMock<MockIHintSession>* iSession = new StrictMock<MockIHintSession>();
-    sp<IHintSession> session_sp(iSession);
-
-    EXPECT_CALL(*mMockIHintManager, createHintSession(_, Eq(tids), Eq(targetDuration), _))
-            .Times(Exactly(1))
-            .WillRepeatedly(DoAll(SetArgPointee<3>(std::move(session_sp)), Return(Status())));
-
-    APerformanceHintSession* session =
-            APerformanceHint_createSession(manager, tids.data(), tids.size(), targetDuration);
+    APerformanceHintSession* session = createSession(manager);
     ASSERT_TRUE(session);
 
-    std::vector<int32_t> emptyTids;
-    int result = APerformanceHint_setThreads(session, emptyTids.data(), emptyTids.size());
+    int32_t emptyTids[2];
+    int result = APerformanceHint_setThreads(session, emptyTids, 0);
     EXPECT_EQ(EINVAL, result);
 
     std::vector<int32_t> newTids;
     newTids.push_back(1);
     newTids.push_back(3);
-    EXPECT_CALL(*mMockIHintManager, setHintSessionThreads(_, Eq(newTids)))
-            .Times(Exactly(1))
-            .WillOnce(Return(Status()));
+    EXPECT_CALL(*mMockIHintManager, setHintSessionThreads(_, Eq(newTids))).Times(Exactly(1));
     result = APerformanceHint_setThreads(session, newTids.data(), newTids.size());
     EXPECT_EQ(0, result);
 
-    testing::Mock::VerifyAndClearExpectations(mMockIHintManager);
+    testing::Mock::VerifyAndClearExpectations(mMockIHintManager.get());
     std::vector<int32_t> invalidTids;
-    auto status = Status::fromExceptionCode(binder::Status::Exception::EX_SECURITY);
     invalidTids.push_back(4);
     invalidTids.push_back(6);
     EXPECT_CALL(*mMockIHintManager, setHintSessionThreads(_, Eq(invalidTids)))
             .Times(Exactly(1))
-            .WillOnce(Return(status));
+            .WillOnce(Return(ByMove(ScopedAStatus::fromExceptionCode(EX_SECURITY))));
     result = APerformanceHint_setThreads(session, invalidTids.data(), invalidTids.size());
     EXPECT_EQ(EPERM, result);
 }
 
 TEST_F(PerformanceHintTest, SetPowerEfficient) {
     APerformanceHintManager* manager = createManager();
-
-    std::vector<int32_t> tids;
-    tids.push_back(1);
-    tids.push_back(2);
-    int64_t targetDuration = 56789L;
-
-    StrictMock<MockIHintSession>* iSession = new StrictMock<MockIHintSession>();
-    sp<IHintSession> session_sp(iSession);
-
-    EXPECT_CALL(*mMockIHintManager, createHintSession(_, Eq(tids), Eq(targetDuration), _))
-            .Times(Exactly(1))
-            .WillRepeatedly(DoAll(SetArgPointee<3>(std::move(session_sp)), Return(Status())));
-
-    APerformanceHintSession* session =
-            APerformanceHint_createSession(manager, tids.data(), tids.size(), targetDuration);
+    APerformanceHintSession* session = createSession(manager);
     ASSERT_TRUE(session);
 
-    EXPECT_CALL(*iSession, setMode(_, Eq(true))).Times(Exactly(1));
+    EXPECT_CALL(*mMockSession, setMode(_, Eq(true))).Times(Exactly(1));
     int result = APerformanceHint_setPreferPowerEfficiency(session, true);
     EXPECT_EQ(0, result);
 
-    EXPECT_CALL(*iSession, setMode(_, Eq(false))).Times(Exactly(1));
+    EXPECT_CALL(*mMockSession, setMode(_, Eq(false))).Times(Exactly(1));
     result = APerformanceHint_setPreferPowerEfficiency(session, false);
     EXPECT_EQ(0, result);
 }
 
 TEST_F(PerformanceHintTest, CreateZeroTargetDurationSession) {
     APerformanceHintManager* manager = createManager();
-
-    std::vector<int32_t> tids;
-    tids.push_back(1);
-    tids.push_back(2);
-    int64_t targetDuration = 0;
-
-    StrictMock<MockIHintSession>* iSession = new StrictMock<MockIHintSession>();
-    sp<IHintSession> session_sp(iSession);
-
-    EXPECT_CALL(*mMockIHintManager, createHintSession(_, Eq(tids), Eq(targetDuration), _))
-            .Times(Exactly(1))
-            .WillRepeatedly(DoAll(SetArgPointee<3>(std::move(session_sp)), Return(Status())));
-
-    APerformanceHintSession* session =
-            APerformanceHint_createSession(manager, tids.data(), tids.size(), targetDuration);
+    APerformanceHintSession* session = createSession(manager, 0);
     ASSERT_TRUE(session);
 }
 
@@ -251,12 +233,12 @@
         return false;
     }
     for (int i = 0; i < expected.size(); ++i) {
-        android::os::WorkDuration expectedWorkDuration = expected[i];
-        android::os::WorkDuration actualWorkDuration = arg[i];
-        if (!expectedWorkDuration.equalsWithoutTimestamp(actualWorkDuration)) {
+        WorkDuration expectedWorkDuration = expected[i];
+        WorkDuration actualWorkDuration = arg[i];
+        if (!equalsWithoutTimestamp(expectedWorkDuration, actualWorkDuration)) {
             *result_listener << "WorkDuration at [" << i << "] is different: "
-                             << "Expected: " << expectedWorkDuration
-                             << ", Actual: " << actualWorkDuration;
+                             << "Expected: " << expectedWorkDuration.toString()
+                             << ", Actual: " << actualWorkDuration.toString();
             return false;
         }
     }
@@ -265,92 +247,37 @@
 
 TEST_F(PerformanceHintTest, TestAPerformanceHint_reportActualWorkDuration2) {
     APerformanceHintManager* manager = createManager();
-
-    std::vector<int32_t> tids;
-    tids.push_back(1);
-    tids.push_back(2);
-    int64_t targetDuration = 56789L;
-
-    StrictMock<MockIHintSession>* iSession = new StrictMock<MockIHintSession>();
-    sp<IHintSession> session_sp(iSession);
-
-    EXPECT_CALL(*mMockIHintManager, createHintSession(_, Eq(tids), Eq(targetDuration), _))
-            .Times(Exactly(1))
-            .WillRepeatedly(DoAll(SetArgPointee<3>(std::move(session_sp)), Return(Status())));
-
-    APerformanceHintSession* session =
-            APerformanceHint_createSession(manager, tids.data(), tids.size(), targetDuration);
+    APerformanceHintSession* session = createSession(manager);
     ASSERT_TRUE(session);
 
     int64_t targetDurationNanos = 10;
-    EXPECT_CALL(*iSession, updateTargetWorkDuration(Eq(targetDurationNanos))).Times(Exactly(1));
+    EXPECT_CALL(*mMockSession, updateTargetWorkDuration(Eq(targetDurationNanos))).Times(Exactly(1));
     int result = APerformanceHint_updateTargetWorkDuration(session, targetDurationNanos);
     EXPECT_EQ(0, result);
 
     usleep(2); // Sleep for longer than preferredUpdateRateNanos.
-    {
-        std::vector<android::os::WorkDuration> actualWorkDurations;
-        android::os::WorkDuration workDuration(1, 20, 13, 8);
-        actualWorkDurations.push_back(workDuration);
+    struct TestPair {
+        WorkDuration duration;
+        int expectedResult;
+    };
+    std::vector<TestPair> testPairs{
+            {{1, 20, 1, 13, 8}, OK},       {{1, -20, 1, 13, 8}, EINVAL},
+            {{1, 20, -1, 13, 8}, EINVAL},  {{1, -20, 1, -13, 8}, EINVAL},
+            {{1, -20, 1, 13, -8}, EINVAL},
+    };
+    for (auto&& pair : testPairs) {
+        std::vector<WorkDuration> actualWorkDurations;
+        actualWorkDurations.push_back(pair.duration);
 
-        EXPECT_CALL(*iSession, reportActualWorkDuration2(WorkDurationEq(actualWorkDurations)))
+        EXPECT_CALL(*mMockSession, reportActualWorkDuration2(WorkDurationEq(actualWorkDurations)))
                 .Times(Exactly(1));
         result = APerformanceHint_reportActualWorkDuration2(session,
-                                                            static_cast<AWorkDuration*>(
-                                                                    &workDuration));
-        EXPECT_EQ(0, result);
+                                                            reinterpret_cast<AWorkDuration*>(
+                                                                    &pair.duration));
+        EXPECT_EQ(pair.expectedResult, result);
     }
 
-    {
-        std::vector<android::os::WorkDuration> actualWorkDurations;
-        android::os::WorkDuration workDuration(-1, 20, 13, 8);
-        actualWorkDurations.push_back(workDuration);
-
-        EXPECT_CALL(*iSession, reportActualWorkDuration2(WorkDurationEq(actualWorkDurations)))
-                .Times(Exactly(1));
-        result = APerformanceHint_reportActualWorkDuration2(session,
-                                                            static_cast<AWorkDuration*>(
-                                                                    &workDuration));
-        EXPECT_EQ(22, result);
-    }
-    {
-        std::vector<android::os::WorkDuration> actualWorkDurations;
-        android::os::WorkDuration workDuration(1, -20, 13, 8);
-        actualWorkDurations.push_back(workDuration);
-
-        EXPECT_CALL(*iSession, reportActualWorkDuration2(WorkDurationEq(actualWorkDurations)))
-                .Times(Exactly(1));
-        result = APerformanceHint_reportActualWorkDuration2(session,
-                                                            static_cast<AWorkDuration*>(
-                                                                    &workDuration));
-        EXPECT_EQ(22, result);
-    }
-    {
-        std::vector<android::os::WorkDuration> actualWorkDurations;
-        android::os::WorkDuration workDuration(1, 20, -13, 8);
-        actualWorkDurations.push_back(workDuration);
-
-        EXPECT_CALL(*iSession, reportActualWorkDuration2(WorkDurationEq(actualWorkDurations)))
-                .Times(Exactly(1));
-        result = APerformanceHint_reportActualWorkDuration2(session,
-                                                            static_cast<AWorkDuration*>(
-                                                                    &workDuration));
-        EXPECT_EQ(EINVAL, result);
-    }
-    {
-        std::vector<android::os::WorkDuration> actualWorkDurations;
-        android::os::WorkDuration workDuration(1, 20, 13, -8);
-        actualWorkDurations.push_back(workDuration);
-
-        EXPECT_CALL(*iSession, reportActualWorkDuration2(WorkDurationEq(actualWorkDurations)))
-                .Times(Exactly(1));
-        result = APerformanceHint_reportActualWorkDuration2(session,
-                                                            static_cast<AWorkDuration*>(
-                                                                    &workDuration));
-        EXPECT_EQ(EINVAL, result);
-    }
-
-    EXPECT_CALL(*iSession, close()).Times(Exactly(1));
+    EXPECT_CALL(*mMockSession, close()).Times(Exactly(1));
     APerformanceHint_closeSession(session);
 }