Create wrappers for Power HAL.

Create wrappers over existing HIDL Power HALs v1.0, v1.1, and AIDL Power
HAL. All wrappers expose the same API that should be used by the
PowerManagerService.

Bug: 150878220
Test: atest powermanager_test
Change-Id: I5edba6d51d3e18c5137c87b65bc9efa6c70ba7e8
diff --git a/services/powermanager/tests/Android.bp b/services/powermanager/tests/Android.bp
new file mode 100644
index 0000000..65cde030
--- /dev/null
+++ b/services/powermanager/tests/Android.bp
@@ -0,0 +1,61 @@
+// Copyright (C) 2020 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.
+
+cc_test {
+    name: "powermanager_test",
+    test_suites: ["device-tests"],
+    srcs: [
+        "PowerHalWrapperAidlTest.cpp",
+        "PowerHalWrapperHidlV1_0Test.cpp",
+        "PowerHalWrapperHidlV1_1Test.cpp",
+    ],
+    cflags: [
+        "-Wall",
+        "-Werror",
+        "-Wextra",
+    ],
+    shared_libs: [
+        "libbase",
+        "libbinder",
+        "libhidlbase",
+        "liblog",
+        "libpowermanager",
+        "libutils",
+        "android.hardware.power@1.0",
+        "android.hardware.power@1.1",
+        "android.hardware.power-cpp",
+    ],
+    static_libs: [
+        "libgmock",
+    ],
+}
+
+cc_test {
+    name: "thermalmanager_test",
+    test_suites: ["device-tests"],
+    srcs: ["IThermalManagerTest.cpp",],
+    cflags: [
+        "-Wall",
+        "-Werror",
+        "-Wextra",
+    ],
+    shared_libs: [
+        "libbase",
+        "libhidlbase",
+        "liblog",
+        "libpowermanager",
+        "libbinder",
+        "libutils",
+    ],
+}
diff --git a/services/powermanager/tests/IThermalManagerTest.cpp b/services/powermanager/tests/IThermalManagerTest.cpp
new file mode 100644
index 0000000..575b9ee
--- /dev/null
+++ b/services/powermanager/tests/IThermalManagerTest.cpp
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+#define LOG_TAG "ThermalManagerTest"
+//#define LOG_NDEBUG 0
+
+#include <thread>
+
+#include <android/os/BnThermalStatusListener.h>
+#include <android/os/IThermalService.h>
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+#include <binder/Parcel.h>
+#include <condition_variable>
+#include <gtest/gtest.h>
+#include <powermanager/PowerManager.h>
+#include <utils/Log.h>
+
+using namespace android;
+using namespace android::os;
+using namespace std::chrono_literals;
+
+class IThermalServiceTest : public testing::Test,
+                            public BnThermalStatusListener{
+    public:
+        IThermalServiceTest();
+        void setThermalOverride(int level);
+        virtual binder::Status onStatusChange(int status) override;
+        int getStatusFromService();
+        void SetUp() override;
+        void TearDown() override;
+    protected:
+        sp<IThermalService> mThermalSvc;
+        std::condition_variable mCondition;
+        int mListenerStatus;
+        int mServiceStatus;
+        std::mutex mMutex;
+};
+
+IThermalServiceTest::IThermalServiceTest()
+ : mListenerStatus(0),
+   mServiceStatus(0) {
+}
+
+void IThermalServiceTest::setThermalOverride(int level) {
+    std::string cmdStr = "cmd thermalservice override-status " + std::to_string(level);
+    system(cmdStr.c_str());
+}
+
+binder::Status IThermalServiceTest::onStatusChange(int status) {
+    std::unique_lock<std::mutex> lock(mMutex);
+    mListenerStatus = status;
+    ALOGI("IThermalServiceTest::notifyListener %d", mListenerStatus);
+    mCondition.notify_all();
+    return binder::Status::ok();
+}
+
+int IThermalServiceTest::getStatusFromService() {
+    int status;
+    binder::Status ret = mThermalSvc->getCurrentThermalStatus(&status);
+    if (ret.isOk()) {
+        return status;
+    } else {
+        return BAD_VALUE;
+    }
+}
+
+void IThermalServiceTest::SetUp() {
+    setThermalOverride(0);
+    // use checkService() to avoid blocking if thermal service is not up yet
+    sp<IBinder> binder =
+        defaultServiceManager()->checkService(String16("thermalservice"));
+    EXPECT_NE(binder, nullptr);
+    mThermalSvc = interface_cast<IThermalService>(binder);
+    EXPECT_NE(mThermalSvc, nullptr);
+    bool success = false;
+    binder::Status ret = mThermalSvc->registerThermalStatusListener(this, &success);
+    ASSERT_TRUE(success);
+    ASSERT_TRUE(ret.isOk());
+    // Wait for listener called after registration, shouldn't timeout
+    std::unique_lock<std::mutex> lock(mMutex);
+    EXPECT_NE(mCondition.wait_for(lock, 1s), std::cv_status::timeout);
+}
+
+void IThermalServiceTest::TearDown() {
+    bool success = false;
+    binder::Status ret = mThermalSvc->unregisterThermalStatusListener(this, &success);
+    ASSERT_TRUE(success);
+    ASSERT_TRUE(ret.isOk());
+}
+
+class IThermalListenerTest : public IThermalServiceTest, public testing::WithParamInterface<int32_t> {
+  public:
+    static auto PrintParam(const testing::TestParamInfo<ParamType> &info) {
+        return std::to_string(info.param);
+    }
+};
+
+TEST_P(IThermalListenerTest, TestListener) {
+    int level = GetParam();
+    std::unique_lock<std::mutex> lock(mMutex);
+    // Set the override thermal status
+    setThermalOverride(level);
+    // Wait for listener called, shouldn't timeout
+    EXPECT_NE(mCondition.wait_for(lock, 1s), std::cv_status::timeout);
+    // Check the result
+    EXPECT_EQ(level, mListenerStatus);
+    ALOGI("Thermal listener status %d, expecting %d", mListenerStatus, level);
+}
+
+INSTANTIATE_TEST_SUITE_P(TestListenerLevels, IThermalListenerTest, testing::Range(
+        static_cast<int>(ThermalStatus::THERMAL_STATUS_LIGHT),
+        static_cast<int>(ThermalStatus::THERMAL_STATUS_SHUTDOWN)),
+        IThermalListenerTest::PrintParam);
+
+class IThermalLevelTest : public IThermalServiceTest, public testing::WithParamInterface<int32_t> {
+  public:
+    static auto PrintParam(const testing::TestParamInfo<ParamType> &info) {
+        return std::to_string(info.param);
+    }
+};
+
+TEST_P(IThermalLevelTest, TestGetStatusLevel) {
+    int level = GetParam();
+    setThermalOverride(level);
+    mServiceStatus = getStatusFromService();
+    EXPECT_EQ(level, mServiceStatus);
+}
+
+INSTANTIATE_TEST_SUITE_P(TestStatusLevels, IThermalLevelTest, testing::Range(
+        static_cast<int>(ThermalStatus::THERMAL_STATUS_NONE),
+        static_cast<int>(ThermalStatus::THERMAL_STATUS_SHUTDOWN)),
+        IThermalLevelTest::PrintParam);
+
+int main(int argc, char **argv) {
+    std::unique_ptr<std::thread> binderLoop;
+    binderLoop = std::make_unique<std::thread>(
+            [&] { IPCThreadState::self()->joinThreadPool(true); });
+
+    ::testing::InitGoogleTest(&argc, argv);
+    int status = RUN_ALL_TESTS();
+    ALOGV("Test result = %d\n", status);
+
+    return status;
+}
\ No newline at end of file
diff --git a/services/powermanager/tests/PowerHalWrapperAidlTest.cpp b/services/powermanager/tests/PowerHalWrapperAidlTest.cpp
new file mode 100644
index 0000000..73b7466
--- /dev/null
+++ b/services/powermanager/tests/PowerHalWrapperAidlTest.cpp
@@ -0,0 +1,202 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+#define LOG_TAG "PowerHalWrapperAidlTest"
+
+#include <android/hardware/power/Boost.h>
+#include <android/hardware/power/Mode.h>
+#include <binder/IServiceManager.h>
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include <powermanager/PowerHalWrapper.h>
+
+#include <thread>
+#include <utils/Log.h>
+
+using android::binder::Status;
+using android::hardware::power::Boost;
+using android::hardware::power::IPower;
+using android::hardware::power::Mode;
+
+using namespace android;
+using namespace std::chrono_literals;
+using namespace testing;
+
+// -------------------------------------------------------------------------------------------------
+
+class MockIPower : public IPower {
+public:
+    MOCK_METHOD(Status, isBoostSupported, (Boost boost, bool* ret), (override));
+    MOCK_METHOD(Status, setBoost, (Boost boost, int32_t durationMs), (override));
+    MOCK_METHOD(Status, isModeSupported, (Mode mode, bool* ret), (override));
+    MOCK_METHOD(Status, setMode, (Mode mode, bool enabled), (override));
+    MOCK_METHOD(int32_t, getInterfaceVersion, (), (override));
+    MOCK_METHOD(std::string, getInterfaceHash, (), (override));
+    MOCK_METHOD(IBinder*, onAsBinder, (), (override));
+};
+
+// -------------------------------------------------------------------------------------------------
+
+class PowerHalWrapperAidlTest : public Test {
+public:
+    void SetUp() override;
+
+protected:
+    std::unique_ptr<PowerHalWrapper> mWrapper = nullptr;
+    sp<StrictMock<MockIPower>> mMockHal = nullptr;
+};
+
+// -------------------------------------------------------------------------------------------------
+
+void PowerHalWrapperAidlTest::SetUp() {
+    mMockHal = new StrictMock<MockIPower>();
+    mWrapper = std::make_unique<AidlPowerHalWrapper>(mMockHal);
+    ASSERT_NE(mWrapper, nullptr);
+}
+
+// -------------------------------------------------------------------------------------------------
+
+TEST_F(PowerHalWrapperAidlTest, TestSetBoostSuccessful) {
+    {
+        InSequence seq;
+        EXPECT_CALL(*mMockHal.get(), isBoostSupported(Eq(Boost::DISPLAY_UPDATE_IMMINENT), _))
+            .Times(Exactly(1))
+            .WillRepeatedly(DoAll(SetArgPointee<1>(true), Return(Status())));
+        EXPECT_CALL(*mMockHal.get(), setBoost(Eq(Boost::DISPLAY_UPDATE_IMMINENT), Eq(100)))
+            .Times(Exactly(1));
+    }
+
+    auto result = mWrapper->setBoost(Boost::DISPLAY_UPDATE_IMMINENT, 100);
+    ASSERT_EQ(PowerHalResult::SUCCESSFUL, result);
+}
+
+TEST_F(PowerHalWrapperAidlTest, TestSetBoostFailed) {
+    {
+        InSequence seq;
+        EXPECT_CALL(*mMockHal.get(), isBoostSupported(Eq(Boost::INTERACTION), _))
+            .Times(Exactly(1))
+            .WillRepeatedly(DoAll(SetArgPointee<1>(true), Return(Status())));
+        EXPECT_CALL(*mMockHal.get(), setBoost(Eq(Boost::INTERACTION), Eq(100)))
+            .Times(Exactly(1))
+            .WillRepeatedly(Return(Status::fromExceptionCode(-1)));
+        EXPECT_CALL(*mMockHal.get(), isBoostSupported(Eq(Boost::DISPLAY_UPDATE_IMMINENT), _))
+            .Times(Exactly(1))
+            .WillRepeatedly(Return(Status::fromExceptionCode(-1)));
+    }
+
+    auto result = mWrapper->setBoost(Boost::INTERACTION, 100);
+    ASSERT_EQ(PowerHalResult::FAILED, result);
+    result = mWrapper->setBoost(Boost::DISPLAY_UPDATE_IMMINENT, 1000);
+    ASSERT_EQ(PowerHalResult::FAILED, result);
+}
+
+TEST_F(PowerHalWrapperAidlTest, TestSetBoostUnsupported) {
+    EXPECT_CALL(*mMockHal.get(), isBoostSupported(Eq(Boost::INTERACTION), _))
+        .Times(Exactly(1))
+        .WillRepeatedly(DoAll(SetArgPointee<1>(false), Return(Status())));
+
+    auto result = mWrapper->setBoost(Boost::INTERACTION, 1000);
+    ASSERT_EQ(PowerHalResult::UNSUPPORTED, result);
+    result = mWrapper->setBoost(Boost::CAMERA_SHOT, 10);
+    ASSERT_EQ(PowerHalResult::UNSUPPORTED, result);
+}
+
+TEST_F(PowerHalWrapperAidlTest, TestSetBoostMultiThreadCheckSupportedOnlyOnce) {
+    {
+        InSequence seq;
+        EXPECT_CALL(*mMockHal.get(), isBoostSupported(Eq(Boost::INTERACTION), _))
+            .Times(Exactly(1))
+            .WillRepeatedly(DoAll(SetArgPointee<1>(true), Return(Status())));
+        EXPECT_CALL(*mMockHal.get(), setBoost(Eq(Boost::INTERACTION), Eq(100)))
+            .Times(Exactly(10));
+    }
+
+    std::vector<std::thread> threads;
+    for (int i = 0; i < 10; i++) {
+        threads.push_back(std::thread([&]() {
+            auto result = mWrapper->setBoost(Boost::INTERACTION, 100);
+            ASSERT_EQ(PowerHalResult::SUCCESSFUL, result);
+        }));
+    }
+    std::for_each(threads.begin(), threads.end(), [](std::thread& t) { t.join(); });
+}
+
+TEST_F(PowerHalWrapperAidlTest, TestSetModeSuccessful) {
+    {
+        InSequence seq;
+        EXPECT_CALL(*mMockHal.get(), isModeSupported(Eq(Mode::DISPLAY_INACTIVE), _))
+            .Times(Exactly(1))
+            .WillRepeatedly(DoAll(SetArgPointee<1>(true), Return(Status())));
+        EXPECT_CALL(*mMockHal.get(), setMode(Eq(Mode::DISPLAY_INACTIVE), Eq(false)))
+            .Times(Exactly(1));
+    }
+
+    auto result = mWrapper->setMode(Mode::DISPLAY_INACTIVE, false);
+    ASSERT_EQ(PowerHalResult::SUCCESSFUL, result);
+}
+
+TEST_F(PowerHalWrapperAidlTest, TestSetModeFailed) {
+    {
+        InSequence seq;
+        EXPECT_CALL(*mMockHal.get(), isModeSupported(Eq(Mode::LAUNCH), _))
+            .Times(Exactly(1))
+            .WillRepeatedly(DoAll(SetArgPointee<1>(true), Return(Status())));
+        EXPECT_CALL(*mMockHal.get(), setMode(Eq(Mode::LAUNCH), Eq(true)))
+            .Times(Exactly(1))
+            .WillRepeatedly(Return(Status::fromExceptionCode(-1)));
+        EXPECT_CALL(*mMockHal.get(), isModeSupported(Eq(Mode::DISPLAY_INACTIVE), _))
+            .Times(Exactly(1))
+            .WillRepeatedly(Return(Status::fromExceptionCode(-1)));
+    }
+
+    auto result = mWrapper->setMode(Mode::LAUNCH, true);
+    ASSERT_EQ(PowerHalResult::FAILED, result);
+    result = mWrapper->setMode(Mode::DISPLAY_INACTIVE, false);
+    ASSERT_EQ(PowerHalResult::FAILED, result);
+}
+
+TEST_F(PowerHalWrapperAidlTest, TestSetModeUnsupported) {
+    EXPECT_CALL(*mMockHal.get(), isModeSupported(Eq(Mode::LAUNCH), _))
+        .Times(Exactly(1))
+        .WillRepeatedly(DoAll(SetArgPointee<1>(false), Return(Status())));
+
+    auto result = mWrapper->setMode(Mode::LAUNCH, true);
+    ASSERT_EQ(PowerHalResult::UNSUPPORTED, result);
+    result = mWrapper->setMode(Mode::CAMERA_STREAMING_HIGH, true);
+    ASSERT_EQ(PowerHalResult::UNSUPPORTED, result);
+}
+
+TEST_F(PowerHalWrapperAidlTest, TestSetModeMultiThreadCheckSupportedOnlyOnce) {
+    {
+        InSequence seq;
+        EXPECT_CALL(*mMockHal.get(), isModeSupported(Eq(Mode::LAUNCH), _))
+            .Times(Exactly(1))
+            .WillRepeatedly(DoAll(SetArgPointee<1>(true), Return(Status())));
+        EXPECT_CALL(*mMockHal.get(), setMode(Eq(Mode::LAUNCH), Eq(false)))
+            .Times(Exactly(10));
+    }
+
+    std::vector<std::thread> threads;
+    for (int i = 0; i < 10; i++) {
+        threads.push_back(std::thread([&]() {
+            auto result = mWrapper->setMode(Mode::LAUNCH, false);
+            ASSERT_EQ(PowerHalResult::SUCCESSFUL, result);
+        }));
+    }
+    std::for_each(threads.begin(), threads.end(), [](std::thread& t) { t.join(); });
+}
diff --git a/services/powermanager/tests/PowerHalWrapperHidlV1_0Test.cpp b/services/powermanager/tests/PowerHalWrapperHidlV1_0Test.cpp
new file mode 100644
index 0000000..5379054
--- /dev/null
+++ b/services/powermanager/tests/PowerHalWrapperHidlV1_0Test.cpp
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+#define LOG_TAG "PowerHalWrapperHidlV1_0Test"
+
+#include <android/hardware/power/Boost.h>
+#include <android/hardware/power/IPower.h>
+#include <android/hardware/power/Mode.h>
+#include <binder/IServiceManager.h>
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include <powermanager/PowerHalWrapper.h>
+
+#include <utils/Log.h>
+
+using android::hardware::power::Boost;
+using android::hardware::power::Mode;
+using android::hardware::power::V1_0::Feature;
+using android::hardware::power::V1_0::IPower;
+using android::hardware::power::V1_0::PowerHint;
+
+using namespace android;
+using namespace std::chrono_literals;
+using namespace testing;
+
+// -------------------------------------------------------------------------------------------------
+
+class MockIPowerV1_0 : public IPower {
+public:
+    MOCK_METHOD(hardware::Return<void>, setInteractive, (bool interactive), (override));
+    MOCK_METHOD(hardware::Return<void>, powerHint, (PowerHint hint, int32_t data), (override));
+    MOCK_METHOD(
+        hardware::Return<void>, setFeature, (Feature feature, bool activate), (override));
+    MOCK_METHOD(
+        hardware::Return<void>, getPlatformLowPowerStats,
+        (getPlatformLowPowerStats_cb _hidl_cb), (override));
+};
+
+// -------------------------------------------------------------------------------------------------
+
+class PowerHalWrapperHidlV1_0Test : public Test {
+public:
+    void SetUp() override;
+
+protected:
+    std::unique_ptr<PowerHalWrapper> mWrapper = nullptr;
+    sp<StrictMock<MockIPowerV1_0>> mMockHal = nullptr;
+};
+
+// -------------------------------------------------------------------------------------------------
+
+void PowerHalWrapperHidlV1_0Test::SetUp() {
+    mMockHal = new StrictMock<MockIPowerV1_0>();
+    mWrapper = std::make_unique<HidlPowerHalWrapperV1_0>(mMockHal);
+    ASSERT_NE(mWrapper, nullptr);
+}
+
+// -------------------------------------------------------------------------------------------------
+
+TEST_F(PowerHalWrapperHidlV1_0Test, TestSetBoostSuccessful) {
+    EXPECT_CALL(*mMockHal.get(), powerHint(Eq(PowerHint::INTERACTION), Eq(1000)))
+        .Times(Exactly(1));
+
+    auto result = mWrapper->setBoost(Boost::INTERACTION, 1000);
+    ASSERT_EQ(PowerHalResult::SUCCESSFUL, result);
+}
+
+TEST_F(PowerHalWrapperHidlV1_0Test, TestSetBoostFailed) {
+    EXPECT_CALL(*mMockHal.get(), powerHint(Eq(PowerHint::INTERACTION), Eq(1000)))
+        .Times(Exactly(1))
+        .WillRepeatedly([](PowerHint, int32_t) {
+            return hardware::Return<void>(hardware::Status::fromExceptionCode(-1));
+        });
+
+    auto result = mWrapper->setBoost(Boost::INTERACTION, 1000);
+    ASSERT_EQ(PowerHalResult::FAILED, result);
+}
+
+TEST_F(PowerHalWrapperHidlV1_0Test, TestSetBoostUnsupported) {
+    auto result = mWrapper->setBoost(Boost::CAMERA_LAUNCH, 10);
+    ASSERT_EQ(PowerHalResult::UNSUPPORTED, result);
+}
+
+TEST_F(PowerHalWrapperHidlV1_0Test, TestSetModeSuccessful) {
+    {
+        InSequence seq;
+        EXPECT_CALL(*mMockHal.get(), powerHint(Eq(PowerHint::LAUNCH), Eq(1)))
+            .Times(Exactly(1));
+        EXPECT_CALL(*mMockHal.get(), powerHint(Eq(PowerHint::LOW_POWER), Eq(0)))
+            .Times(Exactly(1));
+        EXPECT_CALL(*mMockHal.get(), powerHint(Eq(PowerHint::SUSTAINED_PERFORMANCE), Eq(1)))
+            .Times(Exactly(1));
+        EXPECT_CALL(*mMockHal.get(), powerHint(Eq(PowerHint::VR_MODE), Eq(0)))
+            .Times(Exactly(1));
+        EXPECT_CALL(*mMockHal.get(), setInteractive(Eq(true)))
+            .Times(Exactly(1));
+        EXPECT_CALL(*mMockHal.get(),
+                    setFeature(Eq(Feature::POWER_FEATURE_DOUBLE_TAP_TO_WAKE), Eq(false)))
+            .Times(Exactly(1));
+    }
+
+    auto result = mWrapper->setMode(Mode::LAUNCH, true);
+    ASSERT_EQ(PowerHalResult::SUCCESSFUL, result);
+    result = mWrapper->setMode(Mode::LOW_POWER, false);
+    ASSERT_EQ(PowerHalResult::SUCCESSFUL, result);
+    result = mWrapper->setMode(Mode::SUSTAINED_PERFORMANCE, true);
+    ASSERT_EQ(PowerHalResult::SUCCESSFUL, result);
+    result = mWrapper->setMode(Mode::VR, false);
+    ASSERT_EQ(PowerHalResult::SUCCESSFUL, result);
+    result = mWrapper->setMode(Mode::INTERACTIVE, true);
+    ASSERT_EQ(PowerHalResult::SUCCESSFUL, result);
+    result = mWrapper->setMode(Mode::DOUBLE_TAP_TO_WAKE, false);
+    ASSERT_EQ(PowerHalResult::SUCCESSFUL, result);
+}
+
+TEST_F(PowerHalWrapperHidlV1_0Test, TestSetModeFailed) {
+    EXPECT_CALL(*mMockHal.get(), powerHint(Eq(PowerHint::LAUNCH), Eq(1)))
+        .Times(Exactly(1))
+        .WillRepeatedly([](PowerHint, int32_t) {
+            return hardware::Return<void>(hardware::Status::fromExceptionCode(-1));
+        });
+
+    auto result = mWrapper->setMode(Mode::LAUNCH, 1);
+    ASSERT_EQ(PowerHalResult::FAILED, result);
+}
+
+TEST_F(PowerHalWrapperHidlV1_0Test, TestSetModeIgnored) {
+    auto result = mWrapper->setMode(Mode::CAMERA_STREAMING_HIGH, true);
+    ASSERT_EQ(PowerHalResult::UNSUPPORTED, result);
+}
diff --git a/services/powermanager/tests/PowerHalWrapperHidlV1_1Test.cpp b/services/powermanager/tests/PowerHalWrapperHidlV1_1Test.cpp
new file mode 100644
index 0000000..931c0d5
--- /dev/null
+++ b/services/powermanager/tests/PowerHalWrapperHidlV1_1Test.cpp
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+#define LOG_TAG "PowerHalWrapperHidlV1_1Test"
+
+#include <android/hardware/power/1.1/IPower.h>
+#include <android/hardware/power/Boost.h>
+#include <android/hardware/power/IPower.h>
+#include <android/hardware/power/Mode.h>
+#include <binder/IServiceManager.h>
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include <powermanager/PowerHalWrapper.h>
+
+#include <utils/Log.h>
+
+using android::hardware::power::Boost;
+using android::hardware::power::Mode;
+using android::hardware::power::V1_0::Feature;
+using android::hardware::power::V1_0::PowerHint;
+using IPowerV1_1 = android::hardware::power::V1_1::IPower;
+using IPowerV1_0 = android::hardware::power::V1_0::IPower;
+
+using namespace android;
+using namespace std::chrono_literals;
+using namespace testing;
+
+// -------------------------------------------------------------------------------------------------
+
+class MockIPowerV1_0 : public IPowerV1_0 {
+public:
+    MOCK_METHOD(hardware::Return<void>, setInteractive, (bool interactive), (override));
+    MOCK_METHOD(hardware::Return<void>, powerHint, (PowerHint hint, int32_t data), (override));
+    MOCK_METHOD(
+        hardware::Return<void>, setFeature, (Feature feature, bool activate), (override));
+    MOCK_METHOD(
+        hardware::Return<void>, getPlatformLowPowerStats,
+        (getPlatformLowPowerStats_cb _hidl_cb), (override));
+};
+
+class MockIPowerV1_1 : public IPowerV1_1 {
+public:
+    MOCK_METHOD(hardware::Return<void>, setInteractive, (bool interactive), (override));
+    MOCK_METHOD(hardware::Return<void>, powerHint, (PowerHint hint, int32_t data), (override));
+    MOCK_METHOD(
+        hardware::Return<void>, setFeature, (Feature feature, bool activate), (override));
+    MOCK_METHOD(
+        hardware::Return<void>, getPlatformLowPowerStats,
+        (getPlatformLowPowerStats_cb _hidl_cb), (override));
+    MOCK_METHOD(
+        hardware::Return<void>, powerHintAsync, (PowerHint hint, int32_t data), (override));
+    MOCK_METHOD(
+        hardware::Return<void>, getSubsystemLowPowerStats,
+        (getSubsystemLowPowerStats_cb _hidl_cb), (override));
+};
+
+// -------------------------------------------------------------------------------------------------
+
+class PowerHalWrapperHidlV1_1Test : public Test {
+public:
+    void SetUp() override;
+
+protected:
+    std::unique_ptr<PowerHalWrapper> mWrapper = nullptr;
+    sp<StrictMock<MockIPowerV1_0>> mMockHalV1_0 = nullptr;
+    sp<StrictMock<MockIPowerV1_1>> mMockHalV1_1 = nullptr;
+};
+
+// -------------------------------------------------------------------------------------------------
+
+void PowerHalWrapperHidlV1_1Test::SetUp() {
+    mMockHalV1_0 = new StrictMock<MockIPowerV1_0>();
+    mMockHalV1_1 = new StrictMock<MockIPowerV1_1>();
+    mWrapper = std::make_unique<HidlPowerHalWrapperV1_1>(mMockHalV1_0, mMockHalV1_1);
+    ASSERT_NE(mWrapper, nullptr);
+}
+
+// -------------------------------------------------------------------------------------------------
+
+TEST_F(PowerHalWrapperHidlV1_1Test, TestSetBoostSuccessful) {
+    EXPECT_CALL(*mMockHalV1_1.get(), powerHintAsync(Eq(PowerHint::INTERACTION), Eq(1000)))
+        .Times(Exactly(1));
+
+    auto result = mWrapper->setBoost(Boost::INTERACTION, 1000);
+    ASSERT_EQ(PowerHalResult::SUCCESSFUL, result);
+}
+
+TEST_F(PowerHalWrapperHidlV1_1Test, TestSetBoostFailed) {
+    EXPECT_CALL(*mMockHalV1_1.get(), powerHintAsync(Eq(PowerHint::INTERACTION), Eq(1000)))
+        .Times(Exactly(1))
+        .WillRepeatedly([](PowerHint, int32_t) {
+            return hardware::Return<void>(hardware::Status::fromExceptionCode(-1));
+        });
+
+    auto result = mWrapper->setBoost(Boost::INTERACTION, 1000);
+    ASSERT_EQ(PowerHalResult::FAILED, result);
+}
+
+TEST_F(PowerHalWrapperHidlV1_1Test, TestSetBoostUnsupported) {
+    auto result = mWrapper->setBoost(Boost::CAMERA_LAUNCH, 10);
+    ASSERT_EQ(PowerHalResult::UNSUPPORTED, result);
+}
+
+TEST_F(PowerHalWrapperHidlV1_1Test, TestSetMode) {
+    {
+        InSequence seq;
+        EXPECT_CALL(*mMockHalV1_1.get(), powerHintAsync(Eq(PowerHint::LAUNCH), Eq(1)))
+            .Times(Exactly(1));
+        EXPECT_CALL(*mMockHalV1_1.get(), powerHintAsync(Eq(PowerHint::LOW_POWER), Eq(0)))
+            .Times(Exactly(1));
+        EXPECT_CALL(*mMockHalV1_1.get(), powerHintAsync(Eq(PowerHint::SUSTAINED_PERFORMANCE), Eq(1)))
+            .Times(Exactly(1));
+        EXPECT_CALL(*mMockHalV1_1.get(), powerHintAsync(Eq(PowerHint::VR_MODE), Eq(0)))
+            .Times(Exactly(1));
+        EXPECT_CALL(*mMockHalV1_0.get(), setInteractive(Eq(true)))
+            .Times(Exactly(1));
+        EXPECT_CALL(*mMockHalV1_0.get(),
+                    setFeature(Eq(Feature::POWER_FEATURE_DOUBLE_TAP_TO_WAKE), Eq(false)))
+            .Times(Exactly(1));
+    }
+
+    auto result = mWrapper->setMode(Mode::LAUNCH, true);
+    ASSERT_EQ(PowerHalResult::SUCCESSFUL, result);
+    result = mWrapper->setMode(Mode::LOW_POWER, false);
+    ASSERT_EQ(PowerHalResult::SUCCESSFUL, result);
+    result = mWrapper->setMode(Mode::SUSTAINED_PERFORMANCE, true);
+    ASSERT_EQ(PowerHalResult::SUCCESSFUL, result);
+    result = mWrapper->setMode(Mode::VR, false);
+    ASSERT_EQ(PowerHalResult::SUCCESSFUL, result);
+    result = mWrapper->setMode(Mode::INTERACTIVE, true);
+    ASSERT_EQ(PowerHalResult::SUCCESSFUL, result);
+    result = mWrapper->setMode(Mode::DOUBLE_TAP_TO_WAKE, false);
+    ASSERT_EQ(PowerHalResult::SUCCESSFUL, result);
+}
+
+TEST_F(PowerHalWrapperHidlV1_1Test, TestSetModeFailed) {
+    EXPECT_CALL(*mMockHalV1_1.get(), powerHintAsync(Eq(PowerHint::LAUNCH), Eq(1)))
+        .Times(Exactly(1))
+        .WillRepeatedly([](PowerHint, int32_t) {
+            return hardware::Return<void>(hardware::Status::fromExceptionCode(-1));
+        });
+
+    auto result = mWrapper->setMode(Mode::LAUNCH, 1);
+    ASSERT_EQ(PowerHalResult::FAILED, result);
+}
+
+TEST_F(PowerHalWrapperHidlV1_1Test, TestSetModeIgnored) {
+    auto result = mWrapper->setMode(Mode::CAMERA_STREAMING_HIGH, true);
+    ASSERT_EQ(PowerHalResult::UNSUPPORTED, result);
+}