blob: ab38b294c5886bb642e79859907929f28599d40c [file] [log] [blame]
Xiang Wange12b4fa2022-03-25 23:48:40 +00001/*
2 * Copyright 2022 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#undef LOG_TAG
18#define LOG_TAG "AidlPowerHalWrapperTest"
19
Xiang Wang0aba49e2022-04-06 16:13:59 +000020#include <android-base/stringprintf.h>
Xiang Wange12b4fa2022-03-25 23:48:40 +000021#include <android/hardware/power/IPower.h>
22#include <android/hardware/power/IPowerHintSession.h>
23#include <gmock/gmock.h>
24#include <gtest/gtest.h>
25#include <algorithm>
26#include <chrono>
27#include <memory>
28#include "DisplayHardware/PowerAdvisor.h"
29#include "android/hardware/power/WorkDuration.h"
30#include "binder/Status.h"
31#include "log/log_main.h"
32#include "mock/DisplayHardware/MockIPower.h"
33#include "mock/DisplayHardware/MockIPowerHintSession.h"
34#include "utils/Timers.h"
35
36using namespace android;
37using namespace android::Hwc2::mock;
38using namespace android::hardware::power;
39using namespace std::chrono_literals;
40using namespace testing;
41
42namespace android::Hwc2::impl {
43
44class AidlPowerHalWrapperTest : public testing::Test {
45public:
46 void SetUp() override;
47
48protected:
49 std::unique_ptr<AidlPowerHalWrapper> mWrapper = nullptr;
50 sp<NiceMock<MockIPower>> mMockHal = nullptr;
51 sp<NiceMock<MockIPowerHintSession>> mMockSession = nullptr;
52 void verifyAndClearExpectations();
Matt Buckley44e612e2022-08-30 22:02:37 +000053 void sendActualWorkDurationGroup(std::vector<WorkDuration> durations);
54 static constexpr std::chrono::duration kStaleTimeout = 100ms;
Xiang Wange12b4fa2022-03-25 23:48:40 +000055};
56
57void AidlPowerHalWrapperTest::SetUp() {
Ady Abrahamd11bade2022-08-01 16:18:03 -070058 mMockHal = sp<NiceMock<MockIPower>>::make();
59 mMockSession = sp<NiceMock<MockIPowerHintSession>>::make();
Xiang Wange12b4fa2022-03-25 23:48:40 +000060 ON_CALL(*mMockHal.get(), getHintSessionPreferredRate(_)).WillByDefault(Return(Status::ok()));
61 mWrapper = std::make_unique<AidlPowerHalWrapper>(mMockHal);
62}
63
64void AidlPowerHalWrapperTest::verifyAndClearExpectations() {
65 Mock::VerifyAndClearExpectations(mMockHal.get());
66 Mock::VerifyAndClearExpectations(mMockSession.get());
67}
68
Matt Buckley44e612e2022-08-30 22:02:37 +000069void AidlPowerHalWrapperTest::sendActualWorkDurationGroup(std::vector<WorkDuration> durations) {
Xiang Wange12b4fa2022-03-25 23:48:40 +000070 for (size_t i = 0; i < durations.size(); i++) {
Xiang Wange12b4fa2022-03-25 23:48:40 +000071 auto duration = durations[i];
72 mWrapper->sendActualWorkDuration(duration.durationNanos, duration.timeStampNanos);
73 }
74}
Matt Buckley50c44062022-01-17 20:48:10 +000075
Xiang Wange12b4fa2022-03-25 23:48:40 +000076WorkDuration toWorkDuration(std::chrono::nanoseconds durationNanos, int64_t timeStampNanos) {
77 WorkDuration duration;
78 duration.durationNanos = durationNanos.count();
79 duration.timeStampNanos = timeStampNanos;
80 return duration;
81}
82
Matt Buckley50c44062022-01-17 20:48:10 +000083WorkDuration toWorkDuration(std::pair<std::chrono::nanoseconds, nsecs_t> timePair) {
84 return toWorkDuration(timePair.first, timePair.second);
85}
86
Xiang Wang0aba49e2022-04-06 16:13:59 +000087std::string printWorkDurations(const ::std::vector<WorkDuration>& durations) {
88 std::ostringstream os;
89 for (auto duration : durations) {
90 os << duration.toString();
91 os << "\n";
92 }
93 return os.str();
94}
95
Xiang Wange12b4fa2022-03-25 23:48:40 +000096namespace {
97TEST_F(AidlPowerHalWrapperTest, supportsPowerHintSession) {
98 ASSERT_TRUE(mWrapper->supportsPowerHintSession());
99 Mock::VerifyAndClearExpectations(mMockHal.get());
100 ON_CALL(*mMockHal.get(), getHintSessionPreferredRate(_))
101 .WillByDefault(Return(Status::fromExceptionCode(Status::Exception::EX_ILLEGAL_STATE)));
102 auto newWrapper = AidlPowerHalWrapper(mMockHal);
103 EXPECT_FALSE(newWrapper.supportsPowerHintSession());
104}
105
106TEST_F(AidlPowerHalWrapperTest, startPowerHintSession) {
107 ASSERT_TRUE(mWrapper->supportsPowerHintSession());
108 std::vector<int32_t> threadIds = {1, 2};
109 mWrapper->setPowerHintSessionThreadIds(threadIds);
110 EXPECT_CALL(*mMockHal.get(), createHintSession(_, _, threadIds, _, _))
111 .WillOnce(DoAll(SetArgPointee<4>(mMockSession), Return(Status::ok())));
112 EXPECT_TRUE(mWrapper->startPowerHintSession());
113 EXPECT_FALSE(mWrapper->startPowerHintSession());
114}
115
Matt Buckley50c44062022-01-17 20:48:10 +0000116TEST_F(AidlPowerHalWrapperTest, restartNewPowerHintSessionWithNewThreadIds) {
Xiang Wange12b4fa2022-03-25 23:48:40 +0000117 ASSERT_TRUE(mWrapper->supportsPowerHintSession());
118
119 std::vector<int32_t> threadIds = {1, 2};
120 EXPECT_CALL(*mMockHal.get(), createHintSession(_, _, threadIds, _, _))
121 .WillOnce(DoAll(SetArgPointee<4>(mMockSession), Return(Status::ok())));
122 mWrapper->setPowerHintSessionThreadIds(threadIds);
123 EXPECT_EQ(mWrapper->getPowerHintSessionThreadIds(), threadIds);
124 ASSERT_TRUE(mWrapper->startPowerHintSession());
125 verifyAndClearExpectations();
126
127 threadIds = {2, 3};
128 EXPECT_CALL(*mMockHal.get(), createHintSession(_, _, threadIds, _, _))
129 .WillOnce(DoAll(SetArgPointee<4>(mMockSession), Return(Status::ok())));
130 EXPECT_CALL(*mMockSession.get(), close()).Times(1);
131 mWrapper->setPowerHintSessionThreadIds(threadIds);
132 EXPECT_EQ(mWrapper->getPowerHintSessionThreadIds(), threadIds);
133 verifyAndClearExpectations();
134
135 EXPECT_CALL(*mMockHal.get(), createHintSession(_, _, threadIds, _, _)).Times(0);
136 EXPECT_CALL(*mMockSession.get(), close()).Times(0);
137 mWrapper->setPowerHintSessionThreadIds(threadIds);
138 verifyAndClearExpectations();
139}
140
141TEST_F(AidlPowerHalWrapperTest, setTargetWorkDuration) {
142 ASSERT_TRUE(mWrapper->supportsPowerHintSession());
143
144 std::vector<int32_t> threadIds = {1, 2};
145 mWrapper->setPowerHintSessionThreadIds(threadIds);
146 EXPECT_CALL(*mMockHal.get(), createHintSession(_, _, threadIds, _, _))
147 .WillOnce(DoAll(SetArgPointee<4>(mMockSession), Return(Status::ok())));
148 ASSERT_TRUE(mWrapper->startPowerHintSession());
149 verifyAndClearExpectations();
150
151 std::chrono::nanoseconds base = 100ms;
152 // test cases with target work duration and whether it should update hint against baseline 100ms
Matt Buckley50c44062022-01-17 20:48:10 +0000153 const std::vector<std::pair<std::chrono::nanoseconds, bool>> testCases =
154 {{0ms, true}, {-1ms, true}, {200ms, true}, {2ms, true}, {100ms, false}, {109ms, true}};
Xiang Wange12b4fa2022-03-25 23:48:40 +0000155
156 for (const auto& test : testCases) {
157 // reset to 100ms baseline
158 mWrapper->setTargetWorkDuration(1);
159 mWrapper->setTargetWorkDuration(base.count());
160
161 auto target = test.first;
162 EXPECT_CALL(*mMockSession.get(), updateTargetWorkDuration(target.count()))
163 .Times(test.second ? 1 : 0);
164 mWrapper->setTargetWorkDuration(target.count());
165 verifyAndClearExpectations();
166 }
167}
168
169TEST_F(AidlPowerHalWrapperTest, setTargetWorkDuration_shouldReconnectOnError) {
170 ASSERT_TRUE(mWrapper->supportsPowerHintSession());
171
172 std::vector<int32_t> threadIds = {1, 2};
173 mWrapper->setPowerHintSessionThreadIds(threadIds);
174 EXPECT_CALL(*mMockHal.get(), createHintSession(_, _, threadIds, _, _))
175 .WillOnce(DoAll(SetArgPointee<4>(mMockSession), Return(Status::ok())));
176 ASSERT_TRUE(mWrapper->startPowerHintSession());
177 verifyAndClearExpectations();
178
179 EXPECT_CALL(*mMockSession.get(), updateTargetWorkDuration(1))
180 .WillOnce(Return(Status::fromExceptionCode(Status::Exception::EX_ILLEGAL_STATE)));
181 mWrapper->setTargetWorkDuration(1);
182 EXPECT_TRUE(mWrapper->shouldReconnectHAL());
183}
184
185TEST_F(AidlPowerHalWrapperTest, sendActualWorkDuration) {
186 ASSERT_TRUE(mWrapper->supportsPowerHintSession());
187
188 std::vector<int32_t> threadIds = {1, 2};
189 mWrapper->setPowerHintSessionThreadIds(threadIds);
190 EXPECT_CALL(*mMockHal.get(), createHintSession(_, _, threadIds, _, _))
191 .WillOnce(DoAll(SetArgPointee<4>(mMockSession), Return(Status::ok())));
192 ASSERT_TRUE(mWrapper->startPowerHintSession());
193 verifyAndClearExpectations();
194
195 auto base = toWorkDuration(100ms, 0);
196 // test cases with actual work durations and whether it should update hint against baseline
197 // 100ms
198 const std::vector<std::pair<std::vector<std::pair<std::chrono::nanoseconds, nsecs_t>>, bool>>
199 testCases = {{{{-1ms, 100}}, false},
Matt Buckley44e612e2022-08-30 22:02:37 +0000200 {{{50ms, 100}}, true},
Xiang Wange12b4fa2022-03-25 23:48:40 +0000201 {{{100ms, 100}, {200ms, 200}}, true},
202 {{{100ms, 500}, {100ms, 600}, {3ms, 600}}, true}};
203
204 for (const auto& test : testCases) {
205 // reset actual duration
Matt Buckley44e612e2022-08-30 22:02:37 +0000206 sendActualWorkDurationGroup({base});
Xiang Wange12b4fa2022-03-25 23:48:40 +0000207
208 auto raw = test.first;
209 std::vector<WorkDuration> durations(raw.size());
210 std::transform(raw.begin(), raw.end(), durations.begin(),
Matt Buckley50c44062022-01-17 20:48:10 +0000211 [](auto d) { return toWorkDuration(d); });
Matt Buckley44e612e2022-08-30 22:02:37 +0000212 for (auto& duration : durations) {
213 EXPECT_CALL(*mMockSession.get(),
214 reportActualWorkDuration(std::vector<WorkDuration>{duration}))
215 .Times(test.second ? 1 : 0);
216 }
217 sendActualWorkDurationGroup(durations);
Xiang Wange12b4fa2022-03-25 23:48:40 +0000218 verifyAndClearExpectations();
219 }
220}
221
222TEST_F(AidlPowerHalWrapperTest, sendActualWorkDuration_shouldReconnectOnError) {
223 ASSERT_TRUE(mWrapper->supportsPowerHintSession());
224
225 std::vector<int32_t> threadIds = {1, 2};
226 mWrapper->setPowerHintSessionThreadIds(threadIds);
227 EXPECT_CALL(*mMockHal.get(), createHintSession(_, _, threadIds, _, _))
228 .WillOnce(DoAll(SetArgPointee<4>(mMockSession), Return(Status::ok())));
229 ASSERT_TRUE(mWrapper->startPowerHintSession());
230 verifyAndClearExpectations();
231 WorkDuration duration;
232 duration.durationNanos = 1;
233 EXPECT_CALL(*mMockSession.get(), reportActualWorkDuration(_))
234 .WillOnce(Return(Status::fromExceptionCode(Status::Exception::EX_ILLEGAL_STATE)));
Matt Buckley44e612e2022-08-30 22:02:37 +0000235 sendActualWorkDurationGroup({duration});
Xiang Wange12b4fa2022-03-25 23:48:40 +0000236 EXPECT_TRUE(mWrapper->shouldReconnectHAL());
237}
238
239} // namespace
240} // namespace android::Hwc2::impl