blob: 53de4a6e567badf6f1b45abcd2c5984f59b789a9 [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();
53 void sendActualWorkDurationGroup(std::vector<WorkDuration> durations,
54 std::chrono::nanoseconds sleepBeforeLastSend);
Matt Buckley50c44062022-01-17 20:48:10 +000055 std::chrono::nanoseconds mAllowedDeviation;
56 std::chrono::nanoseconds mStaleTimeout;
Xiang Wange12b4fa2022-03-25 23:48:40 +000057};
58
59void AidlPowerHalWrapperTest::SetUp() {
60 mMockHal = new NiceMock<MockIPower>();
61 mMockSession = new NiceMock<MockIPowerHintSession>();
62 ON_CALL(*mMockHal.get(), getHintSessionPreferredRate(_)).WillByDefault(Return(Status::ok()));
63 mWrapper = std::make_unique<AidlPowerHalWrapper>(mMockHal);
Matt Buckley50c44062022-01-17 20:48:10 +000064 mWrapper->setAllowedActualDeviation(std::chrono::nanoseconds{10ms}.count());
65 mAllowedDeviation = std::chrono::nanoseconds{mWrapper->mAllowedActualDeviation};
66 mStaleTimeout = AidlPowerHalWrapper::kStaleTimeout;
Xiang Wange12b4fa2022-03-25 23:48:40 +000067}
68
69void AidlPowerHalWrapperTest::verifyAndClearExpectations() {
70 Mock::VerifyAndClearExpectations(mMockHal.get());
71 Mock::VerifyAndClearExpectations(mMockSession.get());
72}
73
74void AidlPowerHalWrapperTest::sendActualWorkDurationGroup(
75 std::vector<WorkDuration> durations, std::chrono::nanoseconds sleepBeforeLastSend) {
76 for (size_t i = 0; i < durations.size(); i++) {
77 if (i == durations.size() - 1) {
78 std::this_thread::sleep_for(sleepBeforeLastSend);
79 }
80 auto duration = durations[i];
81 mWrapper->sendActualWorkDuration(duration.durationNanos, duration.timeStampNanos);
82 }
83}
Matt Buckley50c44062022-01-17 20:48:10 +000084
Xiang Wange12b4fa2022-03-25 23:48:40 +000085WorkDuration toWorkDuration(std::chrono::nanoseconds durationNanos, int64_t timeStampNanos) {
86 WorkDuration duration;
87 duration.durationNanos = durationNanos.count();
88 duration.timeStampNanos = timeStampNanos;
89 return duration;
90}
91
Matt Buckley50c44062022-01-17 20:48:10 +000092WorkDuration toWorkDuration(std::pair<std::chrono::nanoseconds, nsecs_t> timePair) {
93 return toWorkDuration(timePair.first, timePair.second);
94}
95
Xiang Wang0aba49e2022-04-06 16:13:59 +000096std::string printWorkDurations(const ::std::vector<WorkDuration>& durations) {
97 std::ostringstream os;
98 for (auto duration : durations) {
99 os << duration.toString();
100 os << "\n";
101 }
102 return os.str();
103}
104
Xiang Wange12b4fa2022-03-25 23:48:40 +0000105namespace {
106TEST_F(AidlPowerHalWrapperTest, supportsPowerHintSession) {
107 ASSERT_TRUE(mWrapper->supportsPowerHintSession());
108 Mock::VerifyAndClearExpectations(mMockHal.get());
109 ON_CALL(*mMockHal.get(), getHintSessionPreferredRate(_))
110 .WillByDefault(Return(Status::fromExceptionCode(Status::Exception::EX_ILLEGAL_STATE)));
111 auto newWrapper = AidlPowerHalWrapper(mMockHal);
112 EXPECT_FALSE(newWrapper.supportsPowerHintSession());
113}
114
115TEST_F(AidlPowerHalWrapperTest, startPowerHintSession) {
116 ASSERT_TRUE(mWrapper->supportsPowerHintSession());
117 std::vector<int32_t> threadIds = {1, 2};
118 mWrapper->setPowerHintSessionThreadIds(threadIds);
119 EXPECT_CALL(*mMockHal.get(), createHintSession(_, _, threadIds, _, _))
120 .WillOnce(DoAll(SetArgPointee<4>(mMockSession), Return(Status::ok())));
121 EXPECT_TRUE(mWrapper->startPowerHintSession());
122 EXPECT_FALSE(mWrapper->startPowerHintSession());
123}
124
Matt Buckley50c44062022-01-17 20:48:10 +0000125TEST_F(AidlPowerHalWrapperTest, restartNewPowerHintSessionWithNewThreadIds) {
Xiang Wange12b4fa2022-03-25 23:48:40 +0000126 ASSERT_TRUE(mWrapper->supportsPowerHintSession());
127
128 std::vector<int32_t> threadIds = {1, 2};
129 EXPECT_CALL(*mMockHal.get(), createHintSession(_, _, threadIds, _, _))
130 .WillOnce(DoAll(SetArgPointee<4>(mMockSession), Return(Status::ok())));
131 mWrapper->setPowerHintSessionThreadIds(threadIds);
132 EXPECT_EQ(mWrapper->getPowerHintSessionThreadIds(), threadIds);
133 ASSERT_TRUE(mWrapper->startPowerHintSession());
134 verifyAndClearExpectations();
135
136 threadIds = {2, 3};
137 EXPECT_CALL(*mMockHal.get(), createHintSession(_, _, threadIds, _, _))
138 .WillOnce(DoAll(SetArgPointee<4>(mMockSession), Return(Status::ok())));
139 EXPECT_CALL(*mMockSession.get(), close()).Times(1);
140 mWrapper->setPowerHintSessionThreadIds(threadIds);
141 EXPECT_EQ(mWrapper->getPowerHintSessionThreadIds(), threadIds);
142 verifyAndClearExpectations();
143
144 EXPECT_CALL(*mMockHal.get(), createHintSession(_, _, threadIds, _, _)).Times(0);
145 EXPECT_CALL(*mMockSession.get(), close()).Times(0);
146 mWrapper->setPowerHintSessionThreadIds(threadIds);
147 verifyAndClearExpectations();
148}
149
150TEST_F(AidlPowerHalWrapperTest, setTargetWorkDuration) {
151 ASSERT_TRUE(mWrapper->supportsPowerHintSession());
152
153 std::vector<int32_t> threadIds = {1, 2};
154 mWrapper->setPowerHintSessionThreadIds(threadIds);
155 EXPECT_CALL(*mMockHal.get(), createHintSession(_, _, threadIds, _, _))
156 .WillOnce(DoAll(SetArgPointee<4>(mMockSession), Return(Status::ok())));
157 ASSERT_TRUE(mWrapper->startPowerHintSession());
158 verifyAndClearExpectations();
159
160 std::chrono::nanoseconds base = 100ms;
161 // test cases with target work duration and whether it should update hint against baseline 100ms
Matt Buckley50c44062022-01-17 20:48:10 +0000162 const std::vector<std::pair<std::chrono::nanoseconds, bool>> testCases =
163 {{0ms, true}, {-1ms, true}, {200ms, true}, {2ms, true}, {100ms, false}, {109ms, true}};
Xiang Wange12b4fa2022-03-25 23:48:40 +0000164
165 for (const auto& test : testCases) {
166 // reset to 100ms baseline
167 mWrapper->setTargetWorkDuration(1);
168 mWrapper->setTargetWorkDuration(base.count());
169
170 auto target = test.first;
171 EXPECT_CALL(*mMockSession.get(), updateTargetWorkDuration(target.count()))
172 .Times(test.second ? 1 : 0);
173 mWrapper->setTargetWorkDuration(target.count());
174 verifyAndClearExpectations();
175 }
176}
177
178TEST_F(AidlPowerHalWrapperTest, setTargetWorkDuration_shouldReconnectOnError) {
179 ASSERT_TRUE(mWrapper->supportsPowerHintSession());
180
181 std::vector<int32_t> threadIds = {1, 2};
182 mWrapper->setPowerHintSessionThreadIds(threadIds);
183 EXPECT_CALL(*mMockHal.get(), createHintSession(_, _, threadIds, _, _))
184 .WillOnce(DoAll(SetArgPointee<4>(mMockSession), Return(Status::ok())));
185 ASSERT_TRUE(mWrapper->startPowerHintSession());
186 verifyAndClearExpectations();
187
188 EXPECT_CALL(*mMockSession.get(), updateTargetWorkDuration(1))
189 .WillOnce(Return(Status::fromExceptionCode(Status::Exception::EX_ILLEGAL_STATE)));
190 mWrapper->setTargetWorkDuration(1);
191 EXPECT_TRUE(mWrapper->shouldReconnectHAL());
192}
193
194TEST_F(AidlPowerHalWrapperTest, sendActualWorkDuration) {
195 ASSERT_TRUE(mWrapper->supportsPowerHintSession());
196
197 std::vector<int32_t> threadIds = {1, 2};
198 mWrapper->setPowerHintSessionThreadIds(threadIds);
199 EXPECT_CALL(*mMockHal.get(), createHintSession(_, _, threadIds, _, _))
200 .WillOnce(DoAll(SetArgPointee<4>(mMockSession), Return(Status::ok())));
201 ASSERT_TRUE(mWrapper->startPowerHintSession());
202 verifyAndClearExpectations();
203
204 auto base = toWorkDuration(100ms, 0);
205 // test cases with actual work durations and whether it should update hint against baseline
206 // 100ms
207 const std::vector<std::pair<std::vector<std::pair<std::chrono::nanoseconds, nsecs_t>>, bool>>
208 testCases = {{{{-1ms, 100}}, false},
Matt Buckley50c44062022-01-17 20:48:10 +0000209 {{{100ms - (mAllowedDeviation / 2), 100}}, false},
210 {{{100ms + (mAllowedDeviation / 2), 100}}, false},
211 {{{100ms + (mAllowedDeviation + 1ms), 100}}, true},
212 {{{100ms - (mAllowedDeviation + 1ms), 100}}, true},
Xiang Wange12b4fa2022-03-25 23:48:40 +0000213 {{{100ms, 100}, {200ms, 200}}, true},
214 {{{100ms, 500}, {100ms, 600}, {3ms, 600}}, true}};
215
216 for (const auto& test : testCases) {
217 // reset actual duration
Matt Buckley50c44062022-01-17 20:48:10 +0000218 sendActualWorkDurationGroup({base}, mStaleTimeout);
Xiang Wange12b4fa2022-03-25 23:48:40 +0000219
220 auto raw = test.first;
221 std::vector<WorkDuration> durations(raw.size());
222 std::transform(raw.begin(), raw.end(), durations.begin(),
Matt Buckley50c44062022-01-17 20:48:10 +0000223 [](auto d) { return toWorkDuration(d); });
Xiang Wange12b4fa2022-03-25 23:48:40 +0000224 EXPECT_CALL(*mMockSession.get(), reportActualWorkDuration(durations))
225 .Times(test.second ? 1 : 0);
226 sendActualWorkDurationGroup(durations, 0ms);
227 verifyAndClearExpectations();
228 }
229}
230
Xiang Wange12b4fa2022-03-25 23:48:40 +0000231TEST_F(AidlPowerHalWrapperTest, sendActualWorkDuration_exceedsStaleTime) {
232 ASSERT_TRUE(mWrapper->supportsPowerHintSession());
233
234 std::vector<int32_t> threadIds = {1, 2};
235 mWrapper->setPowerHintSessionThreadIds(threadIds);
236 EXPECT_CALL(*mMockHal.get(), createHintSession(_, _, threadIds, _, _))
237 .WillOnce(DoAll(SetArgPointee<4>(mMockSession), Return(Status::ok())));
238 ASSERT_TRUE(mWrapper->startPowerHintSession());
239 verifyAndClearExpectations();
240
241 auto base = toWorkDuration(100ms, 0);
242 // test cases with actual work durations and whether it should update hint against baseline
243 // 100ms
Matt Buckley50c44062022-01-17 20:48:10 +0000244 const std::vector<std::tuple<std::vector<std::pair<std::chrono::nanoseconds, nsecs_t>>,
245 std::chrono::nanoseconds, bool>>
246 testCases = {{{{100ms, 100}}, mStaleTimeout, true},
247 {{{100ms + (mAllowedDeviation / 2), 100}}, mStaleTimeout, true},
248 {{{100ms, 100}}, mStaleTimeout / 2, false}};
Xiang Wange12b4fa2022-03-25 23:48:40 +0000249
250 for (const auto& test : testCases) {
251 // reset actual duration
Matt Buckley50c44062022-01-17 20:48:10 +0000252 sendActualWorkDurationGroup({base}, mStaleTimeout);
Xiang Wange12b4fa2022-03-25 23:48:40 +0000253
Matt Buckley50c44062022-01-17 20:48:10 +0000254 auto raw = std::get<0>(test);
Xiang Wange12b4fa2022-03-25 23:48:40 +0000255 std::vector<WorkDuration> durations(raw.size());
256 std::transform(raw.begin(), raw.end(), durations.begin(),
Matt Buckley50c44062022-01-17 20:48:10 +0000257 [](auto d) { return toWorkDuration(d); });
Xiang Wange12b4fa2022-03-25 23:48:40 +0000258 EXPECT_CALL(*mMockSession.get(), reportActualWorkDuration(durations))
Matt Buckley50c44062022-01-17 20:48:10 +0000259 .Times(std::get<2>(test) ? 1 : 0);
260 sendActualWorkDurationGroup(durations, std::get<1>(test));
Xiang Wange12b4fa2022-03-25 23:48:40 +0000261 verifyAndClearExpectations();
262 }
263}
264
265TEST_F(AidlPowerHalWrapperTest, sendActualWorkDuration_shouldReconnectOnError) {
266 ASSERT_TRUE(mWrapper->supportsPowerHintSession());
267
268 std::vector<int32_t> threadIds = {1, 2};
269 mWrapper->setPowerHintSessionThreadIds(threadIds);
270 EXPECT_CALL(*mMockHal.get(), createHintSession(_, _, threadIds, _, _))
271 .WillOnce(DoAll(SetArgPointee<4>(mMockSession), Return(Status::ok())));
272 ASSERT_TRUE(mWrapper->startPowerHintSession());
273 verifyAndClearExpectations();
274 WorkDuration duration;
275 duration.durationNanos = 1;
276 EXPECT_CALL(*mMockSession.get(), reportActualWorkDuration(_))
277 .WillOnce(Return(Status::fromExceptionCode(Status::Exception::EX_ILLEGAL_STATE)));
278 sendActualWorkDurationGroup({duration}, 0ms);
279 EXPECT_TRUE(mWrapper->shouldReconnectHAL());
280}
281
282} // namespace
283} // namespace android::Hwc2::impl