• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2024 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 "LibSurfaceFlingerUnittests"
19 
20 #include "Display/DisplayModeController.h"
21 #include "Display/DisplaySnapshot.h"
22 #include "DisplayHardware/HWComposer.h"
23 #include "DisplayHardware/Hal.h"
24 #include "DisplayIdentificationTestHelpers.h"
25 #include "FpsOps.h"
26 #include "mock/DisplayHardware/MockComposer.h"
27 #include "mock/DisplayHardware/MockDisplayMode.h"
28 #include "mock/MockFrameRateMode.h"
29 
30 #include <ftl/fake_guard.h>
31 #include <gmock/gmock.h>
32 #include <gtest/gtest.h>
33 
34 #define EXPECT_DISPLAY_MODE_REQUEST(expected, requestOpt)                               \
35     ASSERT_TRUE(requestOpt);                                                            \
36     EXPECT_FRAME_RATE_MODE(expected.mode.modePtr, expected.mode.fps, requestOpt->mode); \
37     EXPECT_EQ(expected.emitEvent, requestOpt->emitEvent)
38 
39 namespace android::display {
40 namespace {
41 
42 namespace hal = android::hardware::graphics::composer::hal;
43 
44 using testing::_;
45 using testing::DoAll;
46 using testing::Return;
47 using testing::SetArgPointee;
48 
49 class DisplayModeControllerTest : public testing::Test {
50 public:
51     using Action = DisplayModeController::DesiredModeAction;
52 
SetUp()53     void SetUp() override {
54         mDmc.setHwComposer(mComposer.get());
55         mDmc.setActiveModeListener(
56                 [this](PhysicalDisplayId displayId, Fps vsyncRate, Fps renderFps) {
57                     mActiveModeListener.Call(displayId, vsyncRate, renderFps);
58                 });
59 
60         constexpr uint8_t kPort = 111;
61         EXPECT_CALL(*mComposerHal, getDisplayIdentificationData(kHwcDisplayId, _, _))
62                 .WillOnce(DoAll(SetArgPointee<1>(kPort), SetArgPointee<2>(getInternalEdid()),
63                                 Return(hal::Error::NONE)));
64 
65         EXPECT_CALL(*mComposerHal, setClientTargetSlotCount(kHwcDisplayId));
66         EXPECT_CALL(*mComposerHal,
67                     setVsyncEnabled(kHwcDisplayId, hal::IComposerClient::Vsync::DISABLE));
68         EXPECT_CALL(*mComposerHal, onHotplugConnect(kHwcDisplayId));
69 
70         const auto infoOpt =
71                 mComposer->onHotplug(kHwcDisplayId, HWComposer::HotplugEvent::Connected);
72         ASSERT_TRUE(infoOpt);
73 
74         mDisplayId = infoOpt->id;
75         mDisplaySnapshotOpt.emplace(mDisplayId, infoOpt->port, ui::DisplayConnectionType::Internal,
76                                     makeModes(kMode60, kMode90, kMode120), ui::ColorModes{},
77                                     std::nullopt);
78 
79         ftl::FakeGuard guard(kMainThreadContext);
80         mDmc.registerDisplay(*mDisplaySnapshotOpt, kModeId60,
81                              scheduler::RefreshRateSelector::Config{});
82     }
83 
84 protected:
expectModeSet(const DisplayModeRequest & request,hal::VsyncPeriodChangeTimeline & timeline,bool subsequent=false)85     hal::VsyncPeriodChangeConstraints expectModeSet(const DisplayModeRequest& request,
86                                                     hal::VsyncPeriodChangeTimeline& timeline,
87                                                     bool subsequent = false) {
88         EXPECT_CALL(*mComposerHal,
89                     isSupported(Hwc2::Composer::OptionalFeature::RefreshRateSwitching))
90                 .WillOnce(Return(true));
91 
92         if (!subsequent) {
93             EXPECT_CALL(*mComposerHal, getDisplayConnectionType(kHwcDisplayId, _))
94                     .WillOnce(DoAll(SetArgPointee<1>(
95                                             hal::IComposerClient::DisplayConnectionType::INTERNAL),
96                                     Return(hal::V2_4::Error::NONE)));
97         }
98 
99         const hal::VsyncPeriodChangeConstraints constraints{
100                 .desiredTimeNanos = systemTime(),
101                 .seamlessRequired = false,
102         };
103 
104         const hal::HWConfigId hwcModeId = request.mode.modePtr->getHwcId();
105 
106         EXPECT_CALL(*mComposerHal,
107                     setActiveConfigWithConstraints(kHwcDisplayId, hwcModeId, constraints, _))
108                 .WillOnce(DoAll(SetArgPointee<3>(timeline), Return(hal::Error::NONE)));
109 
110         return constraints;
111     }
112 
113     static constexpr hal::HWDisplayId kHwcDisplayId = 1234;
114 
115     Hwc2::mock::Composer* mComposerHal = new testing::StrictMock<Hwc2::mock::Composer>();
116     const std::unique_ptr<HWComposer> mComposer{
117             std::make_unique<impl::HWComposer>(std::unique_ptr<Hwc2::Composer>(mComposerHal))};
118 
119     testing::MockFunction<void(PhysicalDisplayId, Fps, Fps)> mActiveModeListener;
120 
121     DisplayModeController mDmc;
122 
123     PhysicalDisplayId mDisplayId;
124     std::optional<DisplaySnapshot> mDisplaySnapshotOpt;
125 
126     static constexpr DisplayModeId kModeId60{0};
127     static constexpr DisplayModeId kModeId90{1};
128     static constexpr DisplayModeId kModeId120{2};
129 
130     static inline const ftl::NonNull<DisplayModePtr> kMode60 =
131             ftl::as_non_null(mock::createDisplayMode(kModeId60, 60_Hz));
132     static inline const ftl::NonNull<DisplayModePtr> kMode90 =
133             ftl::as_non_null(mock::createDisplayMode(kModeId90, 90_Hz));
134     static inline const ftl::NonNull<DisplayModePtr> kMode120 =
135             ftl::as_non_null(mock::createDisplayMode(kModeId120, 120_Hz));
136 
137     static inline const DisplayModeRequest kDesiredMode30{{30_Hz, kMode60}, .emitEvent = false};
138     static inline const DisplayModeRequest kDesiredMode60{{60_Hz, kMode60}, .emitEvent = true};
139     static inline const DisplayModeRequest kDesiredMode90{{90_Hz, kMode90}, .emitEvent = false};
140     static inline const DisplayModeRequest kDesiredMode120{{120_Hz, kMode120}, .emitEvent = true};
141 };
142 
TEST_F(DisplayModeControllerTest,setDesiredModeToActiveMode)143 TEST_F(DisplayModeControllerTest, setDesiredModeToActiveMode) {
144     EXPECT_CALL(mActiveModeListener, Call(_, _, _)).Times(0);
145 
146     EXPECT_EQ(Action::None, mDmc.setDesiredMode(mDisplayId, DisplayModeRequest(kDesiredMode60)));
147     EXPECT_FALSE(mDmc.getDesiredMode(mDisplayId));
148 }
149 
TEST_F(DisplayModeControllerTest,setDesiredMode)150 TEST_F(DisplayModeControllerTest, setDesiredMode) {
151     // Called because setDesiredMode resets the render rate to the active refresh rate.
152     EXPECT_CALL(mActiveModeListener, Call(mDisplayId, 60_Hz, 60_Hz)).Times(1);
153 
154     EXPECT_EQ(Action::InitiateDisplayModeSwitch,
155               mDmc.setDesiredMode(mDisplayId, DisplayModeRequest(kDesiredMode90)));
156     EXPECT_DISPLAY_MODE_REQUEST(kDesiredMode90, mDmc.getDesiredMode(mDisplayId));
157 
158     // No action since a mode switch has already been initiated.
159     EXPECT_EQ(Action::None, mDmc.setDesiredMode(mDisplayId, DisplayModeRequest(kDesiredMode120)));
160     EXPECT_DISPLAY_MODE_REQUEST(kDesiredMode120, mDmc.getDesiredMode(mDisplayId));
161 }
162 
TEST_F(DisplayModeControllerTest,clearDesiredMode)163 TEST_F(DisplayModeControllerTest, clearDesiredMode) {
164     // Called because setDesiredMode resets the render rate to the active refresh rate.
165     EXPECT_CALL(mActiveModeListener, Call(mDisplayId, 60_Hz, 60_Hz)).Times(1);
166 
167     EXPECT_EQ(Action::InitiateDisplayModeSwitch,
168               mDmc.setDesiredMode(mDisplayId, DisplayModeRequest(kDesiredMode90)));
169     EXPECT_TRUE(mDmc.getDesiredMode(mDisplayId));
170 
171     mDmc.clearDesiredMode(mDisplayId);
172     EXPECT_FALSE(mDmc.getDesiredMode(mDisplayId));
173 }
174 
TEST_F(DisplayModeControllerTest,initiateModeChange)175 TEST_F(DisplayModeControllerTest, initiateModeChange) REQUIRES(kMainThreadContext) {
176     // Called because setDesiredMode resets the render rate to the active refresh rate.
177     EXPECT_CALL(mActiveModeListener, Call(mDisplayId, 60_Hz, 60_Hz)).Times(1);
178 
179     EXPECT_EQ(Action::InitiateDisplayModeSwitch,
180               mDmc.setDesiredMode(mDisplayId, DisplayModeRequest(kDesiredMode90)));
181 
182     EXPECT_DISPLAY_MODE_REQUEST(kDesiredMode90, mDmc.getDesiredMode(mDisplayId));
183     auto modeRequest = kDesiredMode90;
184 
185     hal::VsyncPeriodChangeTimeline timeline;
186     const auto constraints = expectModeSet(modeRequest, timeline);
187 
188     EXPECT_EQ(DisplayModeController::ModeChangeResult::Changed,
189               mDmc.initiateModeChange(mDisplayId, std::move(modeRequest), constraints, timeline));
190     EXPECT_DISPLAY_MODE_REQUEST(kDesiredMode90, mDmc.getPendingMode(mDisplayId));
191 
192     mDmc.clearDesiredMode(mDisplayId);
193     EXPECT_FALSE(mDmc.getDesiredMode(mDisplayId));
194 }
195 
TEST_F(DisplayModeControllerTest,initiateRenderRateSwitch)196 TEST_F(DisplayModeControllerTest, initiateRenderRateSwitch) {
197     EXPECT_CALL(mActiveModeListener, Call(mDisplayId, 60_Hz, 30_Hz)).Times(1);
198 
199     EXPECT_EQ(Action::InitiateRenderRateSwitch,
200               mDmc.setDesiredMode(mDisplayId, DisplayModeRequest(kDesiredMode30)));
201     EXPECT_FALSE(mDmc.getDesiredMode(mDisplayId));
202 }
203 
TEST_F(DisplayModeControllerTest,initiateDisplayModeSwitch)204 TEST_F(DisplayModeControllerTest, initiateDisplayModeSwitch) FTL_FAKE_GUARD(kMainThreadContext) {
205     // Called because setDesiredMode resets the render rate to the active refresh rate.
206     EXPECT_CALL(mActiveModeListener, Call(mDisplayId, 60_Hz, 60_Hz)).Times(1);
207 
208     EXPECT_EQ(Action::InitiateDisplayModeSwitch,
209               mDmc.setDesiredMode(mDisplayId, DisplayModeRequest(kDesiredMode90)));
210     EXPECT_DISPLAY_MODE_REQUEST(kDesiredMode90, mDmc.getDesiredMode(mDisplayId));
211     auto modeRequest = kDesiredMode90;
212 
213     hal::VsyncPeriodChangeTimeline timeline;
214     auto constraints = expectModeSet(modeRequest, timeline);
215 
216     EXPECT_EQ(DisplayModeController::ModeChangeResult::Changed,
217               mDmc.initiateModeChange(mDisplayId, std::move(modeRequest), constraints, timeline));
218     EXPECT_DISPLAY_MODE_REQUEST(kDesiredMode90, mDmc.getPendingMode(mDisplayId));
219 
220     // No action since a mode switch has already been initiated.
221     EXPECT_EQ(Action::None, mDmc.setDesiredMode(mDisplayId, DisplayModeRequest(kDesiredMode120)));
222 
223     EXPECT_DISPLAY_MODE_REQUEST(kDesiredMode90, mDmc.getPendingMode(mDisplayId));
224     EXPECT_DISPLAY_MODE_REQUEST(kDesiredMode120, mDmc.getDesiredMode(mDisplayId));
225     modeRequest = kDesiredMode120;
226 
227     constexpr bool kSubsequent = true;
228     constraints = expectModeSet(modeRequest, timeline, kSubsequent);
229 
230     EXPECT_EQ(DisplayModeController::ModeChangeResult::Changed,
231               mDmc.initiateModeChange(mDisplayId, std::move(modeRequest), constraints, timeline));
232     EXPECT_DISPLAY_MODE_REQUEST(kDesiredMode120, mDmc.getPendingMode(mDisplayId));
233 
234     mDmc.clearDesiredMode(mDisplayId);
235     EXPECT_FALSE(mDmc.getDesiredMode(mDisplayId));
236 }
237 
238 } // namespace
239 } // namespace android::display
240