Update PowerHAL wrapper support checking behavior

- Updates support checks to check status for UNKNOWN_TRANSACTION
- Adds PowerHintSessionWrapper class to check support on session methods
- Ensures that wrapper methods check the HAL version number for support
- Adds macros to cache returned wrapper call support status

Bug: 324255931
Test: atest libpowermanager_test
Test: atest libsurfaceflinger_unittest:PowerAdvisorTest
Change-Id: I4b329e6b55c53198bb064a34e792be6336e66e27
diff --git a/services/powermanager/Android.bp b/services/powermanager/Android.bp
index 1f72e8b..3ea08fe 100644
--- a/services/powermanager/Android.bp
+++ b/services/powermanager/Android.bp
@@ -17,6 +17,7 @@
         "PowerHalController.cpp",
         "PowerHalLoader.cpp",
         "PowerHalWrapper.cpp",
+        "PowerHintSessionWrapper.cpp",
         "PowerSaveState.cpp",
         "Temperature.cpp",
         "WorkDuration.cpp",
diff --git a/services/powermanager/PowerHalController.cpp b/services/powermanager/PowerHalController.cpp
index bc178bc..40fd097 100644
--- a/services/powermanager/PowerHalController.cpp
+++ b/services/powermanager/PowerHalController.cpp
@@ -57,6 +57,10 @@
     PowerHalLoader::unloadAll();
 }
 
+int32_t HalConnector::getAidlVersion() {
+    return PowerHalLoader::getAidlVersion();
+}
+
 // -------------------------------------------------------------------------------------------------
 
 void PowerHalController::init() {
@@ -77,6 +81,22 @@
     return mConnectedHal;
 }
 
+// Using statement expression macro instead of a method lets the static be
+// scoped to the outer method while dodging the need for a support lookup table
+// This only works for AIDL methods that do not vary supported/unsupported depending
+// on their arguments (not setBoost, setMode) which do their own support checks
+#define CACHE_SUPPORT(version, method)                                    \
+    ({                                                                    \
+        static bool support = mHalConnector->getAidlVersion() >= version; \
+        !support ? decltype(method)::unsupported() : ({                   \
+            auto result = method;                                         \
+            if (result.isUnsupported()) {                                 \
+                support = false;                                          \
+            }                                                             \
+            std::move(result);                                            \
+        });                                                               \
+    })
+
 // Check if a call to Power HAL function failed; if so, log the failure and
 // invalidate the current Power HAL handle.
 template <typename T>
@@ -103,40 +123,49 @@
     return processHalResult(handle->setMode(mode, enabled), "setMode");
 }
 
