• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <DisplayHardware/PowerAdvisor.h>
21 #include <compositionengine/Display.h>
22 #include <ftl/fake_guard.h>
23 #include <gmock/gmock.h>
24 #include <gtest/gtest.h>
25 #include <ui/DisplayId.h>
26 #include <chrono>
27 #include "TestableSurfaceFlinger.h"
28 #include "mock/DisplayHardware/MockIPowerHintSession.h"
29 #include "mock/DisplayHardware/MockPowerHalController.h"
30 
31 using namespace android;
32 using namespace android::Hwc2::mock;
33 using namespace android::hardware::power;
34 using namespace std::chrono_literals;
35 using namespace testing;
36 using namespace android::power;
37 
38 namespace android::Hwc2::impl {
39 
40 class PowerAdvisorTest : public testing::Test {
41 public:
42     void SetUp() override;
43     void startPowerHintSession();
44     void fakeBasicFrameTiming(TimePoint startTime, Duration vsyncPeriod);
45     void setExpectedTiming(Duration totalFrameTargetDuration, TimePoint expectedPresentTime);
46     Duration getFenceWaitDelayDuration(bool skipValidate);
47     Duration getErrorMargin();
48 
49 protected:
50     TestableSurfaceFlinger mFlinger;
51     std::unique_ptr<PowerAdvisor> mPowerAdvisor;
52     MockPowerHalController* mMockPowerHalController;
53     sp<MockIPowerHintSession> mMockPowerHintSession;
54 };
55 
SetUp()56 void PowerAdvisorTest::SetUp() {
57     mPowerAdvisor = std::make_unique<impl::PowerAdvisor>(*mFlinger.flinger());
58     mPowerAdvisor->mPowerHal = std::make_unique<NiceMock<MockPowerHalController>>();
59     mMockPowerHalController =
60             reinterpret_cast<MockPowerHalController*>(mPowerAdvisor->mPowerHal.get());
61     ON_CALL(*mMockPowerHalController, getHintSessionPreferredRate)
62             .WillByDefault(Return(HalResult<int64_t>::fromStatus(binder::Status::ok(), 16000)));
63 }
64 
startPowerHintSession()65 void PowerAdvisorTest::startPowerHintSession() {
66     const std::vector<int32_t> threadIds = {1, 2, 3};
67     mMockPowerHintSession = android::sp<NiceMock<MockIPowerHintSession>>::make();
68     ON_CALL(*mMockPowerHalController, createHintSession)
69             .WillByDefault(
70                     Return(HalResult<sp<IPowerHintSession>>::fromStatus(binder::Status::ok(),
71                                                                         mMockPowerHintSession)));
72     mPowerAdvisor->enablePowerHintSession(true);
73     mPowerAdvisor->startPowerHintSession(threadIds);
74 }
75 
setExpectedTiming(Duration totalFrameTargetDuration,TimePoint expectedPresentTime)76 void PowerAdvisorTest::setExpectedTiming(Duration totalFrameTargetDuration,
77                                          TimePoint expectedPresentTime) {
78     mPowerAdvisor->setTotalFrameTargetWorkDuration(totalFrameTargetDuration);
79     mPowerAdvisor->setExpectedPresentTime(expectedPresentTime);
80 }
81 
fakeBasicFrameTiming(TimePoint startTime,Duration vsyncPeriod)82 void PowerAdvisorTest::fakeBasicFrameTiming(TimePoint startTime, Duration vsyncPeriod) {
83     mPowerAdvisor->setCommitStart(startTime);
84     mPowerAdvisor->setFrameDelay(0ns);
85     mPowerAdvisor->updateTargetWorkDuration(vsyncPeriod);
86 }
87 
getFenceWaitDelayDuration(bool skipValidate)88 Duration PowerAdvisorTest::getFenceWaitDelayDuration(bool skipValidate) {
89     return (skipValidate ? PowerAdvisor::kFenceWaitStartDelaySkippedValidate
90                          : PowerAdvisor::kFenceWaitStartDelayValidated);
91 }
92 
getErrorMargin()93 Duration PowerAdvisorTest::getErrorMargin() {
94     return mPowerAdvisor->sTargetSafetyMargin;
95 }
96 
97 namespace {
98 
TEST_F(PowerAdvisorTest,hintSessionUseHwcDisplay)99 TEST_F(PowerAdvisorTest, hintSessionUseHwcDisplay) {
100     mPowerAdvisor->onBootFinished();
101     startPowerHintSession();
102 
103     std::vector<DisplayId> displayIds{PhysicalDisplayId::fromPort(42u)};
104 
105     // 60hz
106     const Duration vsyncPeriod{std::chrono::nanoseconds(1s) / 60};
107     const Duration presentDuration = 5ms;
108     const Duration postCompDuration = 1ms;
109 
110     TimePoint startTime{100ns};
111 
112     // advisor only starts on frame 2 so do an initial no-op frame
113     fakeBasicFrameTiming(startTime, vsyncPeriod);
114     setExpectedTiming(vsyncPeriod, startTime + vsyncPeriod);
115     mPowerAdvisor->setDisplays(displayIds);
116     mPowerAdvisor->setSfPresentTiming(startTime, startTime + presentDuration);
117     mPowerAdvisor->setCompositeEnd(startTime + presentDuration + postCompDuration);
118 
119     // increment the frame
120     startTime += vsyncPeriod;
121 
122     const Duration expectedDuration = getErrorMargin() + presentDuration + postCompDuration;
123     EXPECT_CALL(*mMockPowerHintSession,
124                 reportActualWorkDuration(ElementsAre(
125                         Field(&WorkDuration::durationNanos, Eq(expectedDuration.ns())))))
126             .Times(1);
127 
128     fakeBasicFrameTiming(startTime, vsyncPeriod);
129     setExpectedTiming(vsyncPeriod, startTime + vsyncPeriod);
130     mPowerAdvisor->setDisplays(displayIds);
131     mPowerAdvisor->setHwcValidateTiming(displayIds[0], startTime + 1ms, startTime + 1500us);
132     mPowerAdvisor->setHwcPresentTiming(displayIds[0], startTime + 2ms, startTime + 2500us);
133     mPowerAdvisor->setSfPresentTiming(startTime, startTime + presentDuration);
134     mPowerAdvisor->reportActualWorkDuration();
135 }
136 
TEST_F(PowerAdvisorTest,hintSessionSubtractsHwcFenceTime)137 TEST_F(PowerAdvisorTest, hintSessionSubtractsHwcFenceTime) {
138     mPowerAdvisor->onBootFinished();
139     startPowerHintSession();
140 
141     std::vector<DisplayId> displayIds{PhysicalDisplayId::fromPort(42u)};
142 
143     // 60hz
144     const Duration vsyncPeriod{std::chrono::nanoseconds(1s) / 60};
145     const Duration presentDuration = 5ms;
146     const Duration postCompDuration = 1ms;
147     const Duration hwcBlockedDuration = 500us;
148 
149     TimePoint startTime{100ns};
150 
151     // advisor only starts on frame 2 so do an initial no-op frame
152     fakeBasicFrameTiming(startTime, vsyncPeriod);
153     setExpectedTiming(vsyncPeriod, startTime + vsyncPeriod);
154     mPowerAdvisor->setDisplays(displayIds);
155     mPowerAdvisor->setSfPresentTiming(startTime, startTime + presentDuration);
156     mPowerAdvisor->setCompositeEnd(startTime + presentDuration + postCompDuration);
157 
158     // increment the frame
159     startTime += vsyncPeriod;
160 
161     const Duration expectedDuration = getErrorMargin() + presentDuration +
162             getFenceWaitDelayDuration(false) - hwcBlockedDuration + postCompDuration;
163     EXPECT_CALL(*mMockPowerHintSession,
164                 reportActualWorkDuration(ElementsAre(
165                         Field(&WorkDuration::durationNanos, Eq(expectedDuration.ns())))))
166             .Times(1);
167 
168     fakeBasicFrameTiming(startTime, vsyncPeriod);
169     setExpectedTiming(vsyncPeriod, startTime + vsyncPeriod);
170     mPowerAdvisor->setDisplays(displayIds);
171     mPowerAdvisor->setHwcValidateTiming(displayIds[0], startTime + 1ms, startTime + 1500us);
172     mPowerAdvisor->setHwcPresentTiming(displayIds[0], startTime + 2ms, startTime + 3ms);
173     // now report the fence as having fired during the display HWC time
174     mPowerAdvisor->setSfPresentTiming(startTime + 2ms + hwcBlockedDuration,
175                                       startTime + presentDuration);
176     mPowerAdvisor->reportActualWorkDuration();
177 }
178 
TEST_F(PowerAdvisorTest,hintSessionUsingSecondaryVirtualDisplays)179 TEST_F(PowerAdvisorTest, hintSessionUsingSecondaryVirtualDisplays) {
180     mPowerAdvisor->onBootFinished();
181     startPowerHintSession();
182 
183     std::vector<DisplayId> displayIds{PhysicalDisplayId::fromPort(42u), GpuVirtualDisplayId(0),
184                                       GpuVirtualDisplayId(1)};
185 
186     // 60hz
187     const Duration vsyncPeriod{std::chrono::nanoseconds(1s) / 60};
188     // make present duration much later than the hwc display by itself will account for
189     const Duration presentDuration{10ms};
190     const Duration postCompDuration{1ms};
191 
192     TimePoint startTime{100ns};
193 
194     // advisor only starts on frame 2 so do an initial no-op frame
195     fakeBasicFrameTiming(startTime, vsyncPeriod);
196     setExpectedTiming(vsyncPeriod, startTime + vsyncPeriod);
197     mPowerAdvisor->setDisplays(displayIds);
198     mPowerAdvisor->setSfPresentTiming(startTime, startTime + presentDuration);
199     mPowerAdvisor->setCompositeEnd(startTime + presentDuration + postCompDuration);
200 
201     // increment the frame
202     startTime += vsyncPeriod;
203 
204     const Duration expectedDuration = getErrorMargin() + presentDuration + postCompDuration;
205     EXPECT_CALL(*mMockPowerHintSession,
206                 reportActualWorkDuration(ElementsAre(
207                         Field(&WorkDuration::durationNanos, Eq(expectedDuration.ns())))))
208             .Times(1);
209 
210     fakeBasicFrameTiming(startTime, vsyncPeriod);
211     setExpectedTiming(vsyncPeriod, startTime + vsyncPeriod);
212     mPowerAdvisor->setDisplays(displayIds);
213 
214     // don't report timing for the gpu displays since they don't use hwc
215     mPowerAdvisor->setHwcValidateTiming(displayIds[0], startTime + 1ms, startTime + 1500us);
216     mPowerAdvisor->setHwcPresentTiming(displayIds[0], startTime + 2ms, startTime + 2500us);
217     mPowerAdvisor->setSfPresentTiming(startTime, startTime + presentDuration);
218     mPowerAdvisor->reportActualWorkDuration();
219 }
220 
221 } // namespace
222 } // namespace android::Hwc2::impl
223