blob: ac09cbcea6316266a561fd03d2427ab60079c880 [file] [log] [blame]
Ady Abrahamb0dbdaa2020-01-06 16:19:42 -08001/*
2 * Copyright 2019 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
ramindani0491e642023-11-16 17:42:14 -080017#include <common/test/FlagUtils.h>
Leon Scroggins III67388622023-02-06 20:36:20 -050018#include <ftl/fake_guard.h>
Ana Krulec0c8cd522018-08-31 12:27:28 -070019#include <gmock/gmock.h>
20#include <gtest/gtest.h>
Ana Krulec0c8cd522018-08-31 12:27:28 -070021#include <log/log.h>
22
Ana Krulece588e312018-09-18 12:32:24 -070023#include <mutex>
24
Ana Krulec0c8cd522018-08-31 12:27:28 -070025#include "Scheduler/EventThread.h"
Dominik Laskowskid82e0f02022-10-26 15:23:04 -040026#include "Scheduler/RefreshRateSelector.h"
ramindani0491e642023-11-16 17:42:14 -080027#include "Scheduler/VSyncPredictor.h"
Ady Abraham20024aa2024-03-05 01:32:49 +000028#include "Scheduler/VSyncReactor.h"
Dominik Laskowski98041832019-08-01 18:35:59 -070029#include "TestableScheduler.h"
Dominik Laskowski983f2b52020-06-25 16:54:06 -070030#include "TestableSurfaceFlinger.h"
Dominik Laskowskib0054a22022-03-03 09:03:06 -080031#include "mock/DisplayHardware/MockDisplayMode.h"
Ana Krulec0c8cd522018-08-31 12:27:28 -070032#include "mock/MockEventThread.h"
Dominik Laskowski983f2b52020-06-25 16:54:06 -070033#include "mock/MockLayer.h"
Dominik Laskowski8b01cc02020-07-14 19:02:41 -070034#include "mock/MockSchedulerCallback.h"
Ana Krulec0c8cd522018-08-31 12:27:28 -070035
Ady Abraham822ecbd2023-07-07 16:16:09 -070036#include <FrontEnd/LayerHierarchy.h>
ramindani7b32b3a2024-07-02 10:17:47 -070037#include <scheduler/FrameTime.h>
Ady Abraham822ecbd2023-07-07 16:16:09 -070038
ramindani0491e642023-11-16 17:42:14 -080039#include <com_android_graphics_surfaceflinger_flags.h>
Ady Abraham822ecbd2023-07-07 16:16:09 -070040#include "FpsOps.h"
41
ramindani0491e642023-11-16 17:42:14 -080042using namespace com::android::graphics::surfaceflinger;
43
Dominik Laskowski068173d2021-08-11 17:22:59 -070044namespace android::scheduler {
45
Dominik Laskowskib0054a22022-03-03 09:03:06 -080046using android::mock::createDisplayMode;
ramindani0491e642023-11-16 17:42:14 -080047using android::mock::createVrrDisplayMode;
Dominik Laskowskib0054a22022-03-03 09:03:06 -080048
Ana Krulec0c8cd522018-08-31 12:27:28 -070049using testing::_;
50using testing::Return;
51
Dominik Laskowski8b01cc02020-07-14 19:02:41 -070052namespace {
Ana Krulec0c8cd522018-08-31 12:27:28 -070053
Dominik Laskowski068173d2021-08-11 17:22:59 -070054using MockEventThread = android::mock::EventThread;
55using MockLayer = android::mock::MockLayer;
56
Ady Abraham822ecbd2023-07-07 16:16:09 -070057using LayerHierarchy = surfaceflinger::frontend::LayerHierarchy;
58using LayerHierarchyBuilder = surfaceflinger::frontend::LayerHierarchyBuilder;
59using RequestedLayerState = surfaceflinger::frontend::RequestedLayerState;
60
Ady Abraham77b4fb12024-03-05 17:51:53 -080061class ZeroClock : public Clock {
62public:
63 nsecs_t now() const override { return 0; }
64};
65
Ana Krulec0c8cd522018-08-31 12:27:28 -070066class SchedulerTest : public testing::Test {
67protected:
Ana Krulec85c39af2018-12-26 17:29:57 -080068 class MockEventThreadConnection : public android::EventThreadConnection {
Ana Krulec0c8cd522018-08-31 12:27:28 -070069 public:
Ana Krulec85c39af2018-12-26 17:29:57 -080070 explicit MockEventThreadConnection(EventThread* eventThread)
Ady Abrahamf2851612023-09-25 17:19:00 -070071 : EventThreadConnection(eventThread, /*callingUid*/ static_cast<uid_t>(0)) {}
Ana Krulec0c8cd522018-08-31 12:27:28 -070072 ~MockEventThreadConnection() = default;
73
Huihong Luo6fac5232021-11-22 16:05:23 -080074 MOCK_METHOD1(stealReceiveChannel, binder::Status(gui::BitTube* outChannel));
75 MOCK_METHOD1(setVsyncRate, binder::Status(int count));
76 MOCK_METHOD0(requestNextVsync, binder::Status());
Ana Krulec0c8cd522018-08-31 12:27:28 -070077 };
78
Ana Krulec0c8cd522018-08-31 12:27:28 -070079 SchedulerTest();
Ana Krulec0c8cd522018-08-31 12:27:28 -070080
Dominik Laskowskiaa49af72024-08-12 17:29:34 -040081 static constexpr RefreshRateSelector::LayerRequirement kLayer = {.weight = 1.f};
82
Dominik Laskowski530d6bd2022-10-10 16:55:54 -040083 static constexpr PhysicalDisplayId kDisplayId1 = PhysicalDisplayId::fromPort(255u);
Ady Abrahamace3d052022-11-17 16:25:05 -080084 static inline const ftl::NonNull<DisplayModePtr> kDisplay1Mode60 =
85 ftl::as_non_null(createDisplayMode(kDisplayId1, DisplayModeId(0), 60_Hz));
86 static inline const ftl::NonNull<DisplayModePtr> kDisplay1Mode120 =
87 ftl::as_non_null(createDisplayMode(kDisplayId1, DisplayModeId(1), 120_Hz));
Dominik Laskowski530d6bd2022-10-10 16:55:54 -040088 static inline const DisplayModes kDisplay1Modes = makeModes(kDisplay1Mode60, kDisplay1Mode120);
89
Dominik Laskowskiaa49af72024-08-12 17:29:34 -040090 static inline FrameRateMode kDisplay1Mode60_60{60_Hz, kDisplay1Mode60};
91 static inline FrameRateMode kDisplay1Mode120_120{120_Hz, kDisplay1Mode120};
92
Dominik Laskowski530d6bd2022-10-10 16:55:54 -040093 static constexpr PhysicalDisplayId kDisplayId2 = PhysicalDisplayId::fromPort(254u);
Ady Abrahamace3d052022-11-17 16:25:05 -080094 static inline const ftl::NonNull<DisplayModePtr> kDisplay2Mode60 =
95 ftl::as_non_null(createDisplayMode(kDisplayId2, DisplayModeId(0), 60_Hz));
96 static inline const ftl::NonNull<DisplayModePtr> kDisplay2Mode120 =
97 ftl::as_non_null(createDisplayMode(kDisplayId2, DisplayModeId(1), 120_Hz));
Dominik Laskowski530d6bd2022-10-10 16:55:54 -040098 static inline const DisplayModes kDisplay2Modes = makeModes(kDisplay2Mode60, kDisplay2Mode120);
99
100 static constexpr PhysicalDisplayId kDisplayId3 = PhysicalDisplayId::fromPort(253u);
Ady Abrahamace3d052022-11-17 16:25:05 -0800101 static inline const ftl::NonNull<DisplayModePtr> kDisplay3Mode60 =
102 ftl::as_non_null(createDisplayMode(kDisplayId3, DisplayModeId(0), 60_Hz));
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400103 static inline const DisplayModes kDisplay3Modes = makeModes(kDisplay3Mode60);
Marin Shalamanov2cde1002021-06-08 19:50:10 +0200104
Dominik Laskowskid82e0f02022-10-26 15:23:04 -0400105 std::shared_ptr<RefreshRateSelector> mSelector =
106 std::make_shared<RefreshRateSelector>(makeModes(kDisplay1Mode60),
107 kDisplay1Mode60->getId());
Dominik Laskowski983f2b52020-06-25 16:54:06 -0700108
Dominik Laskowski8b01cc02020-07-14 19:02:41 -0700109 mock::SchedulerCallback mSchedulerCallback;
Leon Scroggins III823d4ca2023-12-12 16:57:34 -0500110 TestableSurfaceFlinger mFlinger;
ramindaniae645822024-01-11 10:57:29 -0800111 TestableScheduler* mScheduler = new TestableScheduler{mSelector, mFlinger, mSchedulerCallback};
Vishnu Naira0292282023-12-16 14:32:00 -0800112 surfaceflinger::frontend::LayerHierarchyBuilder mLayerHierarchyBuilder;
Dominik Laskowski98041832019-08-01 18:35:59 -0700113
Dominik Laskowski068173d2021-08-11 17:22:59 -0700114 MockEventThread* mEventThread;
Ana Krulec0c8cd522018-08-31 12:27:28 -0700115 sp<MockEventThreadConnection> mEventThreadConnection;
Ana Krulec0c8cd522018-08-31 12:27:28 -0700116};
117
118SchedulerTest::SchedulerTest() {
Dominik Laskowski068173d2021-08-11 17:22:59 -0700119 auto eventThread = std::make_unique<MockEventThread>();
Ana Krulec0c8cd522018-08-31 12:27:28 -0700120 mEventThread = eventThread.get();
Ana Krulec85c39af2018-12-26 17:29:57 -0800121 EXPECT_CALL(*mEventThread, registerDisplayEventConnection(_)).WillOnce(Return(0));
122
Ady Abrahamd11bade2022-08-01 16:18:03 -0700123 mEventThreadConnection = sp<MockEventThreadConnection>::make(mEventThread);
Ana Krulec0c8cd522018-08-31 12:27:28 -0700124
125 // createConnection call to scheduler makes a createEventConnection call to EventThread. Make
126 // sure that call gets executed and returns an EventThread::Connection object.
Lloyd Pique6f240172024-09-16 15:51:45 -0700127 EXPECT_CALL(*mEventThread, createEventConnection(_))
Ana Krulec0c8cd522018-08-31 12:27:28 -0700128 .WillRepeatedly(Return(mEventThreadConnection));
129
Dominik Laskowski4babfc42024-02-16 12:28:40 -0500130 mScheduler->setEventThread(Cycle::Render, std::move(eventThread));
Dominik Laskowskiaa49af72024-08-12 17:29:34 -0400131 mScheduler->setEventThread(Cycle::LastComposite, std::make_unique<MockEventThread>());
Ady Abrahama0a16272021-03-03 15:23:35 -0800132
133 mFlinger.resetScheduler(mScheduler);
Ana Krulec0c8cd522018-08-31 12:27:28 -0700134}
135
Dominik Laskowski8b01cc02020-07-14 19:02:41 -0700136} // namespace
Ana Krulec0c8cd522018-08-31 12:27:28 -0700137
Dominik Laskowski66295432023-03-14 12:25:36 -0400138TEST_F(SchedulerTest, registerDisplay) FTL_FAKE_GUARD(kMainThreadContext) {
Dominik Laskowski008bec02023-03-14 12:04:58 -0400139 // Hardware VSYNC should not change if the display is already registered.
Dominik Laskowski66295432023-03-14 12:25:36 -0400140 EXPECT_CALL(mSchedulerCallback, requestHardwareVsync(kDisplayId1, false)).Times(0);
Dominik Laskowski008bec02023-03-14 12:04:58 -0400141 mScheduler->registerDisplay(kDisplayId1,
142 std::make_shared<RefreshRateSelector>(kDisplay1Modes,
143 kDisplay1Mode60->getId()));
144
Dominik Laskowski66295432023-03-14 12:25:36 -0400145 // TODO(b/241285191): Restore once VsyncSchedule::getPendingHardwareVsyncState is called by
146 // Scheduler::setDisplayPowerMode rather than SF::setPowerModeInternal.
147#if 0
Dominik Laskowski008bec02023-03-14 12:04:58 -0400148 // Hardware VSYNC should be disabled for newly registered displays.
Dominik Laskowski66295432023-03-14 12:25:36 -0400149 EXPECT_CALL(mSchedulerCallback, requestHardwareVsync(kDisplayId2, false)).Times(1);
150 EXPECT_CALL(mSchedulerCallback, requestHardwareVsync(kDisplayId3, false)).Times(1);
151#endif
Dominik Laskowski008bec02023-03-14 12:04:58 -0400152
153 mScheduler->registerDisplay(kDisplayId2,
154 std::make_shared<RefreshRateSelector>(kDisplay2Modes,
155 kDisplay2Mode60->getId()));
156 mScheduler->registerDisplay(kDisplayId3,
157 std::make_shared<RefreshRateSelector>(kDisplay3Modes,
158 kDisplay3Mode60->getId()));
Dominik Laskowski66295432023-03-14 12:25:36 -0400159
160 EXPECT_FALSE(mScheduler->getVsyncSchedule(kDisplayId1)->getPendingHardwareVsyncState());
161 EXPECT_FALSE(mScheduler->getVsyncSchedule(kDisplayId2)->getPendingHardwareVsyncState());
162 EXPECT_FALSE(mScheduler->getVsyncSchedule(kDisplayId3)->getPendingHardwareVsyncState());
Dominik Laskowski008bec02023-03-14 12:04:58 -0400163}
164
Marin Shalamanov2cde1002021-06-08 19:50:10 +0200165TEST_F(SchedulerTest, chooseRefreshRateForContentIsNoopWhenModeSwitchingIsNotSupported) {
166 // The layer is registered at creation time and deregistered at destruction time.
Dominik Laskowski068173d2021-08-11 17:22:59 -0700167 sp<MockLayer> layer = sp<MockLayer>::make(mFlinger.flinger());
Dominik Laskowski983f2b52020-06-25 16:54:06 -0700168
Marin Shalamanov2cde1002021-06-08 19:50:10 +0200169 // recordLayerHistory should be a noop
Dominik Laskowski9c93d602021-10-07 19:38:26 -0700170 ASSERT_EQ(0u, mScheduler->getNumActiveLayers());
Vishnu Nair5c61a012024-08-05 21:14:39 -0700171 scheduler::LayerProps layerProps = {
172 .visible = true,
173 .bounds = {0, 0, 100, 100},
174 .transform = {},
175 .setFrameRateVote = {},
176 .frameRateSelectionPriority = Layer::PRIORITY_UNSET,
177 .isSmallDirty = false,
178 .isFrontBuffered = false,
179 };
180
181 mScheduler->recordLayerHistory(layer->getSequence(), layerProps, 0, 0,
Vishnu Nairef68d6d2023-02-28 06:18:27 +0000182 LayerHistory::LayerUpdateType::Buffer);
Dominik Laskowski9c93d602021-10-07 19:38:26 -0700183 ASSERT_EQ(0u, mScheduler->getNumActiveLayers());
Dominik Laskowski983f2b52020-06-25 16:54:06 -0700184
Rachel Lee6a9731d2022-06-06 17:08:14 -0700185 constexpr hal::PowerMode kPowerModeOn = hal::PowerMode::ON;
Leon Scroggins III67388622023-02-06 20:36:20 -0500186 FTL_FAKE_GUARD(kMainThreadContext, mScheduler->setDisplayPowerMode(kDisplayId1, kPowerModeOn));
Dominik Laskowski983f2b52020-06-25 16:54:06 -0700187
188 constexpr uint32_t kDisplayArea = 999'999;
Ady Abrahamed3290f2021-05-17 15:12:14 -0700189 mScheduler->onActiveDisplayAreaChanged(kDisplayArea);
Dominik Laskowski983f2b52020-06-25 16:54:06 -0700190
ramindani69b58e82022-09-26 16:48:36 -0700191 EXPECT_CALL(mSchedulerCallback, requestDisplayModes(_)).Times(0);
Ady Abraham822ecbd2023-07-07 16:16:09 -0700192 mScheduler->chooseRefreshRateForContent(/*LayerHierarchy*/ nullptr,
193 /*updateAttachedChoreographer*/ false);
Dominik Laskowski983f2b52020-06-25 16:54:06 -0700194}
195
Marin Shalamanov2cde1002021-06-08 19:50:10 +0200196TEST_F(SchedulerTest, updateDisplayModes) {
Dominik Laskowski9c93d602021-10-07 19:38:26 -0700197 ASSERT_EQ(0u, mScheduler->layerHistorySize());
Dominik Laskowski068173d2021-08-11 17:22:59 -0700198 sp<MockLayer> layer = sp<MockLayer>::make(mFlinger.flinger());
Dominik Laskowski9c93d602021-10-07 19:38:26 -0700199 ASSERT_EQ(1u, mScheduler->layerHistorySize());
Marin Shalamanov2cde1002021-06-08 19:50:10 +0200200
Dominik Laskowski596a2562022-10-28 11:26:12 -0400201 // Replace `mSelector` with a new `RefreshRateSelector` that has different display modes.
202 mScheduler->registerDisplay(kDisplayId1,
203 std::make_shared<RefreshRateSelector>(kDisplay1Modes,
204 kDisplay1Mode60->getId()));
Marin Shalamanov2cde1002021-06-08 19:50:10 +0200205
Dominik Laskowski9c93d602021-10-07 19:38:26 -0700206 ASSERT_EQ(0u, mScheduler->getNumActiveLayers());
Vishnu Nair5c61a012024-08-05 21:14:39 -0700207 scheduler::LayerProps layerProps = {
208 .visible = true,
209 .bounds = {0, 0, 100, 100},
210 .transform = {},
211 .setFrameRateVote = {},
212 .frameRateSelectionPriority = Layer::PRIORITY_UNSET,
213 .isSmallDirty = false,
214 .isFrontBuffered = false,
215 };
216 mScheduler->recordLayerHistory(layer->getSequence(), layerProps, 0, 0,
Vishnu Nairef68d6d2023-02-28 06:18:27 +0000217 LayerHistory::LayerUpdateType::Buffer);
Dominik Laskowski9c93d602021-10-07 19:38:26 -0700218 ASSERT_EQ(1u, mScheduler->getNumActiveLayers());
Marin Shalamanov2cde1002021-06-08 19:50:10 +0200219}
220
Dominik Laskowskiaa49af72024-08-12 17:29:34 -0400221TEST_F(SchedulerTest, emitModeChangeEvent) {
222 const auto selectorPtr =
223 std::make_shared<RefreshRateSelector>(kDisplay1Modes, kDisplay1Mode120->getId());
224 mScheduler->registerDisplay(kDisplayId1, selectorPtr);
Dominik Laskowskibda52362024-08-04 00:41:46 -0400225 mScheduler->onDisplayModeChanged(kDisplayId1, kDisplay1Mode120_120);
Dominik Laskowski068173d2021-08-11 17:22:59 -0700226
Dominik Laskowskiaa49af72024-08-12 17:29:34 -0400227 mScheduler->setContentRequirements({kLayer});
228
229 // No event is emitted in response to idle.
Ady Abraham690f4612021-07-01 23:24:03 -0700230 EXPECT_CALL(*mEventThread, onModeChanged(_)).Times(0);
Dominik Laskowskiaa49af72024-08-12 17:29:34 -0400231
232 using TimerState = TestableScheduler::TimerState;
233
234 mScheduler->idleTimerCallback(TimerState::Expired);
235 selectorPtr->setActiveMode(kDisplay1Mode60->getId(), 60_Hz);
236
237 auto layer = kLayer;
238 layer.vote = RefreshRateSelector::LayerVoteType::ExplicitExact;
239 layer.desiredRefreshRate = 60_Hz;
240 mScheduler->setContentRequirements({layer});
241
242 // An event is emitted implicitly despite choosing the same mode as when idle.
243 EXPECT_CALL(*mEventThread, onModeChanged(kDisplay1Mode60_60)).Times(1);
244
245 mScheduler->idleTimerCallback(TimerState::Reset);
246
247 mScheduler->setContentRequirements({kLayer});
248
249 // An event is emitted explicitly for the mode change.
250 EXPECT_CALL(*mEventThread, onModeChanged(kDisplay1Mode120_120)).Times(1);
251
252 mScheduler->touchTimerCallback(TimerState::Reset);
Dominik Laskowskibda52362024-08-04 00:41:46 -0400253 mScheduler->onDisplayModeChanged(kDisplayId1, kDisplay1Mode120_120);
Ana Krulec6ddd2612020-09-24 13:06:33 -0700254}
255
Ady Abraham899dcdb2021-06-15 16:56:21 -0700256TEST_F(SchedulerTest, calculateMaxAcquiredBufferCount) {
Dominik Laskowski6eab42d2021-09-13 14:34:13 -0700257 EXPECT_EQ(1, mFlinger.calculateMaxAcquiredBufferCount(60_Hz, 30ms));
258 EXPECT_EQ(2, mFlinger.calculateMaxAcquiredBufferCount(90_Hz, 30ms));
259 EXPECT_EQ(3, mFlinger.calculateMaxAcquiredBufferCount(120_Hz, 30ms));
Ady Abraham564f9de2021-02-03 18:34:33 -0800260
Dominik Laskowski6eab42d2021-09-13 14:34:13 -0700261 EXPECT_EQ(2, mFlinger.calculateMaxAcquiredBufferCount(60_Hz, 40ms));
Ady Abraham564f9de2021-02-03 18:34:33 -0800262
Dominik Laskowski6eab42d2021-09-13 14:34:13 -0700263 EXPECT_EQ(1, mFlinger.calculateMaxAcquiredBufferCount(60_Hz, 10ms));
Lloyd Piquea1456c12023-05-17 12:11:15 -0700264
Lloyd Pique30db6402023-06-26 18:56:51 +0000265 const auto savedMinAcquiredBuffers = mFlinger.mutableMinAcquiredBuffers();
266 mFlinger.mutableMinAcquiredBuffers() = 2;
Lloyd Piquea1456c12023-05-17 12:11:15 -0700267 EXPECT_EQ(2, mFlinger.calculateMaxAcquiredBufferCount(60_Hz, 10ms));
Lloyd Pique30db6402023-06-26 18:56:51 +0000268 mFlinger.mutableMinAcquiredBuffers() = savedMinAcquiredBuffers;
Ady Abraham564f9de2021-02-03 18:34:33 -0800269}
270
Marin Shalamanov4c7831e2021-06-08 20:44:06 +0200271MATCHER(Is120Hz, "") {
Ady Abrahamace3d052022-11-17 16:25:05 -0800272 return isApproxEqual(arg.front().mode.fps, 120_Hz);
Marin Shalamanov4c7831e2021-06-08 20:44:06 +0200273}
274
275TEST_F(SchedulerTest, chooseRefreshRateForContentSelectsMaxRefreshRate) {
Dominik Laskowski596a2562022-10-28 11:26:12 -0400276 mScheduler->registerDisplay(kDisplayId1,
277 std::make_shared<RefreshRateSelector>(kDisplay1Modes,
278 kDisplay1Mode60->getId()));
Marin Shalamanov4c7831e2021-06-08 20:44:06 +0200279
Dominik Laskowski0c41ffa2021-12-24 16:45:12 -0800280 const sp<MockLayer> layer = sp<MockLayer>::make(mFlinger.flinger());
Vishnu Nair5c61a012024-08-05 21:14:39 -0700281 scheduler::LayerProps layerProps = {
282 .visible = true,
283 .bounds = {0, 0, 0, 0},
284 .transform = {},
285 .setFrameRateVote = {},
286 .frameRateSelectionPriority = Layer::PRIORITY_UNSET,
287 .isSmallDirty = false,
288 .isFrontBuffered = false,
289 };
290 mScheduler->recordLayerHistory(layer->getSequence(), layerProps, 0, systemTime(),
Vishnu Nairef68d6d2023-02-28 06:18:27 +0000291 LayerHistory::LayerUpdateType::Buffer);
Marin Shalamanov4c7831e2021-06-08 20:44:06 +0200292
Rachel Lee6a9731d2022-06-06 17:08:14 -0700293 constexpr hal::PowerMode kPowerModeOn = hal::PowerMode::ON;
Leon Scroggins III67388622023-02-06 20:36:20 -0500294 FTL_FAKE_GUARD(kMainThreadContext, mScheduler->setDisplayPowerMode(kDisplayId1, kPowerModeOn));
Marin Shalamanov4c7831e2021-06-08 20:44:06 +0200295
296 constexpr uint32_t kDisplayArea = 999'999;
Ady Abrahamed3290f2021-05-17 15:12:14 -0700297 mScheduler->onActiveDisplayAreaChanged(kDisplayArea);
Marin Shalamanov4c7831e2021-06-08 20:44:06 +0200298
ramindani69b58e82022-09-26 16:48:36 -0700299 EXPECT_CALL(mSchedulerCallback, requestDisplayModes(Is120Hz())).Times(1);
Ady Abraham822ecbd2023-07-07 16:16:09 -0700300 mScheduler->chooseRefreshRateForContent(/*LayerHierarchy*/ nullptr,
301 /*updateAttachedChoreographer*/ false);
Dominik Laskowski0c41ffa2021-12-24 16:45:12 -0800302
303 // No-op if layer requirements have not changed.
ramindani69b58e82022-09-26 16:48:36 -0700304 EXPECT_CALL(mSchedulerCallback, requestDisplayModes(_)).Times(0);
Ady Abraham822ecbd2023-07-07 16:16:09 -0700305 mScheduler->chooseRefreshRateForContent(/*LayerHierarchy*/ nullptr,
306 /*updateAttachedChoreographer*/ false);
Marin Shalamanov4c7831e2021-06-08 20:44:06 +0200307}
308
Dominik Laskowskiaa49af72024-08-12 17:29:34 -0400309TEST_F(SchedulerTest, chooseDisplayModes) {
Dominik Laskowskib5a094b2022-10-27 12:00:12 -0400310 mScheduler->registerDisplay(kDisplayId1,
311 std::make_shared<RefreshRateSelector>(kDisplay1Modes,
312 kDisplay1Mode60->getId()));
ramindani69b58e82022-09-26 16:48:36 -0700313
Dominik Laskowskiaa49af72024-08-12 17:29:34 -0400314 mScheduler->setContentRequirements({kLayer, kLayer});
ramindani69b58e82022-09-26 16:48:36 -0700315 GlobalSignals globalSignals = {.idle = true};
316 mScheduler->setTouchStateAndIdleTimerPolicy(globalSignals);
317
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400318 using DisplayModeChoice = TestableScheduler::DisplayModeChoice;
319
320 auto modeChoices = mScheduler->chooseDisplayModes();
321 ASSERT_EQ(1u, modeChoices.size());
322
323 auto choice = modeChoices.get(kDisplayId1);
324 ASSERT_TRUE(choice);
Ady Abrahamace3d052022-11-17 16:25:05 -0800325 EXPECT_EQ(choice->get(), DisplayModeChoice({60_Hz, kDisplay1Mode60}, globalSignals));
ramindani69b58e82022-09-26 16:48:36 -0700326
327 globalSignals = {.idle = false};
328 mScheduler->setTouchStateAndIdleTimerPolicy(globalSignals);
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400329
330 modeChoices = mScheduler->chooseDisplayModes();
331 ASSERT_EQ(1u, modeChoices.size());
332
333 choice = modeChoices.get(kDisplayId1);
334 ASSERT_TRUE(choice);
Ady Abrahamace3d052022-11-17 16:25:05 -0800335 EXPECT_EQ(choice->get(), DisplayModeChoice({120_Hz, kDisplay1Mode120}, globalSignals));
ramindani69b58e82022-09-26 16:48:36 -0700336
337 globalSignals = {.touch = true};
338 mScheduler->replaceTouchTimer(10);
339 mScheduler->setTouchStateAndIdleTimerPolicy(globalSignals);
ramindani69b58e82022-09-26 16:48:36 -0700340
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400341 modeChoices = mScheduler->chooseDisplayModes();
342 ASSERT_EQ(1u, modeChoices.size());
343
344 choice = modeChoices.get(kDisplayId1);
345 ASSERT_TRUE(choice);
Ady Abrahamace3d052022-11-17 16:25:05 -0800346 EXPECT_EQ(choice->get(), DisplayModeChoice({120_Hz, kDisplay1Mode120}, globalSignals));
ramindani69b58e82022-09-26 16:48:36 -0700347}
348
Dominik Laskowskiaa49af72024-08-12 17:29:34 -0400349TEST_F(SchedulerTest, chooseDisplayModesHighHintTouchSignal) {
Rachel Lee6ed96c92024-02-07 14:37:38 -0800350 mScheduler->registerDisplay(kDisplayId1,
351 std::make_shared<RefreshRateSelector>(kDisplay1Modes,
352 kDisplay1Mode60->getId()));
353
354 using DisplayModeChoice = TestableScheduler::DisplayModeChoice;
355
Dominik Laskowskiaa49af72024-08-12 17:29:34 -0400356 std::vector<RefreshRateSelector::LayerRequirement> layers = {kLayer, kLayer};
Rachel Lee6ed96c92024-02-07 14:37:38 -0800357 auto& lr1 = layers[0];
358 auto& lr2 = layers[1];
359
360 // Scenario that is similar to game. Expects no touch boost.
361 lr1.vote = RefreshRateSelector::LayerVoteType::ExplicitCategory;
362 lr1.frameRateCategory = FrameRateCategory::HighHint;
363 lr1.name = "ExplicitCategory HighHint";
364 lr2.vote = RefreshRateSelector::LayerVoteType::ExplicitDefault;
365 lr2.desiredRefreshRate = 30_Hz;
366 lr2.name = "30Hz ExplicitDefault";
367 mScheduler->setContentRequirements(layers);
368 auto modeChoices = mScheduler->chooseDisplayModes();
369 ASSERT_EQ(1u, modeChoices.size());
370 auto choice = modeChoices.get(kDisplayId1);
371 ASSERT_TRUE(choice);
372 EXPECT_EQ(choice->get(), DisplayModeChoice({60_Hz, kDisplay1Mode60}, {.touch = false}));
373
374 // Scenario that is similar to video playback and interaction. Expects touch boost.
375 lr1.vote = RefreshRateSelector::LayerVoteType::ExplicitCategory;
376 lr1.frameRateCategory = FrameRateCategory::HighHint;
377 lr1.name = "ExplicitCategory HighHint";
378 lr2.vote = RefreshRateSelector::LayerVoteType::ExplicitExactOrMultiple;
379 lr2.desiredRefreshRate = 30_Hz;
380 lr2.name = "30Hz ExplicitExactOrMultiple";
381 mScheduler->setContentRequirements(layers);
382 modeChoices = mScheduler->chooseDisplayModes();
383 ASSERT_EQ(1u, modeChoices.size());
384 choice = modeChoices.get(kDisplayId1);
385 ASSERT_TRUE(choice);
386 EXPECT_EQ(choice->get(), DisplayModeChoice({120_Hz, kDisplay1Mode120}, {.touch = true}));
387
388 // Scenario with explicit category and HighHint. Expects touch boost.
389 lr1.vote = RefreshRateSelector::LayerVoteType::ExplicitCategory;
390 lr1.frameRateCategory = FrameRateCategory::HighHint;
391 lr1.name = "ExplicitCategory HighHint";
392 lr2.vote = RefreshRateSelector::LayerVoteType::ExplicitCategory;
393 lr2.frameRateCategory = FrameRateCategory::Low;
394 lr2.name = "ExplicitCategory Low";
395 mScheduler->setContentRequirements(layers);
396 modeChoices = mScheduler->chooseDisplayModes();
397 ASSERT_EQ(1u, modeChoices.size());
398 choice = modeChoices.get(kDisplayId1);
399 ASSERT_TRUE(choice);
400 EXPECT_EQ(choice->get(), DisplayModeChoice({120_Hz, kDisplay1Mode120}, {.touch = true}));
401}
402
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400403TEST_F(SchedulerTest, chooseDisplayModesMultipleDisplays) {
Dominik Laskowski3ff44c72024-06-17 11:03:30 -0400404 constexpr PhysicalDisplayId kActiveDisplayId = kDisplayId1;
Dominik Laskowskib5a094b2022-10-27 12:00:12 -0400405 mScheduler->registerDisplay(kDisplayId1,
406 std::make_shared<RefreshRateSelector>(kDisplay1Modes,
Dominik Laskowski3ff44c72024-06-17 11:03:30 -0400407 kDisplay1Mode60->getId()),
408 kActiveDisplayId);
Dominik Laskowskib5a094b2022-10-27 12:00:12 -0400409 mScheduler->registerDisplay(kDisplayId2,
410 std::make_shared<RefreshRateSelector>(kDisplay2Modes,
Dominik Laskowski3ff44c72024-06-17 11:03:30 -0400411 kDisplay2Mode60->getId()),
412 kActiveDisplayId);
ramindani69b58e82022-09-26 16:48:36 -0700413
Dominik Laskowski086507b2024-05-16 15:33:16 -0400414 mScheduler->setDisplayPowerMode(kDisplayId1, hal::PowerMode::ON);
415 mScheduler->setDisplayPowerMode(kDisplayId2, hal::PowerMode::ON);
416
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400417 using DisplayModeChoice = TestableScheduler::DisplayModeChoice;
418 TestableScheduler::DisplayModeChoiceMap expectedChoices;
ramindani69b58e82022-09-26 16:48:36 -0700419
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400420 {
421 const GlobalSignals globalSignals = {.idle = true};
422 expectedChoices =
423 ftl::init::map<const PhysicalDisplayId&,
Ady Abrahamace3d052022-11-17 16:25:05 -0800424 DisplayModeChoice>(kDisplayId1,
425 FrameRateMode{60_Hz, kDisplay1Mode60},
426 globalSignals)(kDisplayId2,
427 FrameRateMode{60_Hz,
428 kDisplay2Mode60},
Dominik Laskowski9e88d622024-03-06 17:42:39 -0500429 GlobalSignals{});
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400430
Dominik Laskowskiaa49af72024-08-12 17:29:34 -0400431 mScheduler->setContentRequirements({kLayer, kLayer});
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400432 mScheduler->setTouchStateAndIdleTimerPolicy(globalSignals);
433
434 const auto actualChoices = mScheduler->chooseDisplayModes();
435 EXPECT_EQ(expectedChoices, actualChoices);
ramindani69b58e82022-09-26 16:48:36 -0700436 }
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400437 {
438 const GlobalSignals globalSignals = {.idle = false};
439 expectedChoices =
440 ftl::init::map<const PhysicalDisplayId&,
Ady Abrahamace3d052022-11-17 16:25:05 -0800441 DisplayModeChoice>(kDisplayId1,
442 FrameRateMode{120_Hz, kDisplay1Mode120},
443 globalSignals)(kDisplayId2,
444 FrameRateMode{120_Hz,
445 kDisplay2Mode120},
Dominik Laskowski9e88d622024-03-06 17:42:39 -0500446 GlobalSignals{});
ramindani69b58e82022-09-26 16:48:36 -0700447
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400448 mScheduler->setTouchStateAndIdleTimerPolicy(globalSignals);
ramindani69b58e82022-09-26 16:48:36 -0700449
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400450 const auto actualChoices = mScheduler->chooseDisplayModes();
451 EXPECT_EQ(expectedChoices, actualChoices);
ramindani69b58e82022-09-26 16:48:36 -0700452 }
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400453 {
454 const GlobalSignals globalSignals = {.touch = true};
455 mScheduler->replaceTouchTimer(10);
456 mScheduler->setTouchStateAndIdleTimerPolicy(globalSignals);
ramindani69b58e82022-09-26 16:48:36 -0700457
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400458 expectedChoices =
459 ftl::init::map<const PhysicalDisplayId&,
Ady Abrahamace3d052022-11-17 16:25:05 -0800460 DisplayModeChoice>(kDisplayId1,
461 FrameRateMode{120_Hz, kDisplay1Mode120},
462 globalSignals)(kDisplayId2,
463 FrameRateMode{120_Hz,
464 kDisplay2Mode120},
Dominik Laskowski9e88d622024-03-06 17:42:39 -0500465 GlobalSignals{});
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400466
467 const auto actualChoices = mScheduler->chooseDisplayModes();
468 EXPECT_EQ(expectedChoices, actualChoices);
ramindani69b58e82022-09-26 16:48:36 -0700469 }
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400470 {
ramindani22f2ead2023-04-21 10:27:11 -0700471 // The kDisplayId3 does not support 120Hz, The pacesetter display rate is chosen to be 120
472 // Hz. In this case only the display kDisplayId3 choose 60Hz as it does not support 120Hz.
Dominik Laskowski3ff44c72024-06-17 11:03:30 -0400473 mScheduler->registerDisplay(kDisplayId3,
474 std::make_shared<RefreshRateSelector>(kDisplay3Modes,
475 kDisplay3Mode60->getId()),
476 kActiveDisplayId);
Dominik Laskowski086507b2024-05-16 15:33:16 -0400477 mScheduler->setDisplayPowerMode(kDisplayId3, hal::PowerMode::ON);
Dominik Laskowski327d6092022-10-11 18:05:08 -0400478
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400479 const GlobalSignals globalSignals = {.touch = true};
480 mScheduler->replaceTouchTimer(10);
481 mScheduler->setTouchStateAndIdleTimerPolicy(globalSignals);
ramindani7c487282022-10-10 16:17:51 -0700482
Ady Abrahamace3d052022-11-17 16:25:05 -0800483 expectedChoices = ftl::init::map<
484 const PhysicalDisplayId&,
ramindani22f2ead2023-04-21 10:27:11 -0700485 DisplayModeChoice>(kDisplayId1, FrameRateMode{120_Hz, kDisplay1Mode120},
486 globalSignals)(kDisplayId2,
487 FrameRateMode{120_Hz, kDisplay2Mode120},
Dominik Laskowski9e88d622024-03-06 17:42:39 -0500488 GlobalSignals{})(kDisplayId3,
489 FrameRateMode{60_Hz,
490 kDisplay3Mode60},
491 GlobalSignals{});
ramindani22f2ead2023-04-21 10:27:11 -0700492
493 const auto actualChoices = mScheduler->chooseDisplayModes();
494 EXPECT_EQ(expectedChoices, actualChoices);
495 }
496 {
497 // We should choose 60Hz despite the touch signal as pacesetter only supports 60Hz
498 mScheduler->setPacesetterDisplay(kDisplayId3);
499 const GlobalSignals globalSignals = {.touch = true};
500 mScheduler->replaceTouchTimer(10);
501 mScheduler->setTouchStateAndIdleTimerPolicy(globalSignals);
502
503 expectedChoices = ftl::init::map<
504 const PhysicalDisplayId&,
Ady Abrahamace3d052022-11-17 16:25:05 -0800505 DisplayModeChoice>(kDisplayId1, FrameRateMode{60_Hz, kDisplay1Mode60},
Dominik Laskowski9e88d622024-03-06 17:42:39 -0500506 GlobalSignals{})(kDisplayId2,
507 FrameRateMode{60_Hz, kDisplay2Mode60},
508 GlobalSignals{})(kDisplayId3,
509 FrameRateMode{60_Hz,
510 kDisplay3Mode60},
511 globalSignals);
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400512
513 const auto actualChoices = mScheduler->chooseDisplayModes();
514 EXPECT_EQ(expectedChoices, actualChoices);
ramindani7c487282022-10-10 16:17:51 -0700515 }
ramindani69b58e82022-09-26 16:48:36 -0700516}
517
Dominik Laskowski50e2e4d2023-10-04 10:58:28 -0400518TEST_F(SchedulerTest, onFrameSignalMultipleDisplays) {
Dominik Laskowski3ff44c72024-06-17 11:03:30 -0400519 constexpr PhysicalDisplayId kActiveDisplayId = kDisplayId1;
Dominik Laskowski50e2e4d2023-10-04 10:58:28 -0400520 mScheduler->registerDisplay(kDisplayId1,
521 std::make_shared<RefreshRateSelector>(kDisplay1Modes,
Dominik Laskowski3ff44c72024-06-17 11:03:30 -0400522 kDisplay1Mode60->getId()),
523 kActiveDisplayId);
Dominik Laskowski50e2e4d2023-10-04 10:58:28 -0400524 mScheduler->registerDisplay(kDisplayId2,
525 std::make_shared<RefreshRateSelector>(kDisplay2Modes,
Dominik Laskowski3ff44c72024-06-17 11:03:30 -0400526 kDisplay2Mode60->getId()),
527 kActiveDisplayId);
Dominik Laskowski50e2e4d2023-10-04 10:58:28 -0400528
529 using VsyncIds = std::vector<std::pair<PhysicalDisplayId, VsyncId>>;
530
531 struct Compositor final : ICompositor {
Dominik Laskowskifb4b7372023-11-22 09:56:54 -0500532 explicit Compositor(TestableScheduler& scheduler) : scheduler(scheduler) {}
533
534 TestableScheduler& scheduler;
535
536 struct {
537 PhysicalDisplayId commit;
538 PhysicalDisplayId composite;
539 } pacesetterIds;
540
541 struct {
542 VsyncIds commit;
543 VsyncIds composite;
544 } vsyncIds;
545
Dominik Laskowski50e2e4d2023-10-04 10:58:28 -0400546 bool committed = true;
Dominik Laskowskifb4b7372023-11-22 09:56:54 -0500547 bool changePacesetter = false;
Dominik Laskowski50e2e4d2023-10-04 10:58:28 -0400548
549 void configure() override {}
550
Dominik Laskowskifb4b7372023-11-22 09:56:54 -0500551 bool commit(PhysicalDisplayId pacesetterId,
552 const scheduler::FrameTargets& targets) override {
553 pacesetterIds.commit = pacesetterId;
554
555 vsyncIds.commit.clear();
556 vsyncIds.composite.clear();
Dominik Laskowski50e2e4d2023-10-04 10:58:28 -0400557
558 for (const auto& [id, target] : targets) {
Dominik Laskowskifb4b7372023-11-22 09:56:54 -0500559 vsyncIds.commit.emplace_back(id, target->vsyncId());
560 }
561
562 if (changePacesetter) {
563 scheduler.setPacesetterDisplay(kDisplayId2);
Dominik Laskowski50e2e4d2023-10-04 10:58:28 -0400564 }
565
566 return committed;
567 }
568
Dominik Laskowskifb4b7372023-11-22 09:56:54 -0500569 CompositeResultsPerDisplay composite(PhysicalDisplayId pacesetterId,
570 const scheduler::FrameTargeters& targeters) override {
571 pacesetterIds.composite = pacesetterId;
572
Dominik Laskowski50e2e4d2023-10-04 10:58:28 -0400573 CompositeResultsPerDisplay results;
574
Dominik Laskowskifb4b7372023-11-22 09:56:54 -0500575 for (const auto& [id, targeter] : targeters) {
576 vsyncIds.composite.emplace_back(id, targeter->target().vsyncId());
Dominik Laskowski50e2e4d2023-10-04 10:58:28 -0400577 results.try_emplace(id,
578 CompositeResult{.compositionCoverage =
579 CompositionCoverage::Hwc});
580 }
581
582 return results;
583 }
584
585 void sample() override {}
ramindaniae645822024-01-11 10:57:29 -0800586 void sendNotifyExpectedPresentHint(PhysicalDisplayId) override {}
Dominik Laskowskifb4b7372023-11-22 09:56:54 -0500587 } compositor(*mScheduler);
Dominik Laskowski50e2e4d2023-10-04 10:58:28 -0400588
589 mScheduler->doFrameSignal(compositor, VsyncId(42));
590
Dominik Laskowskifb4b7372023-11-22 09:56:54 -0500591 const auto makeVsyncIds = [](VsyncId vsyncId, bool swap = false) -> VsyncIds {
592 if (swap) {
593 return {{kDisplayId2, vsyncId}, {kDisplayId1, vsyncId}};
594 } else {
595 return {{kDisplayId1, vsyncId}, {kDisplayId2, vsyncId}};
596 }
Dominik Laskowski50e2e4d2023-10-04 10:58:28 -0400597 };
598
Dominik Laskowskifb4b7372023-11-22 09:56:54 -0500599 EXPECT_EQ(kDisplayId1, compositor.pacesetterIds.commit);
600 EXPECT_EQ(kDisplayId1, compositor.pacesetterIds.composite);
601 EXPECT_EQ(makeVsyncIds(VsyncId(42)), compositor.vsyncIds.commit);
602 EXPECT_EQ(makeVsyncIds(VsyncId(42)), compositor.vsyncIds.composite);
Dominik Laskowski50e2e4d2023-10-04 10:58:28 -0400603
Dominik Laskowskifb4b7372023-11-22 09:56:54 -0500604 // FrameTargets should be updated despite the skipped commit.
Dominik Laskowski50e2e4d2023-10-04 10:58:28 -0400605 compositor.committed = false;
606 mScheduler->doFrameSignal(compositor, VsyncId(43));
607
Dominik Laskowskifb4b7372023-11-22 09:56:54 -0500608 EXPECT_EQ(kDisplayId1, compositor.pacesetterIds.commit);
609 EXPECT_EQ(kDisplayId1, compositor.pacesetterIds.composite);
610 EXPECT_EQ(makeVsyncIds(VsyncId(43)), compositor.vsyncIds.commit);
611 EXPECT_TRUE(compositor.vsyncIds.composite.empty());
612
613 // The pacesetter may change during commit.
614 compositor.committed = true;
615 compositor.changePacesetter = true;
616 mScheduler->doFrameSignal(compositor, VsyncId(44));
617
618 EXPECT_EQ(kDisplayId1, compositor.pacesetterIds.commit);
619 EXPECT_EQ(kDisplayId2, compositor.pacesetterIds.composite);
620 EXPECT_EQ(makeVsyncIds(VsyncId(44)), compositor.vsyncIds.commit);
621 EXPECT_EQ(makeVsyncIds(VsyncId(44), true), compositor.vsyncIds.composite);
Dominik Laskowski50e2e4d2023-10-04 10:58:28 -0400622}
623
ramindani0491e642023-11-16 17:42:14 -0800624TEST_F(SchedulerTest, nextFrameIntervalTest) {
625 SET_FLAG_FOR_TEST(flags::vrr_config, true);
626
627 static constexpr size_t kHistorySize = 10;
628 static constexpr size_t kMinimumSamplesForPrediction = 6;
629 static constexpr size_t kOutlierTolerancePercent = 25;
630 const auto refreshRate = Fps::fromPeriodNsecs(500);
631 auto frameRate = Fps::fromPeriodNsecs(1000);
632
633 const ftl::NonNull<DisplayModePtr> kMode = ftl::as_non_null(
634 createVrrDisplayMode(DisplayModeId(0), refreshRate,
635 hal::VrrConfig{.minFrameIntervalNs = static_cast<int32_t>(
636 frameRate.getPeriodNsecs())}));
637 std::shared_ptr<VSyncPredictor> vrrTracker =
Ady Abraham77b4fb12024-03-05 17:51:53 -0800638 std::make_shared<VSyncPredictor>(std::make_unique<ZeroClock>(), kMode, kHistorySize,
Ady Abraham20024aa2024-03-05 01:32:49 +0000639 kMinimumSamplesForPrediction,
ramindaniae645822024-01-11 10:57:29 -0800640 kOutlierTolerancePercent);
ramindani0491e642023-11-16 17:42:14 -0800641 std::shared_ptr<RefreshRateSelector> vrrSelectorPtr =
642 std::make_shared<RefreshRateSelector>(makeModes(kMode), kMode->getId());
643 TestableScheduler scheduler{std::make_unique<android::mock::VsyncController>(),
644 vrrTracker,
645 vrrSelectorPtr,
Leon Scroggins III823d4ca2023-12-12 16:57:34 -0500646 mFlinger.getFactory(),
647 mFlinger.getTimeStats(),
ramindaniae645822024-01-11 10:57:29 -0800648 mSchedulerCallback};
ramindani0491e642023-11-16 17:42:14 -0800649
Dominik Laskowski3ff44c72024-06-17 11:03:30 -0400650 scheduler.registerDisplay(kMode->getPhysicalDisplayId(), vrrSelectorPtr, std::nullopt,
651 vrrTracker);
ramindani0491e642023-11-16 17:42:14 -0800652 vrrSelectorPtr->setActiveMode(kMode->getId(), frameRate);
Ady Abrahamee6365b2024-03-06 14:31:45 -0800653 scheduler.setRenderRate(kMode->getPhysicalDisplayId(), frameRate, /*applyImmediately*/ false);
ramindani0491e642023-11-16 17:42:14 -0800654 vrrTracker->addVsyncTimestamp(0);
Ady Abraham20024aa2024-03-05 01:32:49 +0000655 // Set 1000 as vsync seq #0
656 vrrTracker->nextAnticipatedVSyncTimeFrom(700);
ramindani0491e642023-11-16 17:42:14 -0800657
ramindani0491e642023-11-16 17:42:14 -0800658 EXPECT_EQ(Fps::fromPeriodNsecs(1000),
659 scheduler.getNextFrameInterval(kMode->getPhysicalDisplayId(),
Ady Abraham4335afd2023-12-18 19:10:47 -0800660 TimePoint::fromNs(1000)));
ramindani0491e642023-11-16 17:42:14 -0800661 EXPECT_EQ(Fps::fromPeriodNsecs(1000),
662 scheduler.getNextFrameInterval(kMode->getPhysicalDisplayId(),
Ady Abraham4335afd2023-12-18 19:10:47 -0800663 TimePoint::fromNs(2000)));
ramindani0491e642023-11-16 17:42:14 -0800664
Ady Abraham4335afd2023-12-18 19:10:47 -0800665 // Not crossing the min frame period
ramindani7b32b3a2024-07-02 10:17:47 -0700666 vrrTracker->onFrameBegin(TimePoint::fromNs(2000),
667 {TimePoint::fromNs(1500), TimePoint::fromNs(1500)});
Ady Abraham20024aa2024-03-05 01:32:49 +0000668 EXPECT_EQ(Fps::fromPeriodNsecs(1000),
Ady Abraham4335afd2023-12-18 19:10:47 -0800669 scheduler.getNextFrameInterval(kMode->getPhysicalDisplayId(),
670 TimePoint::fromNs(2500)));
ramindani0491e642023-11-16 17:42:14 -0800671 // Change render rate
672 frameRate = Fps::fromPeriodNsecs(2000);
673 vrrSelectorPtr->setActiveMode(kMode->getId(), frameRate);
Ady Abrahamee6365b2024-03-06 14:31:45 -0800674 scheduler.setRenderRate(kMode->getPhysicalDisplayId(), frameRate, /*applyImmediately*/ false);
ramindani0491e642023-11-16 17:42:14 -0800675
676 EXPECT_EQ(Fps::fromPeriodNsecs(2000),
677 scheduler.getNextFrameInterval(kMode->getPhysicalDisplayId(),
Ady Abrahamfe15a352024-03-19 10:49:17 -0700678 TimePoint::fromNs(5500)));
ramindani0491e642023-11-16 17:42:14 -0800679 EXPECT_EQ(Fps::fromPeriodNsecs(2000),
680 scheduler.getNextFrameInterval(kMode->getPhysicalDisplayId(),
Ady Abrahamfe15a352024-03-19 10:49:17 -0700681 TimePoint::fromNs(7500)));
ramindani0491e642023-11-16 17:42:14 -0800682}
683
Leon Scroggins III792ea802023-11-27 17:32:51 -0500684TEST_F(SchedulerTest, resyncAllToHardwareVsync) FTL_FAKE_GUARD(kMainThreadContext) {
685 // resyncAllToHardwareVsync will result in requesting hardware VSYNC on both displays, since
686 // they are both on.
687 EXPECT_CALL(mScheduler->mockRequestHardwareVsync, Call(kDisplayId1, true)).Times(1);
688 EXPECT_CALL(mScheduler->mockRequestHardwareVsync, Call(kDisplayId2, true)).Times(1);
689
690 mScheduler->registerDisplay(kDisplayId2,
691 std::make_shared<RefreshRateSelector>(kDisplay2Modes,
692 kDisplay2Mode60->getId()));
693 mScheduler->setDisplayPowerMode(kDisplayId1, hal::PowerMode::ON);
694 mScheduler->setDisplayPowerMode(kDisplayId2, hal::PowerMode::ON);
695
696 static constexpr bool kDisallow = true;
697 mScheduler->disableHardwareVsync(kDisplayId1, kDisallow);
698 mScheduler->disableHardwareVsync(kDisplayId2, kDisallow);
699
700 static constexpr bool kAllowToEnable = true;
701 mScheduler->resyncAllToHardwareVsync(kAllowToEnable);
702}
703
704TEST_F(SchedulerTest, resyncAllDoNotAllow) FTL_FAKE_GUARD(kMainThreadContext) {
705 // Without setting allowToEnable to true, resyncAllToHardwareVsync does not
706 // result in requesting hardware VSYNC.
707 EXPECT_CALL(mScheduler->mockRequestHardwareVsync, Call(kDisplayId1, _)).Times(0);
708
709 mScheduler->setDisplayPowerMode(kDisplayId1, hal::PowerMode::ON);
710
711 static constexpr bool kDisallow = true;
712 mScheduler->disableHardwareVsync(kDisplayId1, kDisallow);
713
714 static constexpr bool kAllowToEnable = false;
715 mScheduler->resyncAllToHardwareVsync(kAllowToEnable);
716}
717
718TEST_F(SchedulerTest, resyncAllSkipsOffDisplays) FTL_FAKE_GUARD(kMainThreadContext) {
719 SET_FLAG_FOR_TEST(flags::multithreaded_present, true);
720
721 // resyncAllToHardwareVsync will result in requesting hardware VSYNC on display 1, which is on,
722 // but not on display 2, which is off.
723 EXPECT_CALL(mScheduler->mockRequestHardwareVsync, Call(kDisplayId1, true)).Times(1);
724 EXPECT_CALL(mScheduler->mockRequestHardwareVsync, Call(kDisplayId2, _)).Times(0);
725
726 mScheduler->setDisplayPowerMode(kDisplayId1, hal::PowerMode::ON);
727
728 mScheduler->registerDisplay(kDisplayId2,
729 std::make_shared<RefreshRateSelector>(kDisplay2Modes,
730 kDisplay2Mode60->getId()));
731 ASSERT_EQ(hal::PowerMode::OFF, mScheduler->getDisplayPowerMode(kDisplayId2));
732
733 static constexpr bool kDisallow = true;
734 mScheduler->disableHardwareVsync(kDisplayId1, kDisallow);
735 mScheduler->disableHardwareVsync(kDisplayId2, kDisallow);
736
737 static constexpr bool kAllowToEnable = true;
738 mScheduler->resyncAllToHardwareVsync(kAllowToEnable);
739}
740
741TEST_F(SchedulerTest, resyncAllLegacyAppliesToOffDisplays) FTL_FAKE_GUARD(kMainThreadContext) {
742 SET_FLAG_FOR_TEST(flags::multithreaded_present, false);
743
744 // In the legacy code, prior to the flag, resync applied to OFF displays.
745 EXPECT_CALL(mScheduler->mockRequestHardwareVsync, Call(kDisplayId1, true)).Times(1);
746 EXPECT_CALL(mScheduler->mockRequestHardwareVsync, Call(kDisplayId2, true)).Times(1);
747
748 mScheduler->setDisplayPowerMode(kDisplayId1, hal::PowerMode::ON);
749
750 mScheduler->registerDisplay(kDisplayId2,
751 std::make_shared<RefreshRateSelector>(kDisplay2Modes,
752 kDisplay2Mode60->getId()));
753 ASSERT_EQ(hal::PowerMode::OFF, mScheduler->getDisplayPowerMode(kDisplayId2));
754
755 static constexpr bool kDisallow = true;
756 mScheduler->disableHardwareVsync(kDisplayId1, kDisallow);
757 mScheduler->disableHardwareVsync(kDisplayId2, kDisallow);
758
759 static constexpr bool kAllowToEnable = true;
760 mScheduler->resyncAllToHardwareVsync(kAllowToEnable);
761}
762
Ady Abraham822ecbd2023-07-07 16:16:09 -0700763class AttachedChoreographerTest : public SchedulerTest {
764protected:
765 void frameRateTestScenario(Fps layerFps, int8_t frameRateCompatibility, Fps displayFps,
766 Fps expectedChoreographerFps);
767};
768
769TEST_F(AttachedChoreographerTest, registerSingle) {
770 EXPECT_TRUE(mScheduler->mutableAttachedChoreographers().empty());
771
772 const sp<MockLayer> layer = sp<MockLayer>::make(mFlinger.flinger());
773
774 EXPECT_CALL(mSchedulerCallback, onChoreographerAttached);
775 const sp<IDisplayEventConnection> connection =
Dominik Laskowski4babfc42024-02-16 12:28:40 -0500776 mScheduler->createDisplayEventConnection(Cycle::Render, {}, layer->getHandle());
Ady Abraham822ecbd2023-07-07 16:16:09 -0700777
778 EXPECT_EQ(1u, mScheduler->mutableAttachedChoreographers().size());
779 ASSERT_EQ(1u, mScheduler->mutableAttachedChoreographers().count(layer->getSequence()));
780 EXPECT_EQ(1u,
781 mScheduler->mutableAttachedChoreographers()[layer->getSequence()].connections.size());
782 EXPECT_FALSE(
783 mScheduler->mutableAttachedChoreographers()[layer->getSequence()].frameRate.isValid());
784}
785
786TEST_F(AttachedChoreographerTest, registerMultipleOnSameLayer) {
787 EXPECT_TRUE(mScheduler->mutableAttachedChoreographers().empty());
788
789 const sp<MockLayer> layer = sp<MockLayer>::make(mFlinger.flinger());
790 const auto handle = layer->getHandle();
791
792 EXPECT_CALL(mSchedulerCallback, onChoreographerAttached).Times(2);
793
794 EXPECT_CALL(*mEventThread, registerDisplayEventConnection(_))
795 .WillOnce(Return(0))
796 .WillOnce(Return(0));
797
798 const auto mockConnection1 = sp<MockEventThreadConnection>::make(mEventThread);
799 const auto mockConnection2 = sp<MockEventThreadConnection>::make(mEventThread);
Lloyd Pique6f240172024-09-16 15:51:45 -0700800 EXPECT_CALL(*mEventThread, createEventConnection(_))
Ady Abraham822ecbd2023-07-07 16:16:09 -0700801 .WillOnce(Return(mockConnection1))
802 .WillOnce(Return(mockConnection2));
803
804 const sp<IDisplayEventConnection> connection1 =
Dominik Laskowski4babfc42024-02-16 12:28:40 -0500805 mScheduler->createDisplayEventConnection(Cycle::Render, {}, handle);
Ady Abraham822ecbd2023-07-07 16:16:09 -0700806 const sp<IDisplayEventConnection> connection2 =
Dominik Laskowski4babfc42024-02-16 12:28:40 -0500807 mScheduler->createDisplayEventConnection(Cycle::Render, {}, handle);
Ady Abraham822ecbd2023-07-07 16:16:09 -0700808
809 EXPECT_EQ(1u, mScheduler->mutableAttachedChoreographers().size());
810 ASSERT_EQ(1u, mScheduler->mutableAttachedChoreographers().count(layer->getSequence()));
811 EXPECT_EQ(2u,
812 mScheduler->mutableAttachedChoreographers()[layer->getSequence()].connections.size());
813 EXPECT_FALSE(
814 mScheduler->mutableAttachedChoreographers()[layer->getSequence()].frameRate.isValid());
815}
816
817TEST_F(AttachedChoreographerTest, registerMultipleOnDifferentLayers) {
818 EXPECT_TRUE(mScheduler->mutableAttachedChoreographers().empty());
819
820 const sp<MockLayer> layer1 = sp<MockLayer>::make(mFlinger.flinger());
821 const sp<MockLayer> layer2 = sp<MockLayer>::make(mFlinger.flinger());
822
823 EXPECT_CALL(mSchedulerCallback, onChoreographerAttached).Times(2);
824 const sp<IDisplayEventConnection> connection1 =
Dominik Laskowski4babfc42024-02-16 12:28:40 -0500825 mScheduler->createDisplayEventConnection(Cycle::Render, {}, layer1->getHandle());
Ady Abraham822ecbd2023-07-07 16:16:09 -0700826 const sp<IDisplayEventConnection> connection2 =
Dominik Laskowski4babfc42024-02-16 12:28:40 -0500827 mScheduler->createDisplayEventConnection(Cycle::Render, {}, layer2->getHandle());
Ady Abraham822ecbd2023-07-07 16:16:09 -0700828
829 EXPECT_EQ(2u, mScheduler->mutableAttachedChoreographers().size());
830
831 ASSERT_EQ(1u, mScheduler->mutableAttachedChoreographers().count(layer1->getSequence()));
832 EXPECT_EQ(1u,
833 mScheduler->mutableAttachedChoreographers()[layer1->getSequence()]
834 .connections.size());
835 EXPECT_FALSE(
836 mScheduler->mutableAttachedChoreographers()[layer1->getSequence()].frameRate.isValid());
837
838 ASSERT_EQ(1u, mScheduler->mutableAttachedChoreographers().count(layer2->getSequence()));
839 EXPECT_EQ(1u,
840 mScheduler->mutableAttachedChoreographers()[layer2->getSequence()]
841 .connections.size());
842 EXPECT_FALSE(
843 mScheduler->mutableAttachedChoreographers()[layer2->getSequence()].frameRate.isValid());
844}
845
846TEST_F(AttachedChoreographerTest, removedWhenConnectionIsGone) {
847 EXPECT_TRUE(mScheduler->mutableAttachedChoreographers().empty());
848
849 const sp<MockLayer> layer = sp<MockLayer>::make(mFlinger.flinger());
850
851 EXPECT_CALL(mSchedulerCallback, onChoreographerAttached);
852
853 sp<IDisplayEventConnection> connection =
Dominik Laskowski4babfc42024-02-16 12:28:40 -0500854 mScheduler->createDisplayEventConnection(Cycle::Render, {}, layer->getHandle());
Ady Abraham822ecbd2023-07-07 16:16:09 -0700855
856 ASSERT_EQ(1u, mScheduler->mutableAttachedChoreographers().count(layer->getSequence()));
857 EXPECT_EQ(1u,
858 mScheduler->mutableAttachedChoreographers()[layer->getSequence()].connections.size());
859
860 // The connection is used all over this test, so it is quite hard to release it from here.
861 // Instead, we just do a small shortcut.
862 {
863 EXPECT_CALL(*mEventThread, registerDisplayEventConnection(_)).WillOnce(Return(0));
864 sp<MockEventThreadConnection> mockConnection =
865 sp<MockEventThreadConnection>::make(mEventThread);
866 mScheduler->mutableAttachedChoreographers()[layer->getSequence()].connections.clear();
867 mScheduler->mutableAttachedChoreographers()[layer->getSequence()].connections.emplace(
868 mockConnection);
869 }
870
871 RequestedLayerState layerState(LayerCreationArgs(layer->getSequence()));
872 LayerHierarchy hierarchy(&layerState);
873 mScheduler->updateAttachedChoreographers(hierarchy, 60_Hz);
874 EXPECT_TRUE(mScheduler->mutableAttachedChoreographers().empty());
875}
876
877TEST_F(AttachedChoreographerTest, removedWhenLayerIsGone) {
878 EXPECT_TRUE(mScheduler->mutableAttachedChoreographers().empty());
879
880 sp<MockLayer> layer = sp<MockLayer>::make(mFlinger.flinger());
881
882 EXPECT_CALL(mSchedulerCallback, onChoreographerAttached);
883 const sp<IDisplayEventConnection> connection =
Dominik Laskowski4babfc42024-02-16 12:28:40 -0500884 mScheduler->createDisplayEventConnection(Cycle::Render, {}, layer->getHandle());
Ady Abraham822ecbd2023-07-07 16:16:09 -0700885
886 layer.clear();
Ady Abraham822ecbd2023-07-07 16:16:09 -0700887 EXPECT_TRUE(mScheduler->mutableAttachedChoreographers().empty());
888}
889
890void AttachedChoreographerTest::frameRateTestScenario(Fps layerFps, int8_t frameRateCompatibility,
891 Fps displayFps,
892 Fps expectedChoreographerFps) {
893 const sp<MockLayer> layer = sp<MockLayer>::make(mFlinger.flinger());
894
895 EXPECT_CALL(mSchedulerCallback, onChoreographerAttached);
896 sp<IDisplayEventConnection> connection =
Dominik Laskowski4babfc42024-02-16 12:28:40 -0500897 mScheduler->createDisplayEventConnection(Cycle::Render, {}, layer->getHandle());
Ady Abraham822ecbd2023-07-07 16:16:09 -0700898
899 RequestedLayerState layerState(LayerCreationArgs(layer->getSequence()));
900 LayerHierarchy hierarchy(&layerState);
901
902 layerState.frameRate = layerFps.getValue();
903 layerState.frameRateCompatibility = frameRateCompatibility;
904
905 mScheduler->updateAttachedChoreographers(hierarchy, displayFps);
906
907 ASSERT_EQ(1u, mScheduler->mutableAttachedChoreographers().count(layer->getSequence()));
908 EXPECT_EQ(expectedChoreographerFps,
909 mScheduler->mutableAttachedChoreographers()[layer->getSequence()].frameRate);
910 EXPECT_EQ(expectedChoreographerFps, mEventThreadConnection->frameRate);
911}
912
913TEST_F(AttachedChoreographerTest, setsFrameRateDefault) {
914 Fps layerFps = 30_Hz;
915 int8_t frameRateCompatibility = ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT;
916 Fps displayFps = 60_Hz;
917 Fps expectedChoreographerFps = 30_Hz;
918
919 frameRateTestScenario(layerFps, frameRateCompatibility, displayFps, expectedChoreographerFps);
920
921 layerFps = Fps::fromValue(32.7f);
922 frameRateTestScenario(layerFps, frameRateCompatibility, displayFps, expectedChoreographerFps);
923}
924
925TEST_F(AttachedChoreographerTest, setsFrameRateExact) {
926 Fps layerFps = 30_Hz;
927 int8_t frameRateCompatibility = ANATIVEWINDOW_FRAME_RATE_EXACT;
928 Fps displayFps = 60_Hz;
929 Fps expectedChoreographerFps = 30_Hz;
930
931 frameRateTestScenario(layerFps, frameRateCompatibility, displayFps, expectedChoreographerFps);
932
933 layerFps = Fps::fromValue(32.7f);
934 expectedChoreographerFps = {};
935 frameRateTestScenario(layerFps, frameRateCompatibility, displayFps, expectedChoreographerFps);
936}
937
938TEST_F(AttachedChoreographerTest, setsFrameRateExactOrMultiple) {
939 Fps layerFps = 30_Hz;
940 int8_t frameRateCompatibility = ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_FIXED_SOURCE;
941 Fps displayFps = 60_Hz;
942 Fps expectedChoreographerFps = 30_Hz;
943
944 frameRateTestScenario(layerFps, frameRateCompatibility, displayFps, expectedChoreographerFps);
945
946 layerFps = Fps::fromValue(32.7f);
947 expectedChoreographerFps = {};
948 frameRateTestScenario(layerFps, frameRateCompatibility, displayFps, expectedChoreographerFps);
949}
950
951TEST_F(AttachedChoreographerTest, setsFrameRateParent) {
952 const sp<MockLayer> layer = sp<MockLayer>::make(mFlinger.flinger());
953 const sp<MockLayer> parent = sp<MockLayer>::make(mFlinger.flinger());
954
955 EXPECT_CALL(mSchedulerCallback, onChoreographerAttached);
956 sp<IDisplayEventConnection> connection =
Dominik Laskowski4babfc42024-02-16 12:28:40 -0500957 mScheduler->createDisplayEventConnection(Cycle::Render, {}, parent->getHandle());
Ady Abraham822ecbd2023-07-07 16:16:09 -0700958
959 RequestedLayerState parentState(LayerCreationArgs(parent->getSequence()));
960 LayerHierarchy parentHierarchy(&parentState);
961
962 RequestedLayerState layerState(LayerCreationArgs(layer->getSequence()));
963 LayerHierarchy hierarchy(&layerState);
964 parentHierarchy.mChildren.push_back(
965 std::make_pair(&hierarchy, LayerHierarchy::Variant::Attached));
966
967 layerState.frameRate = (30_Hz).getValue();
968 layerState.frameRateCompatibility = ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT;
969
970 mScheduler->updateAttachedChoreographers(parentHierarchy, 120_Hz);
971
972 ASSERT_EQ(1u, mScheduler->mutableAttachedChoreographers().count(parent->getSequence()));
973
974 EXPECT_EQ(30_Hz, mScheduler->mutableAttachedChoreographers()[parent->getSequence()].frameRate);
975}
976
977TEST_F(AttachedChoreographerTest, setsFrameRateParent2Children) {
978 const sp<MockLayer> layer1 = sp<MockLayer>::make(mFlinger.flinger());
979 const sp<MockLayer> layer2 = sp<MockLayer>::make(mFlinger.flinger());
980 const sp<MockLayer> parent = sp<MockLayer>::make(mFlinger.flinger());
981
982 EXPECT_CALL(mSchedulerCallback, onChoreographerAttached);
983 sp<IDisplayEventConnection> connection =
Dominik Laskowski4babfc42024-02-16 12:28:40 -0500984 mScheduler->createDisplayEventConnection(Cycle::Render, {}, parent->getHandle());
Ady Abraham822ecbd2023-07-07 16:16:09 -0700985
986 RequestedLayerState parentState(LayerCreationArgs(parent->getSequence()));
987 LayerHierarchy parentHierarchy(&parentState);
988
989 RequestedLayerState layer1State(LayerCreationArgs(layer1->getSequence()));
990 LayerHierarchy layer1Hierarchy(&layer1State);
991 parentHierarchy.mChildren.push_back(
992 std::make_pair(&layer1Hierarchy, LayerHierarchy::Variant::Attached));
993
994 RequestedLayerState layer2State(LayerCreationArgs(layer1->getSequence()));
995 LayerHierarchy layer2Hierarchy(&layer2State);
996 parentHierarchy.mChildren.push_back(
997 std::make_pair(&layer2Hierarchy, LayerHierarchy::Variant::Attached));
998
999 layer1State.frameRate = (30_Hz).getValue();
1000 layer1State.frameRateCompatibility = ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT;
1001
1002 layer2State.frameRate = (20_Hz).getValue();
1003 layer2State.frameRateCompatibility = ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT;
1004
1005 mScheduler->updateAttachedChoreographers(parentHierarchy, 120_Hz);
1006
1007 ASSERT_EQ(1u, mScheduler->mutableAttachedChoreographers().count(parent->getSequence()));
1008
1009 EXPECT_EQ(60_Hz, mScheduler->mutableAttachedChoreographers()[parent->getSequence()].frameRate);
1010}
1011
1012TEST_F(AttachedChoreographerTest, setsFrameRateParentConflictingChildren) {
1013 const sp<MockLayer> layer1 = sp<MockLayer>::make(mFlinger.flinger());
1014 const sp<MockLayer> layer2 = sp<MockLayer>::make(mFlinger.flinger());
1015 const sp<MockLayer> parent = sp<MockLayer>::make(mFlinger.flinger());
1016
1017 EXPECT_CALL(mSchedulerCallback, onChoreographerAttached);
1018 sp<IDisplayEventConnection> connection =
Dominik Laskowski4babfc42024-02-16 12:28:40 -05001019 mScheduler->createDisplayEventConnection(Cycle::Render, {}, parent->getHandle());
Ady Abraham822ecbd2023-07-07 16:16:09 -07001020
1021 RequestedLayerState parentState(LayerCreationArgs(parent->getSequence()));
1022 LayerHierarchy parentHierarchy(&parentState);
1023
1024 RequestedLayerState layer1State(LayerCreationArgs(layer1->getSequence()));
1025 LayerHierarchy layer1Hierarchy(&layer1State);
1026 parentHierarchy.mChildren.push_back(
1027 std::make_pair(&layer1Hierarchy, LayerHierarchy::Variant::Attached));
1028
1029 RequestedLayerState layer2State(LayerCreationArgs(layer1->getSequence()));
1030 LayerHierarchy layer2Hierarchy(&layer2State);
1031 parentHierarchy.mChildren.push_back(
1032 std::make_pair(&layer2Hierarchy, LayerHierarchy::Variant::Attached));
1033
1034 layer1State.frameRate = (30_Hz).getValue();
1035 layer1State.frameRateCompatibility = ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT;
1036
1037 layer2State.frameRate = (25_Hz).getValue();
1038 layer2State.frameRateCompatibility = ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT;
1039
1040 mScheduler->updateAttachedChoreographers(parentHierarchy, 120_Hz);
1041
1042 ASSERT_EQ(1u, mScheduler->mutableAttachedChoreographers().count(parent->getSequence()));
1043
1044 EXPECT_EQ(Fps(), mScheduler->mutableAttachedChoreographers()[parent->getSequence()].frameRate);
1045}
1046
1047TEST_F(AttachedChoreographerTest, setsFrameRateChild) {
1048 const sp<MockLayer> layer = sp<MockLayer>::make(mFlinger.flinger());
1049 const sp<MockLayer> parent = sp<MockLayer>::make(mFlinger.flinger());
1050
1051 EXPECT_CALL(mSchedulerCallback, onChoreographerAttached);
1052 sp<IDisplayEventConnection> connection =
Dominik Laskowski4babfc42024-02-16 12:28:40 -05001053 mScheduler->createDisplayEventConnection(Cycle::Render, {}, layer->getHandle());
Ady Abraham822ecbd2023-07-07 16:16:09 -07001054
1055 RequestedLayerState parentState(LayerCreationArgs(parent->getSequence()));
1056 LayerHierarchy parentHierarchy(&parentState);
1057
1058 RequestedLayerState layerState(LayerCreationArgs(layer->getSequence()));
1059 LayerHierarchy hierarchy(&layerState);
1060 parentHierarchy.mChildren.push_back(
1061 std::make_pair(&hierarchy, LayerHierarchy::Variant::Attached));
1062
1063 parentState.frameRate = (30_Hz).getValue();
1064 parentState.frameRateCompatibility = ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT;
1065
1066 mScheduler->updateAttachedChoreographers(parentHierarchy, 120_Hz);
1067
1068 ASSERT_EQ(1u, mScheduler->mutableAttachedChoreographers().count(layer->getSequence()));
1069
1070 EXPECT_EQ(30_Hz, mScheduler->mutableAttachedChoreographers()[layer->getSequence()].frameRate);
1071}
1072
1073TEST_F(AttachedChoreographerTest, setsFrameRateChildNotOverriddenByParent) {
1074 const sp<MockLayer> layer = sp<MockLayer>::make(mFlinger.flinger());
1075 const sp<MockLayer> parent = sp<MockLayer>::make(mFlinger.flinger());
1076
1077 EXPECT_CALL(mSchedulerCallback, onChoreographerAttached);
1078 sp<IDisplayEventConnection> connection =
Dominik Laskowski4babfc42024-02-16 12:28:40 -05001079 mScheduler->createDisplayEventConnection(Cycle::Render, {}, layer->getHandle());
Ady Abraham822ecbd2023-07-07 16:16:09 -07001080
1081 RequestedLayerState parentState(LayerCreationArgs(parent->getSequence()));
1082 LayerHierarchy parentHierarchy(&parentState);
1083
1084 RequestedLayerState layerState(LayerCreationArgs(layer->getSequence()));
1085 LayerHierarchy hierarchy(&layerState);
1086 parentHierarchy.mChildren.push_back(
1087 std::make_pair(&hierarchy, LayerHierarchy::Variant::Attached));
1088
1089 parentState.frameRate = (30_Hz).getValue();
1090 parentState.frameRateCompatibility = ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT;
1091
1092 layerState.frameRate = (60_Hz).getValue();
1093 layerState.frameRateCompatibility = ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT;
1094
1095 mScheduler->updateAttachedChoreographers(parentHierarchy, 120_Hz);
1096
1097 ASSERT_EQ(1u, mScheduler->mutableAttachedChoreographers().count(layer->getSequence()));
1098
1099 EXPECT_EQ(60_Hz, mScheduler->mutableAttachedChoreographers()[layer->getSequence()].frameRate);
1100}
1101
Dominik Laskowski068173d2021-08-11 17:22:59 -07001102} // namespace android::scheduler