-HalResult<std::shared_ptr<aidl::android::hardware::power::IPowerHintSession>>
-PowerHalController::createHintSession(int32_t tgid, int32_t uid,
-                                      const std::vector<int32_t>& threadIds,
-                                      int64_t durationNanos) {
+// Aidl-only methods
+
+HalResult<std::shared_ptr<PowerHintSessionWrapper>> PowerHalController::createHintSession(
+        int32_t tgid, int32_t uid, const std::vector<int32_t>& threadIds, int64_t durationNanos) {
     std::shared_ptr<HalWrapper> handle = initHal();
-    return processHalResult(handle->createHintSession(tgid, uid, threadIds, durationNanos),
-                            "createHintSession");
+    return CACHE_SUPPORT(2,
+                         processHalResult(handle->createHintSession(tgid, uid, threadIds,
+                                                                    durationNanos),
+                                          "createHintSession"));
 }
 
-HalResult<std::shared_ptr<aidl::android::hardware::power::IPowerHintSession>>
-PowerHalController::createHintSessionWithConfig(
+HalResult<std::shared_ptr<PowerHintSessionWrapper>> PowerHalController::createHintSessionWithConfig(
         int32_t tgid, int32_t uid, const std::vector<int32_t>& threadIds, int64_t durationNanos,
         aidl::android::hardware::power::SessionTag tag,
         aidl::android::hardware::power::SessionConfig* config) {
     std::shared_ptr<HalWrapper> handle = initHal();
-    return processHalResult(handle->createHintSessionWithConfig(tgid, uid, threadIds, durationNanos,
-                                                                tag, config),
-                            "createHintSessionWithConfig");
+    return CACHE_SUPPORT(5,
+                         processHalResult(handle->createHintSessionWithConfig(tgid, uid, threadIds,
+                                                                              durationNanos, tag,
+                                                                              config),
+                                          "createHintSessionWithConfig"));
 }
 
 HalResult<int64_t> PowerHalController::getHintSessionPreferredRate() {
     std::shared_ptr<HalWrapper> handle = initHal();
-    return processHalResult(handle->getHintSessionPreferredRate(), "getHintSessionPreferredRate");
+    return CACHE_SUPPORT(2,
+                         processHalResult(handle->getHintSessionPreferredRate(),
+                                          "getHintSessionPreferredRate"));
 }
 
 HalResult<aidl::android::hardware::power::ChannelConfig> PowerHalController::getSessionChannel(
         int tgid, int uid) {
     std::shared_ptr<HalWrapper> handle = initHal();
-    return processHalResult(handle->getSessionChannel(tgid, uid), "getSessionChannel");
+    return CACHE_SUPPORT(5,
+                         processHalResult(handle->getSessionChannel(tgid, uid),
+                                          "getSessionChannel"));
 }
 
 HalResult<void> PowerHalController::closeSessionChannel(int tgid, int uid) {
     std::shared_ptr<HalWrapper> handle = initHal();
-    return processHalResult(handle->closeSessionChannel(tgid, uid), "closeSessionChannel");
+    return CACHE_SUPPORT(5,
+                         processHalResult(handle->closeSessionChannel(tgid, uid),
+                                          "closeSessionChannel"));
 }
 
 } // namespace power
diff --git a/services/powermanager/PowerHalLoader.cpp b/services/powermanager/PowerHalLoader.cpp
index 2214461..ea284c3 100644
--- a/services/powermanager/PowerHalLoader.cpp
+++ b/services/powermanager/PowerHalLoader.cpp
@@ -60,6 +60,7 @@
 sp<V1_1::IPower> PowerHalLoader::gHalHidlV1_1 = nullptr;
 sp<V1_2::IPower> PowerHalLoader::gHalHidlV1_2 = nullptr;
 sp<V1_3::IPower> PowerHalLoader::gHalHidlV1_3 = nullptr;
+int32_t PowerHalLoader::gAidlInterfaceVersion = 0;
 
 void PowerHalLoader::unloadAll() {
     std::lock_guard<std::mutex> lock(gHalMutex);
@@ -89,6 +90,8 @@
             ndk::SpAIBinder(AServiceManager_waitForService(aidlServiceName.c_str())));
     if (gHalAidl) {
         ALOGI("Successfully connected to Power HAL AIDL service.");
+        gHalAidl->getInterfaceVersion(&gAidlInterfaceVersion);
+
     } else {
         ALOGI("Power HAL AIDL service not available.");
         gHalExists = false;
@@ -128,6 +131,10 @@
     return loadHal<V1_0::IPower>(gHalExists, gHalHidlV1_0, loadFn, "HIDL v1.0");
 }
 
+int32_t PowerHalLoader::getAidlVersion() {
+    return gAidlInterfaceVersion;
+}
+
 // -------------------------------------------------------------------------------------------------
 
 } // namespace power
diff --git a/services/powermanager/PowerHalWrapper.cpp b/services/powermanager/PowerHalWrapper.cpp
index 1009100..bd6685c 100644
--- a/services/powermanager/PowerHalWrapper.cpp
+++ b/services/powermanager/PowerHalWrapper.cpp
@@ -18,11 +18,10 @@
 #include <aidl/android/hardware/power/Boost.h>
 #include <aidl/android/hardware/power/IPowerHintSession.h>
 #include <aidl/android/hardware/power/Mode.h>
