xref: /aosp_15_r20/frameworks/native/services/surfaceflinger/tests/unittests/PowerAdvisorTest.cpp (revision 38e8c45f13ce32b0dcecb25141ffecaf386fa17f)
1 /*
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 "PowerAdvisorTest"
19 
20 #include "PowerAdvisor/PowerAdvisor.h"
21 
22 #include <android_os.h>
23 #include <binder/Status.h>
24 #include <com_android_graphics_surfaceflinger_flags.h>
25 #include <common/FlagManager.h>
26 #include <common/test/FlagUtils.h>
27 #include <gmock/gmock.h>
28 #include <gtest/gtest.h>
29 #include <powermanager/PowerHalWrapper.h>
30 #include <ui/DisplayId.h>
31 #include <chrono>
32 #include <future>
33 #include "mock/PowerAdvisor/MockPowerHalController.h"
34 #include "mock/PowerAdvisor/MockPowerHintSessionWrapper.h"
35 
36 using namespace android;
37 using namespace android::adpf::mock;
38 using namespace android::hardware::power;
39 using namespace std::chrono_literals;
40 using namespace testing;
41 using namespace android::power;
42 
43 namespace android::adpf::impl {
44 
45 class PowerAdvisorTest : public testing::Test {
46 public:
47     void SetUp() override;
48     void SetUpFmq(bool usesSharedEventFlag, bool isQueueFull);
49     void startPowerHintSession(bool returnValidSession = true);
50     void fakeBasicFrameTiming(TimePoint startTime, Duration vsyncPeriod);
51     void setExpectedTiming(Duration totalFrameTargetDuration, TimePoint expectedPresentTime);
52     Duration getFenceWaitDelayDuration(bool skipValidate);
53     Duration getErrorMargin();
54     void setTimingTestingMode(bool testinMode);
55     void allowReportActualToAcquireMutex();
56     bool sessionExists();
57     int64_t toNanos(Duration d);
58 
59     struct GpuTestConfig {
60         bool adpfGpuFlagOn;
61         Duration frame1GpuFenceDuration;
62         Duration frame2GpuFenceDuration;
63         Duration vsyncPeriod;
64         Duration presentDuration = 0ms;
65         Duration postCompDuration = 0ms;
66         bool frame1RequiresRenderEngine;
67         bool frame2RequiresRenderEngine;
68         bool usesFmq = false;
69         bool usesSharedFmqFlag = true;
70         bool fmqFull = false;
71     };
72 
73     void testGpuScenario(GpuTestConfig& config, WorkDuration& ret);
74 
75 protected:
76     std::unique_ptr<PowerAdvisor> mPowerAdvisor;
77     MockPowerHalController* mMockPowerHalController;
78     std::shared_ptr<MockPowerHintSessionWrapper> mMockPowerHintSession;
79     std::shared_ptr<AidlMessageQueue<ChannelMessage, SynchronizedReadWrite>> mBackendFmq;
80     std::shared_ptr<AidlMessageQueue<int8_t, SynchronizedReadWrite>> mBackendFlagQueue;
81     android::hardware::EventFlag* mEventFlag;
82     uint32_t mWriteFlagBitmask = 2;
83     uint32_t mReadFlagBitmask = 1;
84     int64_t mSessionId = 123;
85     SET_FLAG_FOR_TEST(android::os::adpf_use_fmq_channel, true);
86     SET_FLAG_FOR_TEST(android::os::adpf_use_fmq_channel_fixed, false);
87     SET_FLAG_FOR_TEST(com::android::graphics::surfaceflinger::flags::adpf_fmq_sf, false);
88 };
89 
sessionExists()90 bool PowerAdvisorTest::sessionExists() {
91     std::scoped_lock lock(mPowerAdvisor->mHintSessionMutex);
92     return mPowerAdvisor->mHintSession != nullptr;
93 }
94 
toNanos(Duration d)95 int64_t PowerAdvisorTest::toNanos(Duration d) {
96     return std::chrono::nanoseconds(d).count();
97 }
98 
SetUp()99 void PowerAdvisorTest::SetUp() {
100     mPowerAdvisor = std::make_unique<impl::PowerAdvisor>([]() {}, 80ms);
101     mPowerAdvisor->mPowerHal = std::make_unique<NiceMock<MockPowerHalController>>();
102     mMockPowerHalController =
103             reinterpret_cast<MockPowerHalController*>(mPowerAdvisor->mPowerHal.get());
104     ON_CALL(*mMockPowerHalController, getHintSessionPreferredRate)
105             .WillByDefault(Return(
106                     ByMove(HalResult<int64_t>::fromStatus(ndk::ScopedAStatus::ok(), 16000))));
107 }
108 
SetUpFmq(bool usesSharedEventFlag,bool isQueueFull)109 void PowerAdvisorTest::SetUpFmq(bool usesSharedEventFlag, bool isQueueFull) {
110     mBackendFmq = std::make_shared<
111             AidlMessageQueue<ChannelMessage, SynchronizedReadWrite>>(2, !usesSharedEventFlag);
112     ChannelConfig config;
113     config.channelDescriptor = mBackendFmq->dupeDesc();
114     if (usesSharedEventFlag) {
115         mBackendFlagQueue =
116                 std::make_shared<AidlMessageQueue<int8_t, SynchronizedReadWrite>>(1, true);
117         config.eventFlagDescriptor = mBackendFlagQueue->dupeDesc();
118         ASSERT_EQ(android::hardware::EventFlag::createEventFlag(mBackendFlagQueue
119                                                                         ->getEventFlagWord(),
120                                                                 &mEventFlag),
121                   android::NO_ERROR);
122     } else {
123         ASSERT_EQ(android::hardware::EventFlag::createEventFlag(mBackendFmq->getEventFlagWord(),
124                                                                 &mEventFlag),
125                   android::NO_ERROR);
126     }
127     config.writeFlagBitmask = static_cast<int32_t>(mWriteFlagBitmask);
128     config.readFlagBitmask = static_cast<int32_t>(mReadFlagBitmask);
129     ON_CALL(*mMockPowerHalController, getSessionChannel)
130             .WillByDefault(Return(
131                     ByMove(HalResult<ChannelConfig>::fromStatus(Status::ok(), std::move(config)))));
132     startPowerHintSession();
133     if (isQueueFull) {
134         std::vector<ChannelMessage> msgs;
135         msgs.resize(2);
136         mBackendFmq->writeBlocking(msgs.data(), 2, mReadFlagBitmask, mWriteFlagBitmask,
137                                    std::chrono::nanoseconds(1ms).count(), mEventFlag);
138     }
139 }
140 
startPowerHintSession(bool returnValidSession)141 void PowerAdvisorTest::startPowerHintSession(bool returnValidSession) {
142     mMockPowerHintSession = std::make_shared<NiceMock<MockPowerHintSessionWrapper>>();
143     if (returnValidSession) {
144         ON_CALL(*mMockPowerHalController, createHintSessionWithConfig)
145                 .WillByDefault(DoAll(SetArgPointee<5>(aidl::android::hardware::power::SessionConfig{
146                                              .id = mSessionId}),
147                                      Return(HalResult<std::shared_ptr<PowerHintSessionWrapper>>::
148                                                     fromStatus(binder::Status::ok(),
149                                                                mMockPowerHintSession))));
150     } else {
151         ON_CALL(*mMockPowerHalController, createHintSessionWithConfig).WillByDefault([] {
152             return HalResult<
153                     std::shared_ptr<PowerHintSessionWrapper>>::fromStatus(ndk::ScopedAStatus::ok(),
154                                                                           nullptr);
155         });
156     }
157     mPowerAdvisor->enablePowerHintSession(true);
158     mPowerAdvisor->startPowerHintSession({1, 2, 3});
159     ON_CALL(*mMockPowerHintSession, updateTargetWorkDuration)
160             .WillByDefault(Return(testing::ByMove(HalResult<void>::ok())));
161 }
162 
setExpectedTiming(Duration totalFrameTargetDuration,TimePoint expectedPresentTime)163 void PowerAdvisorTest::setExpectedTiming(Duration totalFrameTargetDuration,
164                                          TimePoint expectedPresentTime) {
165     mPowerAdvisor->setTotalFrameTargetWorkDuration(totalFrameTargetDuration);
166     mPowerAdvisor->setExpectedPresentTime(expectedPresentTime);
167 }
168 
fakeBasicFrameTiming(TimePoint startTime,Duration vsyncPeriod)169 void PowerAdvisorTest::fakeBasicFrameTiming(TimePoint startTime, Duration vsyncPeriod) {
170     mPowerAdvisor->setCommitStart(startTime);
171     mPowerAdvisor->setFrameDelay(0ns);
172     mPowerAdvisor->updateTargetWorkDuration(vsyncPeriod);
173 }
174 
setTimingTestingMode(bool testingMode)175 void PowerAdvisorTest::setTimingTestingMode(bool testingMode) {
176     mPowerAdvisor->mTimingTestingMode = testingMode;
177 }
178 
allowReportActualToAcquireMutex()179 void PowerAdvisorTest::allowReportActualToAcquireMutex() {
180     mPowerAdvisor->mDelayReportActualMutexAcquisitonPromise.set_value(true);
181 }
182 
testGpuScenario(GpuTestConfig & config,WorkDuration & ret)183 void PowerAdvisorTest::testGpuScenario(GpuTestConfig& config, WorkDuration& ret) {
184     SET_FLAG_FOR_TEST(com::android::graphics::surfaceflinger::flags::adpf_gpu_sf,
185                       config.adpfGpuFlagOn);
186     SET_FLAG_FOR_TEST(android::os::adpf_use_fmq_channel_fixed, config.usesFmq);
187     SET_FLAG_FOR_TEST(com::android::graphics::surfaceflinger::flags::adpf_fmq_sf, config.usesFmq);
188     mPowerAdvisor->onBootFinished();
189     bool expectsFmqSuccess = config.usesSharedFmqFlag && !config.fmqFull;
190     if (config.usesFmq) {
191         SetUpFmq(config.usesSharedFmqFlag, config.fmqFull);
192     } else {
193         startPowerHintSession();
194     }
195 
196     std::vector<DisplayId> displayIds{PhysicalDisplayId::fromPort(42u), GpuVirtualDisplayId(0),
197                                       GpuVirtualDisplayId(1)};
198     mPowerAdvisor->setDisplays(displayIds);
199     auto display1 = displayIds[0];
200     // 60hz
201 
202     TimePoint startTime = TimePoint::now();
203     int64_t target;
204     SessionHint hint;
205     if (!config.usesFmq || !expectsFmqSuccess) {
206         EXPECT_CALL(*mMockPowerHintSession, updateTargetWorkDuration(_))
207                 .Times(1)
208                 .WillOnce(DoAll(testing::SaveArg<0>(&target),
209                                 testing::Return(testing::ByMove(HalResult<void>::ok()))));
210         EXPECT_CALL(*mMockPowerHintSession, sendHint(_))
211                 .Times(1)
212                 .WillOnce(DoAll(testing::SaveArg<0>(&hint),
213                                 testing::Return(testing::ByMove(HalResult<void>::ok()))));
214     }
215     // advisor only starts on frame 2 so do an initial frame
216     fakeBasicFrameTiming(startTime, config.vsyncPeriod);
217     // send a load hint
218     mPowerAdvisor->notifyCpuLoadUp();
219     if (config.usesFmq && expectsFmqSuccess) {
220         std::vector<ChannelMessage> msgs;
221         ASSERT_EQ(mBackendFmq->availableToRead(), 2uL);
222         msgs.resize(2);
223         ASSERT_TRUE(mBackendFmq->readBlocking(msgs.data(), 2, mReadFlagBitmask, mWriteFlagBitmask,
224                                               std::chrono::nanoseconds(1ms).count(), mEventFlag));
225         ASSERT_EQ(msgs[0].sessionID, mSessionId);
226         ASSERT_GE(msgs[0].timeStampNanos, startTime.ns());
227         ASSERT_EQ(msgs[0].data.getTag(),
228                   ChannelMessage::ChannelMessageContents::Tag::targetDuration);
229         target = msgs[0].data.get<ChannelMessage::ChannelMessageContents::Tag::targetDuration>();
230         ASSERT_EQ(msgs[1].sessionID, mSessionId);
231         ASSERT_GE(msgs[1].timeStampNanos, startTime.ns());
232         ASSERT_EQ(msgs[1].data.getTag(), ChannelMessage::ChannelMessageContents::Tag::hint);
233         hint = msgs[1].data.get<ChannelMessage::ChannelMessageContents::Tag::hint>();
234     }
235     ASSERT_EQ(target, config.vsyncPeriod.ns());
236     ASSERT_EQ(hint, SessionHint::CPU_LOAD_UP);
237 
238     setExpectedTiming(config.vsyncPeriod, startTime + config.vsyncPeriod);
239 
240     // report GPU
241     mPowerAdvisor->setRequiresRenderEngine(display1, config.frame1RequiresRenderEngine);
242     if (config.adpfGpuFlagOn) {
243         mPowerAdvisor->setGpuStartTime(display1, startTime);
244     }
245     if (config.frame1GpuFenceDuration.count() == Fence::SIGNAL_TIME_PENDING) {
246         mPowerAdvisor->setGpuFenceTime(display1,
247                                        std::make_unique<FenceTime>(Fence::SIGNAL_TIME_PENDING));
248     } else {
249         TimePoint end = startTime + config.frame1GpuFenceDuration;
250         mPowerAdvisor->setGpuFenceTime(display1, std::make_unique<FenceTime>(end.ns()));
251     }
252 
253     // increment the frame
254     std::this_thread::sleep_for(config.vsyncPeriod);
255     startTime = TimePoint::now();
256     fakeBasicFrameTiming(startTime, config.vsyncPeriod);
257     if (config.usesFmq && expectsFmqSuccess) {
258         // same target update will not trigger FMQ write
259         ASSERT_EQ(mBackendFmq->availableToRead(), 0uL);
260     }
261     setExpectedTiming(config.vsyncPeriod, startTime + config.vsyncPeriod);
262 
263     // report GPU
264     mPowerAdvisor->setRequiresRenderEngine(display1, config.frame2RequiresRenderEngine);
265     if (config.adpfGpuFlagOn) {
266         mPowerAdvisor->setGpuStartTime(display1, startTime);
267     }
268     if (config.frame2GpuFenceDuration.count() == Fence::SIGNAL_TIME_PENDING) {
269         mPowerAdvisor->setGpuFenceTime(display1,
270                                        std::make_unique<FenceTime>(Fence::SIGNAL_TIME_PENDING));
271     } else {
272         TimePoint end = startTime + config.frame2GpuFenceDuration;
273         mPowerAdvisor->setGpuFenceTime(display1, std::make_unique<FenceTime>(end.ns()));
274     }
275     mPowerAdvisor->setSfPresentTiming(startTime, startTime + config.presentDuration);
276     mPowerAdvisor->setCompositeEnd(startTime + config.presentDuration + config.postCompDuration);
277 
278     // don't report timing for the HWC
279     mPowerAdvisor->setHwcValidateTiming(displayIds[0], startTime, startTime);
280     mPowerAdvisor->setHwcPresentTiming(displayIds[0], startTime, startTime);
281 
282     if (config.usesFmq && expectsFmqSuccess) {
283         mPowerAdvisor->reportActualWorkDuration();
284         ASSERT_EQ(mBackendFmq->availableToRead(), 1uL);
285         std::vector<ChannelMessage> msgs;
286         msgs.resize(1);
287         ASSERT_TRUE(mBackendFmq->readBlocking(msgs.data(), 1, mReadFlagBitmask, mWriteFlagBitmask,
288                                               std::chrono::nanoseconds(1ms).count(), mEventFlag));
289         ASSERT_EQ(msgs[0].sessionID, mSessionId);
290         ASSERT_GE(msgs[0].timeStampNanos, startTime.ns());
291         ASSERT_EQ(msgs[0].data.getTag(), ChannelMessage::ChannelMessageContents::Tag::workDuration);
292         auto actual = msgs[0].data.get<ChannelMessage::ChannelMessageContents::Tag::workDuration>();
293         ret.workPeriodStartTimestampNanos = actual.workPeriodStartTimestampNanos;
294         ret.cpuDurationNanos = actual.cpuDurationNanos;
295         ret.gpuDurationNanos = actual.gpuDurationNanos;
296         ret.durationNanos = actual.durationNanos;
297     } else {
298         std::vector<aidl::android::hardware::power::WorkDuration> durationReq;
299         EXPECT_CALL(*mMockPowerHintSession, reportActualWorkDuration(_))
300                 .Times(1)
301                 .WillOnce(DoAll(testing::SaveArg<0>(&durationReq),
302                                 testing::Return(testing::ByMove(HalResult<void>::ok()))));
303         mPowerAdvisor->reportActualWorkDuration();
304         ASSERT_EQ(durationReq.size(), 1u);
305         ret = std::move(durationReq[0]);
306     }
307 }
308 
getFenceWaitDelayDuration(bool skipValidate)309 Duration PowerAdvisorTest::getFenceWaitDelayDuration(bool skipValidate) {
310     return (skipValidate ? PowerAdvisor::kFenceWaitStartDelaySkippedValidate
311                          : PowerAdvisor::kFenceWaitStartDelayValidated);
312 }
313 
getErrorMargin()314 Duration PowerAdvisorTest::getErrorMargin() {
315     return mPowerAdvisor->sTargetSafetyMargin;
316 }
317 
318 namespace {
319 
TEST_F(PowerAdvisorTest,hintSessionUseHwcDisplay)320 TEST_F(PowerAdvisorTest, hintSessionUseHwcDisplay) {
321     mPowerAdvisor->onBootFinished();
322     startPowerHintSession();
323 
324     std::vector<DisplayId> displayIds{PhysicalDisplayId::fromPort(42u)};
325 
326     // 60hz
327     const Duration vsyncPeriod{std::chrono::nanoseconds(1s) / 60};
328     const Duration presentDuration = 5ms;
329     const Duration postCompDuration = 1ms;
330 
331     TimePoint startTime{100ns};
332 
333     // advisor only starts on frame 2 so do an initial no-op frame
334     fakeBasicFrameTiming(startTime, vsyncPeriod);
335     setExpectedTiming(vsyncPeriod, startTime + vsyncPeriod);
336     mPowerAdvisor->setDisplays(displayIds);
337     mPowerAdvisor->setSfPresentTiming(startTime, startTime + presentDuration);
338     mPowerAdvisor->setCompositeEnd(startTime + presentDuration + postCompDuration);
339 
340     // increment the frame
341     startTime += vsyncPeriod;
342 
343     const Duration expectedDuration = getErrorMargin() + presentDuration + postCompDuration;
344     EXPECT_CALL(*mMockPowerHintSession,
345                 reportActualWorkDuration(ElementsAre(
346                         Field(&WorkDuration::durationNanos, Eq(expectedDuration.ns())))))
347             .Times(1)
348             .WillOnce(Return(testing::ByMove(HalResult<void>::ok())));
349     fakeBasicFrameTiming(startTime, vsyncPeriod);
350     setExpectedTiming(vsyncPeriod, startTime + vsyncPeriod);
351     mPowerAdvisor->setDisplays(displayIds);
352     mPowerAdvisor->setHwcValidateTiming(displayIds[0], startTime + 1ms, startTime + 1500us);
353     mPowerAdvisor->setHwcPresentTiming(displayIds[0], startTime + 2ms, startTime + 2500us);
354     mPowerAdvisor->setSfPresentTiming(startTime, startTime + presentDuration);
355     mPowerAdvisor->reportActualWorkDuration();
356 }
357 
TEST_F(PowerAdvisorTest,hintSessionSubtractsHwcFenceTime)358 TEST_F(PowerAdvisorTest, hintSessionSubtractsHwcFenceTime) {
359     mPowerAdvisor->onBootFinished();
360     startPowerHintSession();
361 
362     std::vector<DisplayId> displayIds{PhysicalDisplayId::fromPort(42u)};
363 
364     // 60hz
365     const Duration vsyncPeriod{std::chrono::nanoseconds(1s) / 60};
366     const Duration presentDuration = 5ms;
367     const Duration postCompDuration = 1ms;
368     const Duration hwcBlockedDuration = 500us;
369 
370     TimePoint startTime{100ns};
371 
372     // advisor only starts on frame 2 so do an initial no-op frame
373     fakeBasicFrameTiming(startTime, vsyncPeriod);
374     setExpectedTiming(vsyncPeriod, startTime + vsyncPeriod);
375     mPowerAdvisor->setDisplays(displayIds);
376     mPowerAdvisor->setSfPresentTiming(startTime, startTime + presentDuration);
377     mPowerAdvisor->setCompositeEnd(startTime + presentDuration + postCompDuration);
378 
379     // increment the frame
380     startTime += vsyncPeriod;
381 
382     const Duration expectedDuration = getErrorMargin() + presentDuration +
383             getFenceWaitDelayDuration(false) - hwcBlockedDuration + postCompDuration;
384     EXPECT_CALL(*mMockPowerHintSession,
385                 reportActualWorkDuration(ElementsAre(
386                         Field(&WorkDuration::durationNanos, Eq(expectedDuration.ns())))))
387             .Times(1)
388             .WillOnce(Return(testing::ByMove(HalResult<void>::ok())));
389 
390     fakeBasicFrameTiming(startTime, vsyncPeriod);
391     setExpectedTiming(vsyncPeriod, startTime + vsyncPeriod);
392     mPowerAdvisor->setDisplays(displayIds);
393     mPowerAdvisor->setHwcValidateTiming(displayIds[0], startTime + 1ms, startTime + 1500us);
394     mPowerAdvisor->setHwcPresentTiming(displayIds[0], startTime + 2ms, startTime + 3ms);
395     // now report the fence as having fired during the display HWC time
396     mPowerAdvisor->setSfPresentTiming(startTime + 2ms + hwcBlockedDuration,
397                                       startTime + presentDuration);
398     mPowerAdvisor->reportActualWorkDuration();
399 }
400 
TEST_F(PowerAdvisorTest,hintSessionUsingSecondaryVirtualDisplays)401 TEST_F(PowerAdvisorTest, hintSessionUsingSecondaryVirtualDisplays) {
402     mPowerAdvisor->onBootFinished();
403     startPowerHintSession();
404 
405     std::vector<DisplayId> displayIds{PhysicalDisplayId::fromPort(42u), GpuVirtualDisplayId(0),
406                                       GpuVirtualDisplayId(1)};
407 
408     // 60hz
409     const Duration vsyncPeriod{std::chrono::nanoseconds(1s) / 60};
410     // make present duration much later than the hwc display by itself will account for
411     const Duration presentDuration{10ms};
412     const Duration postCompDuration{1ms};
413 
414     TimePoint startTime{100ns};
415 
416     // advisor only starts on frame 2 so do an initial no-op frame
417     fakeBasicFrameTiming(startTime, vsyncPeriod);
418     setExpectedTiming(vsyncPeriod, startTime + vsyncPeriod);
419     mPowerAdvisor->setDisplays(displayIds);
420     mPowerAdvisor->setSfPresentTiming(startTime, startTime + presentDuration);
421     mPowerAdvisor->setCompositeEnd(startTime + presentDuration + postCompDuration);
422 
423     // increment the frame
424     startTime += vsyncPeriod;
425 
426     const Duration expectedDuration = getErrorMargin() + presentDuration + postCompDuration;
427     EXPECT_CALL(*mMockPowerHintSession,
428                 reportActualWorkDuration(ElementsAre(
429                         Field(&WorkDuration::durationNanos, Eq(expectedDuration.ns())))))
430             .Times(1)
431             .WillOnce(Return(testing::ByMove(HalResult<void>::ok())));
432 
433     fakeBasicFrameTiming(startTime, vsyncPeriod);
434     setExpectedTiming(vsyncPeriod, startTime + vsyncPeriod);
435     mPowerAdvisor->setDisplays(displayIds);
436 
437     // don't report timing for the gpu displays since they don't use hwc
438     mPowerAdvisor->setHwcValidateTiming(displayIds[0], startTime + 1ms, startTime + 1500us);
439     mPowerAdvisor->setHwcPresentTiming(displayIds[0], startTime + 2ms, startTime + 2500us);
440     mPowerAdvisor->setSfPresentTiming(startTime, startTime + presentDuration);
441     mPowerAdvisor->reportActualWorkDuration();
442 }
443 
TEST_F(PowerAdvisorTest,hintSessionValidWhenNullFromPowerHAL)444 TEST_F(PowerAdvisorTest, hintSessionValidWhenNullFromPowerHAL) {
445     mPowerAdvisor->onBootFinished();
446 
447     startPowerHintSession(false);
448 
449     std::vector<DisplayId> displayIds{PhysicalDisplayId::fromPort(42u)};
450 
451     // 60hz
452     const Duration vsyncPeriod{std::chrono::nanoseconds(1s) / 60};
453     const Duration presentDuration = 5ms;
454     const Duration postCompDuration = 1ms;
455 
456     TimePoint startTime{100ns};
457 
458     // advisor only starts on frame 2 so do an initial no-op frame
459     fakeBasicFrameTiming(startTime, vsyncPeriod);
460     setExpectedTiming(vsyncPeriod, startTime + vsyncPeriod);
461     mPowerAdvisor->setDisplays(displayIds);
462     mPowerAdvisor->setSfPresentTiming(startTime, startTime + presentDuration);
463     mPowerAdvisor->setCompositeEnd(startTime + presentDuration + postCompDuration);
464 
465     // increment the frame
466     startTime += vsyncPeriod;
467 
468     const Duration expectedDuration = getErrorMargin() + presentDuration + postCompDuration;
469     EXPECT_CALL(*mMockPowerHintSession,
470                 reportActualWorkDuration(ElementsAre(
471                         Field(&WorkDuration::durationNanos, Eq(expectedDuration.ns())))))
472             .Times(0);
473     fakeBasicFrameTiming(startTime, vsyncPeriod);
474     setExpectedTiming(vsyncPeriod, startTime + vsyncPeriod);
475     mPowerAdvisor->setDisplays(displayIds);
476     mPowerAdvisor->setHwcValidateTiming(displayIds[0], startTime + 1ms, startTime + 1500us);
477     mPowerAdvisor->setHwcPresentTiming(displayIds[0], startTime + 2ms, startTime + 2500us);
478     mPowerAdvisor->setSfPresentTiming(startTime, startTime + presentDuration);
479     mPowerAdvisor->reportActualWorkDuration();
480 }
481 
TEST_F(PowerAdvisorTest,hintSessionTestNotifyReportRace)482 TEST_F(PowerAdvisorTest, hintSessionTestNotifyReportRace) {
483     // notifyDisplayUpdateImminentAndCpuReset or notifyCpuLoadUp gets called in background
484     // reportActual gets called during callback and sees true session, passes ensure
485     // first notify finishes, setting value to true. Another async method gets called, acquires the
486     // lock between reportactual finishing ensure and acquiring the lock itself, and sets session to
487     // nullptr. reportActual acquires the lock, and the session is now null, so it does nullptr
488     // deref
489 
490     mPowerAdvisor->onBootFinished();
491     startPowerHintSession();
492 
493     // --- fake a bunch of timing data
494     std::vector<DisplayId> displayIds{PhysicalDisplayId::fromPort(42u)};
495     // 60hz
496     const Duration vsyncPeriod{std::chrono::nanoseconds(1s) / 60};
497     const Duration presentDuration = 5ms;
498     const Duration postCompDuration = 1ms;
499     TimePoint startTime{100ns};
500     // advisor only starts on frame 2 so do an initial no-op frame
501     fakeBasicFrameTiming(startTime, vsyncPeriod);
502     setExpectedTiming(vsyncPeriod, startTime + vsyncPeriod);
503     mPowerAdvisor->setDisplays(displayIds);
504     mPowerAdvisor->setSfPresentTiming(startTime, startTime + presentDuration);
505     mPowerAdvisor->setCompositeEnd(startTime + presentDuration + postCompDuration);
506     // increment the frame
507     startTime += vsyncPeriod;
508     fakeBasicFrameTiming(startTime, vsyncPeriod);
509     setExpectedTiming(vsyncPeriod, startTime + vsyncPeriod);
510     mPowerAdvisor->setDisplays(displayIds);
511     mPowerAdvisor->setHwcValidateTiming(displayIds[0], startTime + 1ms, startTime + 1500us);
512     mPowerAdvisor->setHwcPresentTiming(displayIds[0], startTime + 2ms, startTime + 2500us);
513     mPowerAdvisor->setSfPresentTiming(startTime, startTime + presentDuration);
514     // --- Done faking timing data
515 
516     setTimingTestingMode(true);
517     std::promise<bool> letSendHintFinish;
518 
519     ON_CALL(*mMockPowerHintSession, sendHint).WillByDefault([&letSendHintFinish] {
520         letSendHintFinish.get_future().wait();
521         return HalResult<void>::fromStatus(ndk::ScopedAStatus::fromExceptionCode(-127));
522     });
523 
524     ON_CALL(*mMockPowerHintSession, reportActualWorkDuration).WillByDefault([] {
525         return HalResult<void>::fromStatus(ndk::ScopedAStatus::fromExceptionCode(-127));
526     });
527 
528     ON_CALL(*mMockPowerHalController, createHintSessionWithConfig).WillByDefault([] {
529         return HalResult<std::shared_ptr<PowerHintSessionWrapper>>::
530                 fromStatus(ndk::ScopedAStatus::fromExceptionCode(-127), nullptr);
531     });
532 
533     // First background call, to notice the session is down
534     auto firstHint = std::async(std::launch::async, [this] {
535         mPowerAdvisor->notifyCpuLoadUp();
536         return true;
537     });
538     std::this_thread::sleep_for(10ms);
539 
540     // Call reportActual while callback is resolving to try and sneak past ensure
541     auto reportActual =
542             std::async(std::launch::async, [this] { mPowerAdvisor->reportActualWorkDuration(); });
543 
544     std::this_thread::sleep_for(10ms);
545     // Let the first call finish
546     letSendHintFinish.set_value(true);
547     letSendHintFinish = std::promise<bool>{};
548     firstHint.wait();
549 
550     // Do the second notify call, to ensure the session is nullptr
551     auto secondHint = std::async(std::launch::async, [this] {
552         mPowerAdvisor->notifyCpuLoadUp();
553         return true;
554     });
555     letSendHintFinish.set_value(true);
556     secondHint.wait();
557     // Let report finish, potentially dereferencing
558     allowReportActualToAcquireMutex();
559     reportActual.wait();
560     EXPECT_EQ(sessionExists(), false);
561 }
562 
TEST_F(PowerAdvisorTest,legacyHintSessionCreationStillWorks)563 TEST_F(PowerAdvisorTest, legacyHintSessionCreationStillWorks) {
564     mPowerAdvisor->onBootFinished();
565     mMockPowerHintSession = std::make_shared<NiceMock<MockPowerHintSessionWrapper>>();
566     EXPECT_CALL(*mMockPowerHalController, createHintSessionWithConfig)
567             .Times(1)
568             .WillOnce(Return(HalResult<std::shared_ptr<PowerHintSessionWrapper>>::
569                                      fromStatus(ndk::ScopedAStatus::fromExceptionCode(
570                                                         EX_UNSUPPORTED_OPERATION),
571                                                 nullptr)));
572 
573     EXPECT_CALL(*mMockPowerHalController, createHintSession)
574             .Times(1)
575             .WillOnce(Return(HalResult<std::shared_ptr<PowerHintSessionWrapper>>::
576                                      fromStatus(binder::Status::ok(), mMockPowerHintSession)));
577     mPowerAdvisor->enablePowerHintSession(true);
578     ASSERT_TRUE(mPowerAdvisor->startPowerHintSession({1, 2, 3}));
579 }
580 
TEST_F(PowerAdvisorTest,setGpuFenceTime_cpuThenGpuFrames)581 TEST_F(PowerAdvisorTest, setGpuFenceTime_cpuThenGpuFrames) {
582     GpuTestConfig config{
583             .adpfGpuFlagOn = false,
584             // faked buffer fence time for testing
585             .frame1GpuFenceDuration = 41ms,
586             .frame2GpuFenceDuration = 31ms,
587             .vsyncPeriod = 10ms,
588             .presentDuration = 2ms,
589             .postCompDuration = 8ms,
590             .frame1RequiresRenderEngine = false,
591             .frame2RequiresRenderEngine = true,
592     };
593     WorkDuration res;
594     testGpuScenario(config, res);
595     EXPECT_EQ(res.gpuDurationNanos, 0L);
596     EXPECT_EQ(res.cpuDurationNanos, 0L);
597     EXPECT_GE(res.durationNanos, toNanos(30ms + getErrorMargin()));
598     EXPECT_LE(res.durationNanos, toNanos(31ms + getErrorMargin()));
599 }
600 
TEST_F(PowerAdvisorTest,setGpuFenceTime_cpuThenGpuFrames_flagOn)601 TEST_F(PowerAdvisorTest, setGpuFenceTime_cpuThenGpuFrames_flagOn) {
602     GpuTestConfig config{
603             .adpfGpuFlagOn = true,
604             .frame1GpuFenceDuration = 40ms,
605             .frame2GpuFenceDuration = 30ms,
606             .vsyncPeriod = 10ms,
607             .presentDuration = 2ms,
608             .postCompDuration = 8ms,
609             .frame1RequiresRenderEngine = false,
610             .frame2RequiresRenderEngine = true,
611     };
612     WorkDuration res;
613     testGpuScenario(config, res);
614     EXPECT_EQ(res.gpuDurationNanos, toNanos(30ms));
615     EXPECT_EQ(res.cpuDurationNanos, toNanos(10ms));
616     EXPECT_EQ(res.durationNanos, toNanos(30ms + getErrorMargin()));
617 }
618 
TEST_F(PowerAdvisorTest,setGpuFenceTime_gpuThenCpuFrames)619 TEST_F(PowerAdvisorTest, setGpuFenceTime_gpuThenCpuFrames) {
620     GpuTestConfig config{
621             .adpfGpuFlagOn = false,
622             // faked fence time for testing
623             .frame1GpuFenceDuration = 41ms,
624             .frame2GpuFenceDuration = 31ms,
625             .vsyncPeriod = 10ms,
626             .presentDuration = 2ms,
627             .postCompDuration = 8ms,
628             .frame1RequiresRenderEngine = true,
629             .frame2RequiresRenderEngine = false,
630     };
631     WorkDuration res;
632     testGpuScenario(config, res);
633     EXPECT_EQ(res.gpuDurationNanos, 0L);
634     EXPECT_EQ(res.cpuDurationNanos, 0L);
635     EXPECT_EQ(res.durationNanos, toNanos(10ms + getErrorMargin()));
636 }
637 
TEST_F(PowerAdvisorTest,setGpuFenceTime_gpuThenCpuFrames_flagOn)638 TEST_F(PowerAdvisorTest, setGpuFenceTime_gpuThenCpuFrames_flagOn) {
639     GpuTestConfig config{
640             .adpfGpuFlagOn = true,
641             .frame1GpuFenceDuration = 40ms,
642             .frame2GpuFenceDuration = 30ms,
643             .vsyncPeriod = 10ms,
644             .presentDuration = 2ms,
645             .postCompDuration = 8ms,
646             .frame1RequiresRenderEngine = true,
647             .frame2RequiresRenderEngine = false,
648     };
649     WorkDuration res;
650     testGpuScenario(config, res);
651     EXPECT_EQ(res.gpuDurationNanos, 0L);
652     EXPECT_EQ(res.cpuDurationNanos, toNanos(10ms));
653     EXPECT_EQ(res.durationNanos, toNanos(10ms + getErrorMargin()));
654 }
655 
TEST_F(PowerAdvisorTest,setGpuFenceTime_twoSignaledGpuFrames)656 TEST_F(PowerAdvisorTest, setGpuFenceTime_twoSignaledGpuFrames) {
657     GpuTestConfig config{
658             .adpfGpuFlagOn = false,
659             // added a margin as a workaround since we set GPU start time at the time of fence set
660             // call
661             .frame1GpuFenceDuration = 31ms,
662             .frame2GpuFenceDuration = 51ms,
663             .vsyncPeriod = 10ms,
664             .presentDuration = 2ms,
665             .postCompDuration = 8ms,
666             .frame1RequiresRenderEngine = true,
667             .frame2RequiresRenderEngine = true,
668     };
669     WorkDuration res;
670     testGpuScenario(config, res);
671     EXPECT_EQ(res.gpuDurationNanos, 0L);
672     EXPECT_EQ(res.cpuDurationNanos, 0L);
673     EXPECT_GE(res.durationNanos, toNanos(50ms + getErrorMargin()));
674     EXPECT_LE(res.durationNanos, toNanos(51ms + getErrorMargin()));
675 }
676 
TEST_F(PowerAdvisorTest,setGpuFenceTime_twoSignaledGpuFenceFrames_flagOn)677 TEST_F(PowerAdvisorTest, setGpuFenceTime_twoSignaledGpuFenceFrames_flagOn) {
678     GpuTestConfig config{
679             .adpfGpuFlagOn = true,
680             .frame1GpuFenceDuration = 30ms,
681             .frame2GpuFenceDuration = 50ms,
682             .vsyncPeriod = 10ms,
683             .presentDuration = 2ms,
684             .postCompDuration = 8ms,
685             .frame1RequiresRenderEngine = true,
686             .frame2RequiresRenderEngine = true,
687     };
688     WorkDuration res;
689     testGpuScenario(config, res);
690     EXPECT_EQ(res.gpuDurationNanos, toNanos(50ms));
691     EXPECT_EQ(res.cpuDurationNanos, toNanos(10ms));
692     EXPECT_EQ(res.durationNanos, toNanos(50ms + getErrorMargin()));
693 }
694 
TEST_F(PowerAdvisorTest,setGpuFenceTime_UnsingaledGpuFenceFrameUsingPreviousFrame)695 TEST_F(PowerAdvisorTest, setGpuFenceTime_UnsingaledGpuFenceFrameUsingPreviousFrame) {
696     GpuTestConfig config{
697             .adpfGpuFlagOn = false,
698             .frame1GpuFenceDuration = 31ms,
699             .frame2GpuFenceDuration = Duration::fromNs(Fence::SIGNAL_TIME_PENDING),
700             .vsyncPeriod = 10ms,
701             .presentDuration = 2ms,
702             .postCompDuration = 8ms,
703             .frame1RequiresRenderEngine = true,
704             .frame2RequiresRenderEngine = true,
705     };
706     WorkDuration res;
707     testGpuScenario(config, res);
708     EXPECT_EQ(res.gpuDurationNanos, 0L);
709     EXPECT_EQ(res.cpuDurationNanos, 0L);
710     EXPECT_GE(res.durationNanos, toNanos(29ms + getErrorMargin()));
711     EXPECT_LE(res.durationNanos, toNanos(31ms + getErrorMargin()));
712 }
713 
TEST_F(PowerAdvisorTest,setGpuFenceTime_UnsingaledGpuFenceFrameUsingPreviousFrame_flagOn)714 TEST_F(PowerAdvisorTest, setGpuFenceTime_UnsingaledGpuFenceFrameUsingPreviousFrame_flagOn) {
715     GpuTestConfig config{
716             .adpfGpuFlagOn = true,
717             .frame1GpuFenceDuration = 30ms,
718             .frame2GpuFenceDuration = Duration::fromNs(Fence::SIGNAL_TIME_PENDING),
719             .vsyncPeriod = 10ms,
720             .presentDuration = 22ms,
721             .postCompDuration = 88ms,
722             .frame1RequiresRenderEngine = true,
723             .frame2RequiresRenderEngine = true,
724     };
725     WorkDuration res;
726     testGpuScenario(config, res);
727     EXPECT_EQ(res.gpuDurationNanos, toNanos(30ms));
728     EXPECT_EQ(res.cpuDurationNanos, toNanos(110ms));
729     EXPECT_EQ(res.durationNanos, toNanos(110ms + getErrorMargin()));
730 }
731 
TEST_F(PowerAdvisorTest,fmq_sendTargetAndActualDuration)732 TEST_F(PowerAdvisorTest, fmq_sendTargetAndActualDuration) {
733     GpuTestConfig config{
734             .adpfGpuFlagOn = true,
735             .frame1GpuFenceDuration = 30ms,
736             .frame2GpuFenceDuration = Duration::fromNs(Fence::SIGNAL_TIME_PENDING),
737             .vsyncPeriod = 10ms,
738             .presentDuration = 22ms,
739             .postCompDuration = 88ms,
740             .frame1RequiresRenderEngine = true,
741             .frame2RequiresRenderEngine = true,
742             .usesFmq = true,
743             .usesSharedFmqFlag = true,
744     };
745     WorkDuration res;
746     testGpuScenario(config, res);
747     EXPECT_EQ(res.gpuDurationNanos, toNanos(30ms));
748     EXPECT_EQ(res.cpuDurationNanos, toNanos(110ms));
749     EXPECT_EQ(res.durationNanos, toNanos(110ms + getErrorMargin()));
750 }
751 
TEST_F(PowerAdvisorTest,fmq_sendTargetAndActualDuration_noSharedFlag)752 TEST_F(PowerAdvisorTest, fmq_sendTargetAndActualDuration_noSharedFlag) {
753     GpuTestConfig config{
754             .adpfGpuFlagOn = true,
755             .frame1GpuFenceDuration = 30ms,
756             .frame2GpuFenceDuration = Duration::fromNs(Fence::SIGNAL_TIME_PENDING),
757             .vsyncPeriod = 10ms,
758             .presentDuration = 22ms,
759             .postCompDuration = 88ms,
760             .frame1RequiresRenderEngine = true,
761             .frame2RequiresRenderEngine = true,
762             .usesFmq = true,
763             .usesSharedFmqFlag = false,
764     };
765     WorkDuration res;
766     testGpuScenario(config, res);
767     EXPECT_EQ(res.gpuDurationNanos, toNanos(30ms));
768     EXPECT_EQ(res.cpuDurationNanos, toNanos(110ms));
769     EXPECT_EQ(res.durationNanos, toNanos(110ms + getErrorMargin()));
770 }
771 
TEST_F(PowerAdvisorTest,fmq_sendTargetAndActualDuration_queueFull)772 TEST_F(PowerAdvisorTest, fmq_sendTargetAndActualDuration_queueFull) {
773     GpuTestConfig config{.adpfGpuFlagOn = true,
774                          .frame1GpuFenceDuration = 30ms,
775                          .frame2GpuFenceDuration = Duration::fromNs(Fence::SIGNAL_TIME_PENDING),
776                          .vsyncPeriod = 10ms,
777                          .presentDuration = 22ms,
778                          .postCompDuration = 88ms,
779                          .frame1RequiresRenderEngine = true,
780                          .frame2RequiresRenderEngine = true,
781                          .usesFmq = true,
782                          .usesSharedFmqFlag = true,
783                          .fmqFull = true};
784     WorkDuration res;
785     testGpuScenario(config, res);
786     EXPECT_EQ(res.gpuDurationNanos, toNanos(30ms));
787     EXPECT_EQ(res.cpuDurationNanos, toNanos(110ms));
788     EXPECT_EQ(res.durationNanos, toNanos(110ms + getErrorMargin()));
789 }
790 
TEST_F(PowerAdvisorTest,fmq_sendHint)791 TEST_F(PowerAdvisorTest, fmq_sendHint) {
792     SET_FLAG_FOR_TEST(android::os::adpf_use_fmq_channel_fixed, true);
793     SET_FLAG_FOR_TEST(com::android::graphics::surfaceflinger::flags::adpf_fmq_sf, true);
794     mPowerAdvisor->onBootFinished();
795     SetUpFmq(true, false);
796     auto startTime = uptimeNanos();
797     mPowerAdvisor->notifyCpuLoadUp();
798     std::vector<ChannelMessage> msgs;
799     ASSERT_EQ(mBackendFmq->availableToRead(), 1uL);
800     msgs.resize(1);
801     ASSERT_TRUE(mBackendFmq->readBlocking(msgs.data(), 1, mReadFlagBitmask, mWriteFlagBitmask,
802                                           std::chrono::nanoseconds(1ms).count(), mEventFlag));
803     ASSERT_EQ(msgs[0].sessionID, mSessionId);
804     ASSERT_GE(msgs[0].timeStampNanos, startTime);
805     ASSERT_EQ(msgs[0].data.getTag(), ChannelMessage::ChannelMessageContents::Tag::hint);
806     auto hint = msgs[0].data.get<ChannelMessage::ChannelMessageContents::Tag::hint>();
807     ASSERT_EQ(hint, SessionHint::CPU_LOAD_UP);
808 }
809 
TEST_F(PowerAdvisorTest,fmq_sendHint_noSharedFlag)810 TEST_F(PowerAdvisorTest, fmq_sendHint_noSharedFlag) {
811     SET_FLAG_FOR_TEST(android::os::adpf_use_fmq_channel_fixed, true);
812     SET_FLAG_FOR_TEST(com::android::graphics::surfaceflinger::flags::adpf_fmq_sf, true);
813     mPowerAdvisor->onBootFinished();
814     SetUpFmq(false, false);
815     SessionHint hint;
816     EXPECT_CALL(*mMockPowerHintSession, sendHint(_))
817             .Times(1)
818             .WillOnce(DoAll(testing::SaveArg<0>(&hint),
819                             testing::Return(testing::ByMove(HalResult<void>::ok()))));
820     mPowerAdvisor->notifyCpuLoadUp();
821     ASSERT_EQ(mBackendFmq->availableToRead(), 0uL);
822     ASSERT_EQ(hint, SessionHint::CPU_LOAD_UP);
823 }
824 
TEST_F(PowerAdvisorTest,fmq_sendHint_queueFull)825 TEST_F(PowerAdvisorTest, fmq_sendHint_queueFull) {
826     SET_FLAG_FOR_TEST(android::os::adpf_use_fmq_channel_fixed, true);
827     SET_FLAG_FOR_TEST(com::android::graphics::surfaceflinger::flags::adpf_fmq_sf, true);
828     mPowerAdvisor->onBootFinished();
829     SetUpFmq(true, true);
830     ASSERT_EQ(mBackendFmq->availableToRead(), 2uL);
831     SessionHint hint;
832     EXPECT_CALL(*mMockPowerHintSession, sendHint(_))
833             .Times(1)
834             .WillOnce(DoAll(testing::SaveArg<0>(&hint),
835                             testing::Return(testing::ByMove(HalResult<void>::ok()))));
836     std::vector<ChannelMessage> msgs;
837     msgs.resize(1);
838     mBackendFmq->writeBlocking(msgs.data(), 1, mReadFlagBitmask, mWriteFlagBitmask,
839                                std::chrono::nanoseconds(1ms).count(), mEventFlag);
840     mPowerAdvisor->notifyCpuLoadUp();
841     ASSERT_EQ(mBackendFmq->availableToRead(), 2uL);
842     ASSERT_EQ(hint, SessionHint::CPU_LOAD_UP);
843 }
844 
845 } // namespace
846 } // namespace android::adpf::impl
847