+#include <powermanager/HalResult.h>
 #include <powermanager/PowerHalWrapper.h>
 #include <utils/Log.h>
 
-#include <cinttypes>
-
 using namespace android::hardware::power;
 namespace Aidl = aidl::android::hardware::power;
 
@@ -31,15 +30,6 @@
 namespace power {
 
 // -------------------------------------------------------------------------------------------------
-inline HalResult<void> toHalResult(const ndk::ScopedAStatus& result) {
-    if (result.isOk()) {
-        return HalResult<void>::ok();
-    }
-    ALOGE("Power HAL request failed: %s", result.getDescription().c_str());
-    return HalResult<void>::failed(result.getDescription());
-}
-
-// -------------------------------------------------------------------------------------------------
 
 HalResult<void> EmptyHalWrapper::setBoost(Aidl::Boost boost, int32_t durationMs) {
     ALOGV("Skipped setBoost %s with duration %dms because %s", toString(boost).c_str(), durationMs,
@@ -53,19 +43,19 @@
     return HalResult<void>::unsupported();
 }
 
-HalResult<std::shared_ptr<Aidl::IPowerHintSession>> EmptyHalWrapper::createHintSession(
+HalResult<std::shared_ptr<PowerHintSessionWrapper>> EmptyHalWrapper::createHintSession(
         int32_t, int32_t, const std::vector<int32_t>& threadIds, int64_t) {
     ALOGV("Skipped createHintSession(task num=%zu) because %s", threadIds.size(),
           getUnsupportedMessage());
-    return HalResult<std::shared_ptr<Aidl::IPowerHintSession>>::unsupported();
+    return HalResult<std::shared_ptr<PowerHintSessionWrapper>>::unsupported();
 }
 
-HalResult<std::shared_ptr<Aidl::IPowerHintSession>> EmptyHalWrapper::createHintSessionWithConfig(
+HalResult<std::shared_ptr<PowerHintSessionWrapper>> EmptyHalWrapper::createHintSessionWithConfig(
         int32_t, int32_t, const std::vector<int32_t>& threadIds, int64_t, Aidl::SessionTag,
         Aidl::SessionConfig*) {
     ALOGV("Skipped createHintSessionWithConfig(task num=%zu) because %s", threadIds.size(),
           getUnsupportedMessage());
-    return HalResult<std::shared_ptr<Aidl::IPowerHintSession>>::unsupported();
+    return HalResult<std::shared_ptr<PowerHintSessionWrapper>>::unsupported();
 }
 
 HalResult<int64_t> EmptyHalWrapper::getHintSessionPreferredRate() {
@@ -225,7 +215,7 @@
     }
     lock.unlock();
 
-    return toHalResult(mHandle->setBoost(boost, durationMs));
+    return HalResult<void>::fromStatus(mHandle->setBoost(boost, durationMs));
 }
 
 HalResult<void> AidlHalWrapper::setMode(Aidl::Mode mode, bool enabled) {
@@ -253,25 +243,25 @@
     }
     lock.unlock();
 
-    return toHalResult(mHandle->setMode(mode, enabled));
+    return HalResult<void>::fromStatus(mHandle->setMode(mode, enabled));
 }
 
-HalResult<std::shared_ptr<Aidl::IPowerHintSession>> AidlHalWrapper::createHintSession(
+HalResult<std::shared_ptr<PowerHintSessionWrapper>> AidlHalWrapper::createHintSession(
         int32_t tgid, int32_t uid, const std::vector<int32_t>& threadIds, int64_t durationNanos) {
     std::shared_ptr<Aidl::IPowerHintSession> appSession;
-    return HalResult<std::shared_ptr<Aidl::IPowerHintSession>>::
+    return HalResult<std::shared_ptr<PowerHintSessionWrapper>>::
             fromStatus(mHandle->createHintSession(tgid, uid, threadIds, durationNanos, &appSession),
-                       std::move(appSession));
+                       std::make_shared<PowerHintSessionWrapper>(std::move(appSession)));
 }
 
-HalResult<std::shared_ptr<Aidl::IPowerHintSession>> AidlHalWrapper::createHintSessionWithConfig(
+HalResult<std::shared_ptr<PowerHintSessionWrapper>> AidlHalWrapper::createHintSessionWithConfig(
         int32_t tgid, int32_t uid, const std::vector<int32_t>& threadIds, int64_t durationNanos,
         Aidl::SessionTag tag, Aidl::SessionConfig* config) {
     std::shared_ptr<Aidl::IPowerHintSession> appSession;
-    return HalResult<std::shared_ptr<Aidl::IPowerHintSession>>::
+    return HalResult<std::shared_ptr<PowerHintSessionWrapper>>::
             fromStatus(mHandle->createHintSessionWithConfig(tgid, uid, threadIds, durationNanos,
                                                             tag, config, &appSession),
-                       std::move(appSession));
+                       std::make_shared<PowerHintSessionWrapper>(std::move(appSession)));
 }
 
 HalResult<int64_t> AidlHalWrapper::getHintSessionPreferredRate() {
@@ -287,7 +277,7 @@
 }
 
 HalResult<void> AidlHalWrapper::closeSessionChannel(int tgid, int uid) {
-    return toHalResult(mHandle->closeSessionChannel(tgid, uid));
+    return HalResult<void>::fromStatus(mHandle->closeSessionChannel(tgid, uid));
 }
 
 const char* AidlHalWrapper::getUnsupportedMessage() {
diff --git a/services/powermanager/PowerHintSessionWrapper.cpp b/services/powermanager/PowerHintSessionWrapper.cpp
new file mode 100644
index 0000000..930c7fa
--- /dev/null
+++ b/services/powermanager/PowerHintSessionWrapper.cpp
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *            http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <powermanager/PowerHintSessionWrapper.h>
+
+using namespace aidl::android::hardware::power;
+
+namespace android::power {
+
+// Caches support for a given call in a static variable, checking both
+// the return value and interface version.
+#define CACHE_SUPPORT(version, method)                      \
+    ({                                                      \
+        static bool support = mInterfaceVersion >= version; \
+        !support ? decltype(method)::unsupported() : ({     \
+            auto result = method;                           \
+            if (result.isUnsupported()) {                   \
+                support = false;                            \
+            }                                               \
+            std::move(result);                              \
+        });                                                 \
+    })
+
+#define CHECK_SESSION(resultType)                                    \
+    if (mSession == nullptr) {                                       \
+        return HalResult<resultType>::failed("Session not running"); \
+    }
+
+// FWD_CALL just forwards calls from the wrapper to the session object.
+// It only works if the call has no return object, as is the case with all calls
+// except getSessionConfig.
+#define FWD_CALL(version, name, args, untypedArgs)                                              \
+    HalResult<void> PowerHintSessionWrapper::name args {                                        \
+        CHECK_SESSION(void)                                                                     \
+        return CACHE_SUPPORT(version, HalResult<void>::fromStatus(mSession->name untypedArgs)); \
+    }
+
+PowerHintSessionWrapper::PowerHintSessionWrapper(std::shared_ptr<IPowerHintSession>&& session)
+      : mSession(session) {
+    if (mSession != nullptr) {
+        mSession->getInterfaceVersion(&mInterfaceVersion);
+    }
+}
+
+// Support for individual hints/modes is not really handled here since there
+// is no way to check for it, so in the future if a way to check that is added,
+// this will need to be updated.
+
+FWD_CALL(2, updateTargetWorkDuration, (int64_t in_targetDurationNanos), (in_targetDurationNanos));
+FWD_CALL(2, reportActualWorkDuration, (const std::vector<WorkDuration>& in_durations),
+         (in_durations));
+FWD_CALL(2, pause, (), ());
+FWD_CALL(2, resume, (), ());
+FWD_CALL(2, close, (), ());
+FWD_CALL(4, sendHint, (SessionHint in_hint), (in_hint));
+FWD_CALL(4, setThreads, (const std::vector<int32_t>& in_threadIds), (in_threadIds));
+FWD_CALL(5, setMode, (SessionMode in_type, bool in_enabled), (in_type, in_enabled));
+
+HalResult<SessionConfig> PowerHintSessionWrapper::getSessionConfig() {
+    CHECK_SESSION(SessionConfig);
+    SessionConfig config;
+    return CACHE_SUPPORT(5,
+                         HalResult<SessionConfig>::fromStatus(mSession->getSessionConfig(&config),
+                                                              std::move(config)));
+}
+
+} // namespace android::power
diff --git a/services/powermanager/tests/Android.bp b/services/powermanager/tests/Android.bp
index 6fc96c0..a05ce2b 100644
--- a/services/powermanager/tests/Android.bp
+++ b/services/powermanager/tests/Android.bp
@@ -37,6 +37,7 @@
         "PowerHalWrapperHidlV1_1Test.cpp",
         "PowerHalWrapperHidlV1_2Test.cpp",
         "PowerHalWrapperHidlV1_3Test.cpp",
+        "PowerHintSessionWrapperTest.cpp",
         "WorkSourceTest.cpp",
     ],
     cflags: [
diff --git a/services/powermanager/tests/PowerHalWrapperAidlTest.cpp b/services/powermanager/tests/PowerHalWrapperAidlTest.cpp
index a720296..1589c99 100644
--- a/services/powermanager/tests/PowerHalWrapperAidlTest.cpp
+++ b/services/powermanager/tests/PowerHalWrapperAidlTest.cpp
@@ -86,6 +86,10 @@
 
 void PowerHalWrapperAidlTest::SetUp() {
     mMockHal = ndk::SharedRefBase::make<StrictMock<MockIPower>>();
+    EXPECT_CALL(*mMockHal, getInterfaceVersion(_)).WillRepeatedly(([](int32_t* ret) {
+        *ret = 5;
+        return ndk::ScopedAStatus::ok();
+    }));
     mWrapper = std::make_unique<AidlHalWrapper>(mMockHal);
     ASSERT_NE(nullptr, mWrapper);
 }
@@ -130,10 +134,12 @@
 }
 
 TEST_F(PowerHalWrapperAidlTest, TestSetBoostUnsupported) {
-    EXPECT_CALL(*mMockHal.get(), isBoostSupported(Eq(Boost::INTERACTION), _))
-            .Times(Exactly(1))
-            .WillOnce(DoAll(SetArgPointee<1>(false),
-                            Return(testing::ByMove(ndk::ScopedAStatus::ok()))));
+    EXPECT_CALL(*mMockHal.get(), isBoostSupported(_, _))
+            .Times(Exactly(2))
+            .WillRepeatedly([](Boost, bool* ret) {
+                *ret = false;
+                return ndk::ScopedAStatus::ok();
+            });
 
     auto result = mWrapper->setBoost(Boost::INTERACTION, 1000);
     ASSERT_TRUE(result.isUnsupported());
@@ -311,3 +317,29 @@
     auto closeResult = mWrapper->closeSessionChannel(tgid, uid);
     ASSERT_TRUE(closeResult.isOk());
 }
+
+TEST_F(PowerHalWrapperAidlTest, TestCreateHintSessionWithConfigUnsupported) {
+    std::vector<int> threadIds{gettid()};
+    int32_t tgid = 999;
+    int32_t uid = 1001;
+    int64_t durationNanos = 16666666L;
+    SessionTag tag = SessionTag::OTHER;
+    SessionConfig out;
+    EXPECT_CALL(*mMockHal.get(),
+                createHintSessionWithConfig(Eq(tgid), Eq(uid), Eq(threadIds), Eq(durationNanos),
+                                            Eq(tag), _, _))
+            .Times(1)
+            .WillOnce(Return(testing::ByMove(
+                    ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION))));
+    auto result =
+            mWrapper->createHintSessionWithConfig(tgid, uid, threadIds, durationNanos, tag, &out);
+    ASSERT_TRUE(result.isUnsupported());
+    Mock::VerifyAndClearExpectations(mMockHal.get());
+    EXPECT_CALL(*mMockHal.get(),
+                createHintSessionWithConfig(Eq(tgid), Eq(uid), Eq(threadIds), Eq(durationNanos),
+                                            Eq(tag), _, _))
+            .WillOnce(Return(
+                    testing::ByMove(ndk::ScopedAStatus::fromStatus(STATUS_UNKNOWN_TRANSACTION))));
+    result = mWrapper->createHintSessionWithConfig(tgid, uid, threadIds, durationNanos, tag, &out);
+    ASSERT_TRUE(result.isUnsupported());
+}
diff --git a/services/powermanager/tests/PowerHintSessionWrapperTest.cpp b/services/powermanager/tests/PowerHintSessionWrapperTest.cpp
new file mode 100644
index 0000000..7743fa4
--- /dev/null
+++ b/services/powermanager/tests/PowerHintSessionWrapperTest.cpp
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *            http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <aidl/android/hardware/power/IPowerHintSession.h>
+#include <powermanager/PowerHintSessionWrapper.h>
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+using aidl::android::hardware::power::IPowerHintSession;
+using android::power::PowerHintSessionWrapper;
+
+using namespace android;
+using namespace std::chrono_literals;
+using namespace testing;
+
+class MockIPowerHintSession : public IPowerHintSession {
+public:
+    MockIPowerHintSession() = default;
+    MOCK_METHOD(::ndk::ScopedAStatus, updateTargetWorkDuration, (int64_t in_targetDurationNanos),
+                (override));
+    MOCK_METHOD(::ndk::ScopedAStatus, reportActualWorkDuration,
+                (const std::vector<::aidl::android::hardware::power::WorkDuration>& in_durations),
+                (override));
+    MOCK_METHOD(::ndk::ScopedAStatus, pause, (), (override));
+    MOCK_METHOD(::ndk::ScopedAStatus, resume, (), (override));
+    MOCK_METHOD(::ndk::ScopedAStatus, close, (), (override));
+    MOCK_METHOD(::ndk::ScopedAStatus, sendHint,
+                (::aidl::android::hardware::power::SessionHint in_hint), (override));
+    MOCK_METHOD(::ndk::ScopedAStatus, setThreads, (const std::vector<int32_t>& in_threadIds),
+                (override));
+    MOCK_METHOD(::ndk::ScopedAStatus, setMode,
+                (::aidl::android::hardware::power::SessionMode in_type, bool in_enabled),
+                (override));
+    MOCK_METHOD(::ndk::ScopedAStatus, getSessionConfig,
+                (::aidl::android::hardware::power::SessionConfig * _aidl_return), (override));
+    MOCK_METHOD(::ndk::ScopedAStatus, getInterfaceVersion, (int32_t * _aidl_return), (override));
+    MOCK_METHOD(::ndk::ScopedAStatus, getInterfaceHash, (std::string * _aidl_return), (override));
+    MOCK_METHOD(::ndk::SpAIBinder, asBinder, (), (override));
+    MOCK_METHOD(bool, isRemote, (), (override));
+};
+
+class PowerHintSessionWrapperTest : public Test {
+public:
+    void SetUp() override;
+
+protected:
+    std::shared_ptr<NiceMock<MockIPowerHintSession>> mMockSession = nullptr;
+    std::unique_ptr<PowerHintSessionWrapper> mSession = nullptr;
+};
+
+void PowerHintSessionWrapperTest::SetUp() {
+    mMockSession = ndk::SharedRefBase::make<NiceMock<MockIPowerHintSession>>();
+    EXPECT_CALL(*mMockSession, getInterfaceVersion(_)).WillRepeatedly(([](int32_t* ret) {
+        *ret = 5;
+        return ndk::ScopedAStatus::ok();
+    }));
+    mSession = std::make_unique<PowerHintSessionWrapper>(mMockSession);
+    ASSERT_NE(nullptr, mSession);
+}
+
+TEST_F(PowerHintSessionWrapperTest, updateTargetWorkDuration) {
+    EXPECT_CALL(*mMockSession.get(), updateTargetWorkDuration(1000000000))
+            .WillOnce(Return(ndk::ScopedAStatus::ok()));
+    auto status = mSession->updateTargetWorkDuration(1000000000);
+    ASSERT_TRUE(status.isOk());
+}
+
+TEST_F(PowerHintSessionWrapperTest, reportActualWorkDuration) {
+    EXPECT_CALL(*mMockSession.get(),
+                reportActualWorkDuration(
+                        std::vector<::aidl::android::hardware::power::WorkDuration>()))
+            .WillOnce(Return(ndk::ScopedAStatus::ok()));
+    auto status = mSession->reportActualWorkDuration(
+            std::vector<::aidl::android::hardware::power::WorkDuration>());
+    ASSERT_TRUE(status.isOk());
+}
+
+TEST_F(PowerHintSessionWrapperTest, pause) {
+    EXPECT_CALL(*mMockSession.get(), pause()).WillOnce(Return(ndk::ScopedAStatus::ok()));
+    auto status = mSession->pause();
+    ASSERT_TRUE(status.isOk());
+}
+
+TEST_F(PowerHintSessionWrapperTest, resume) {
+    EXPECT_CALL(*mMockSession.get(), resume()).WillOnce(Return(ndk::ScopedAStatus::ok()));
+    auto status = mSession->resume();
+    ASSERT_TRUE(status.isOk());
+}
+
+TEST_F(PowerHintSessionWrapperTest, close) {
+    EXPECT_CALL(*mMockSession.get(), close()).WillOnce(Return(ndk::ScopedAStatus::ok()));
+    auto status = mSession->close();
+    ASSERT_TRUE(status.isOk());
+}
+
+TEST_F(PowerHintSessionWrapperTest, sendHint) {
+    EXPECT_CALL(*mMockSession.get(),
+                sendHint(::aidl::android::hardware::power::SessionHint::CPU_LOAD_UP))
+            .WillOnce(Return(ndk::ScopedAStatus::ok()));
+    auto status = mSession->sendHint(::aidl::android::hardware::power::SessionHint::CPU_LOAD_UP);
+    ASSERT_TRUE(status.isOk());
+}
+
+TEST_F(PowerHintSessionWrapperTest, setThreads) {
+    EXPECT_CALL(*mMockSession.get(), setThreads(_)).WillOnce(Return(ndk::ScopedAStatus::ok()));
+    auto status = mSession->setThreads(std::vector<int32_t>{gettid()});
+    ASSERT_TRUE(status.isOk());
+}
+
+TEST_F(PowerHintSessionWrapperTest, setMode) {
+    EXPECT_CALL(*mMockSession.get(),
+                setMode(::aidl::android::hardware::power::SessionMode::POWER_EFFICIENCY, true))
+            .WillOnce(Return(ndk::ScopedAStatus::ok()));
+    auto status = mSession->setMode(::aidl::android::hardware::power::SessionMode::POWER_EFFICIENCY,
+                                    true);
+    ASSERT_TRUE(status.isOk());
+}
+
+TEST_F(PowerHintSessionWrapperTest, getSessionConfig) {
+    EXPECT_CALL(*mMockSession.get(), getSessionConfig(_))
+            .WillOnce(DoAll(SetArgPointee<0>(
+                                    aidl::android::hardware::power::SessionConfig{.id = 12L}),
+                            Return(ndk::ScopedAStatus::ok())));
+    auto status = mSession->getSessionConfig();
+    ASSERT_TRUE(status.isOk());
+}