blob: 125a4e4cdc0794f0f4ad691555bfc6f84867ebe7 [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 Laskowski530d6bd2022-10-10 16:55:54 -040081 static constexpr PhysicalDisplayId kDisplayId1 = PhysicalDisplayId::fromPort(255u);
Ady Abrahamace3d052022-11-17 16:25:05 -080082 static inline const ftl::NonNull<DisplayModePtr> kDisplay1Mode60 =
83 ftl::as_non_null(createDisplayMode(kDisplayId1, DisplayModeId(0), 60_Hz));
84 static inline const ftl::NonNull<DisplayModePtr> kDisplay1Mode120 =
85 ftl::as_non_null(createDisplayMode(kDisplayId1, DisplayModeId(1), 120_Hz));
Dominik Laskowski530d6bd2022-10-10 16:55:54 -040086 static inline const DisplayModes kDisplay1Modes = makeModes(kDisplay1Mode60, kDisplay1Mode120);
87
88 static constexpr PhysicalDisplayId kDisplayId2 = PhysicalDisplayId::fromPort(254u);
Ady Abrahamace3d052022-11-17 16:25:05 -080089 static inline const ftl::NonNull<DisplayModePtr> kDisplay2Mode60 =
90 ftl::as_non_null(createDisplayMode(kDisplayId2, DisplayModeId(0), 60_Hz));
91 static inline const ftl::NonNull<DisplayModePtr> kDisplay2Mode120 =
92 ftl::as_non_null(createDisplayMode(kDisplayId2, DisplayModeId(1), 120_Hz));
Dominik Laskowski530d6bd2022-10-10 16:55:54 -040093 static inline const DisplayModes kDisplay2Modes = makeModes(kDisplay2Mode60, kDisplay2Mode120);
94
95 static constexpr PhysicalDisplayId kDisplayId3 = PhysicalDisplayId::fromPort(253u);
Ady Abrahamace3d052022-11-17 16:25:05 -080096 static inline const ftl::NonNull<DisplayModePtr> kDisplay3Mode60 =
97 ftl::as_non_null(createDisplayMode(kDisplayId3, DisplayModeId(0), 60_Hz));
Dominik Laskowski530d6bd2022-10-10 16:55:54 -040098 static inline const DisplayModes kDisplay3Modes = makeModes(kDisplay3Mode60);
Marin Shalamanov2cde1002021-06-08 19:50:10 +020099
Dominik Laskowskid82e0f02022-10-26 15:23:04 -0400100 std::shared_ptr<RefreshRateSelector> mSelector =
101 std::make_shared<RefreshRateSelector>(makeModes(kDisplay1Mode60),
102 kDisplay1Mode60->getId());
Dominik Laskowski983f2b52020-06-25 16:54:06 -0700103
Dominik Laskowski8b01cc02020-07-14 19:02:41 -0700104 mock::SchedulerCallback mSchedulerCallback;
Leon Scroggins III823d4ca2023-12-12 16:57:34 -0500105 TestableSurfaceFlinger mFlinger;
ramindaniae645822024-01-11 10:57:29 -0800106 TestableScheduler* mScheduler = new TestableScheduler{mSelector, mFlinger, mSchedulerCallback};
Vishnu Naira0292282023-12-16 14:32:00 -0800107 surfaceflinger::frontend::LayerHierarchyBuilder mLayerHierarchyBuilder;
Dominik Laskowski98041832019-08-01 18:35:59 -0700108
Dominik Laskowski068173d2021-08-11 17:22:59 -0700109 MockEventThread* mEventThread;
Ana Krulec0c8cd522018-08-31 12:27:28 -0700110 sp<MockEventThreadConnection> mEventThreadConnection;
Ana Krulec0c8cd522018-08-31 12:27:28 -0700111};
112
113SchedulerTest::SchedulerTest() {
Dominik Laskowski068173d2021-08-11 17:22:59 -0700114 auto eventThread = std::make_unique<MockEventThread>();
Ana Krulec0c8cd522018-08-31 12:27:28 -0700115 mEventThread = eventThread.get();
Ana Krulec85c39af2018-12-26 17:29:57 -0800116 EXPECT_CALL(*mEventThread, registerDisplayEventConnection(_)).WillOnce(Return(0));
117
Ady Abrahamd11bade2022-08-01 16:18:03 -0700118 mEventThreadConnection = sp<MockEventThreadConnection>::make(mEventThread);
Ana Krulec0c8cd522018-08-31 12:27:28 -0700119
120 // createConnection call to scheduler makes a createEventConnection call to EventThread. Make
121 // sure that call gets executed and returns an EventThread::Connection object.
Ady Abraham0f4a1b12019-06-04 16:04:04 -0700122 EXPECT_CALL(*mEventThread, createEventConnection(_, _))
Ana Krulec0c8cd522018-08-31 12:27:28 -0700123 .WillRepeatedly(Return(mEventThreadConnection));
124
Dominik Laskowski4babfc42024-02-16 12:28:40 -0500125 mScheduler->setEventThread(Cycle::Render, std::move(eventThread));
Ady Abrahama0a16272021-03-03 15:23:35 -0800126
127 mFlinger.resetScheduler(mScheduler);
Ana Krulec0c8cd522018-08-31 12:27:28 -0700128}
129
Dominik Laskowski8b01cc02020-07-14 19:02:41 -0700130} // namespace
Ana Krulec0c8cd522018-08-31 12:27:28 -0700131
Dominik Laskowski66295432023-03-14 12:25:36 -0400132TEST_F(SchedulerTest, registerDisplay) FTL_FAKE_GUARD(kMainThreadContext) {
Dominik Laskowski008bec02023-03-14 12:04:58 -0400133 // Hardware VSYNC should not change if the display is already registered.
Dominik Laskowski66295432023-03-14 12:25:36 -0400134 EXPECT_CALL(mSchedulerCallback, requestHardwareVsync(kDisplayId1, false)).Times(0);
Dominik Laskowski008bec02023-03-14 12:04:58 -0400135 mScheduler->registerDisplay(kDisplayId1,
136 std::make_shared<RefreshRateSelector>(kDisplay1Modes,
137 kDisplay1Mode60->getId()));
138
Dominik Laskowski66295432023-03-14 12:25:36 -0400139 // TODO(b/241285191): Restore once VsyncSchedule::getPendingHardwareVsyncState is called by
140 // Scheduler::setDisplayPowerMode rather than SF::setPowerModeInternal.
141#if 0
Dominik Laskowski008bec02023-03-14 12:04:58 -0400142 // Hardware VSYNC should be disabled for newly registered displays.
Dominik Laskowski66295432023-03-14 12:25:36 -0400143 EXPECT_CALL(mSchedulerCallback, requestHardwareVsync(kDisplayId2, false)).Times(1);
144 EXPECT_CALL(mSchedulerCallback, requestHardwareVsync(kDisplayId3, false)).Times(1);
145#endif
Dominik Laskowski008bec02023-03-14 12:04:58 -0400146
147 mScheduler->registerDisplay(kDisplayId2,
148 std::make_shared<RefreshRateSelector>(kDisplay2Modes,
149 kDisplay2Mode60->getId()));
150 mScheduler->registerDisplay(kDisplayId3,
151 std::make_shared<RefreshRateSelector>(kDisplay3Modes,
152 kDisplay3Mode60->getId()));
Dominik Laskowski66295432023-03-14 12:25:36 -0400153
154 EXPECT_FALSE(mScheduler->getVsyncSchedule(kDisplayId1)->getPendingHardwareVsyncState());
155 EXPECT_FALSE(mScheduler->getVsyncSchedule(kDisplayId2)->getPendingHardwareVsyncState());
156 EXPECT_FALSE(mScheduler->getVsyncSchedule(kDisplayId3)->getPendingHardwareVsyncState());
Dominik Laskowski008bec02023-03-14 12:04:58 -0400157}
158
Marin Shalamanov2cde1002021-06-08 19:50:10 +0200159TEST_F(SchedulerTest, chooseRefreshRateForContentIsNoopWhenModeSwitchingIsNotSupported) {
160 // The layer is registered at creation time and deregistered at destruction time.
Dominik Laskowski068173d2021-08-11 17:22:59 -0700161 sp<MockLayer> layer = sp<MockLayer>::make(mFlinger.flinger());
Dominik Laskowski983f2b52020-06-25 16:54:06 -0700162
Marin Shalamanov2cde1002021-06-08 19:50:10 +0200163 // recordLayerHistory should be a noop
Dominik Laskowski9c93d602021-10-07 19:38:26 -0700164 ASSERT_EQ(0u, mScheduler->getNumActiveLayers());
Vishnu Nair5c61a012024-08-05 21:14:39 -0700165 scheduler::LayerProps layerProps = {
166 .visible = true,
167 .bounds = {0, 0, 100, 100},
168 .transform = {},
169 .setFrameRateVote = {},
170 .frameRateSelectionPriority = Layer::PRIORITY_UNSET,
171 .isSmallDirty = false,
172 .isFrontBuffered = false,
173 };
174
175 mScheduler->recordLayerHistory(layer->getSequence(), layerProps, 0, 0,
Vishnu Nairef68d6d2023-02-28 06:18:27 +0000176 LayerHistory::LayerUpdateType::Buffer);
Dominik Laskowski9c93d602021-10-07 19:38:26 -0700177 ASSERT_EQ(0u, mScheduler->getNumActiveLayers());
Dominik Laskowski983f2b52020-06-25 16:54:06 -0700178
Rachel Lee6a9731d2022-06-06 17:08:14 -0700179 constexpr hal::PowerMode kPowerModeOn = hal::PowerMode::ON;
Leon Scroggins III67388622023-02-06 20:36:20 -0500180 FTL_FAKE_GUARD(kMainThreadContext, mScheduler->setDisplayPowerMode(kDisplayId1, kPowerModeOn));
Dominik Laskowski983f2b52020-06-25 16:54:06 -0700181
182 constexpr uint32_t kDisplayArea = 999'999;
Ady Abrahamed3290f2021-05-17 15:12:14 -0700183 mScheduler->onActiveDisplayAreaChanged(kDisplayArea);
Dominik Laskowski983f2b52020-06-25 16:54:06 -0700184
ramindani69b58e82022-09-26 16:48:36 -0700185 EXPECT_CALL(mSchedulerCallback, requestDisplayModes(_)).Times(0);
Ady Abraham822ecbd2023-07-07 16:16:09 -0700186 mScheduler->chooseRefreshRateForContent(/*LayerHierarchy*/ nullptr,
187 /*updateAttachedChoreographer*/ false);
Dominik Laskowski983f2b52020-06-25 16:54:06 -0700188}
189
Marin Shalamanov2cde1002021-06-08 19:50:10 +0200190TEST_F(SchedulerTest, updateDisplayModes) {
Dominik Laskowski9c93d602021-10-07 19:38:26 -0700191 ASSERT_EQ(0u, mScheduler->layerHistorySize());
Dominik Laskowski068173d2021-08-11 17:22:59 -0700192 sp<MockLayer> layer = sp<MockLayer>::make(mFlinger.flinger());
Dominik Laskowski9c93d602021-10-07 19:38:26 -0700193 ASSERT_EQ(1u, mScheduler->layerHistorySize());
Marin Shalamanov2cde1002021-06-08 19:50:10 +0200194
Dominik Laskowski596a2562022-10-28 11:26:12 -0400195 // Replace `mSelector` with a new `RefreshRateSelector` that has different display modes.
196 mScheduler->registerDisplay(kDisplayId1,
197 std::make_shared<RefreshRateSelector>(kDisplay1Modes,
198 kDisplay1Mode60->getId()));
Marin Shalamanov2cde1002021-06-08 19:50:10 +0200199
Dominik Laskowski9c93d602021-10-07 19:38:26 -0700200 ASSERT_EQ(0u, mScheduler->getNumActiveLayers());
Vishnu Nair5c61a012024-08-05 21:14:39 -0700201 scheduler::LayerProps layerProps = {
202 .visible = true,
203 .bounds = {0, 0, 100, 100},
204 .transform = {},
205 .setFrameRateVote = {},
206 .frameRateSelectionPriority = Layer::PRIORITY_UNSET,
207 .isSmallDirty = false,
208 .isFrontBuffered = false,
209 };
210 mScheduler->recordLayerHistory(layer->getSequence(), layerProps, 0, 0,
Vishnu Nairef68d6d2023-02-28 06:18:27 +0000211 LayerHistory::LayerUpdateType::Buffer);
Dominik Laskowski9c93d602021-10-07 19:38:26 -0700212 ASSERT_EQ(1u, mScheduler->getNumActiveLayers());
Marin Shalamanov2cde1002021-06-08 19:50:10 +0200213}
214
Dominik Laskowski068173d2021-08-11 17:22:59 -0700215TEST_F(SchedulerTest, dispatchCachedReportedMode) {
216 mScheduler->clearCachedReportedMode();
217
Ady Abraham690f4612021-07-01 23:24:03 -0700218 EXPECT_CALL(*mEventThread, onModeChanged(_)).Times(0);
Dominik Laskowski068173d2021-08-11 17:22:59 -0700219 EXPECT_NO_FATAL_FAILURE(mScheduler->dispatchCachedReportedMode());
Ana Krulec6ddd2612020-09-24 13:06:33 -0700220}
221
Ady Abraham899dcdb2021-06-15 16:56:21 -0700222TEST_F(SchedulerTest, calculateMaxAcquiredBufferCount) {
Dominik Laskowski6eab42d2021-09-13 14:34:13 -0700223 EXPECT_EQ(1, mFlinger.calculateMaxAcquiredBufferCount(60_Hz, 30ms));
224 EXPECT_EQ(2, mFlinger.calculateMaxAcquiredBufferCount(90_Hz, 30ms));
225 EXPECT_EQ(3, mFlinger.calculateMaxAcquiredBufferCount(120_Hz, 30ms));
Ady Abraham564f9de2021-02-03 18:34:33 -0800226
Dominik Laskowski6eab42d2021-09-13 14:34:13 -0700227 EXPECT_EQ(2, mFlinger.calculateMaxAcquiredBufferCount(60_Hz, 40ms));
Ady Abraham564f9de2021-02-03 18:34:33 -0800228
Dominik Laskowski6eab42d2021-09-13 14:34:13 -0700229 EXPECT_EQ(1, mFlinger.calculateMaxAcquiredBufferCount(60_Hz, 10ms));
Lloyd Piquea1456c12023-05-17 12:11:15 -0700230
Lloyd Pique30db6402023-06-26 18:56:51 +0000231 const auto savedMinAcquiredBuffers = mFlinger.mutableMinAcquiredBuffers();
232 mFlinger.mutableMinAcquiredBuffers() = 2;
Lloyd Piquea1456c12023-05-17 12:11:15 -0700233 EXPECT_EQ(2, mFlinger.calculateMaxAcquiredBufferCount(60_Hz, 10ms));
Lloyd Pique30db6402023-06-26 18:56:51 +0000234 mFlinger.mutableMinAcquiredBuffers() = savedMinAcquiredBuffers;
Ady Abraham564f9de2021-02-03 18:34:33 -0800235}
236
Marin Shalamanov4c7831e2021-06-08 20:44:06 +0200237MATCHER(Is120Hz, "") {
Ady Abrahamace3d052022-11-17 16:25:05 -0800238 return isApproxEqual(arg.front().mode.fps, 120_Hz);
Marin Shalamanov4c7831e2021-06-08 20:44:06 +0200239}
240
241TEST_F(SchedulerTest, chooseRefreshRateForContentSelectsMaxRefreshRate) {
Dominik Laskowski596a2562022-10-28 11:26:12 -0400242 mScheduler->registerDisplay(kDisplayId1,
243 std::make_shared<RefreshRateSelector>(kDisplay1Modes,
244 kDisplay1Mode60->getId()));
Marin Shalamanov4c7831e2021-06-08 20:44:06 +0200245
Dominik Laskowski0c41ffa2021-12-24 16:45:12 -0800246 const sp<MockLayer> layer = sp<MockLayer>::make(mFlinger.flinger());
Vishnu Nair5c61a012024-08-05 21:14:39 -0700247 scheduler::LayerProps layerProps = {
248 .visible = true,
249 .bounds = {0, 0, 0, 0},
250 .transform = {},
251 .setFrameRateVote = {},
252 .frameRateSelectionPriority = Layer::PRIORITY_UNSET,
253 .isSmallDirty = false,
254 .isFrontBuffered = false,
255 };
256 mScheduler->recordLayerHistory(layer->getSequence(), layerProps, 0, systemTime(),
Vishnu Nairef68d6d2023-02-28 06:18:27 +0000257 LayerHistory::LayerUpdateType::Buffer);
Marin Shalamanov4c7831e2021-06-08 20:44:06 +0200258
Rachel Lee6a9731d2022-06-06 17:08:14 -0700259 constexpr hal::PowerMode kPowerModeOn = hal::PowerMode::ON;
Leon Scroggins III67388622023-02-06 20:36:20 -0500260 FTL_FAKE_GUARD(kMainThreadContext, mScheduler->setDisplayPowerMode(kDisplayId1, kPowerModeOn));
Marin Shalamanov4c7831e2021-06-08 20:44:06 +0200261
262 constexpr uint32_t kDisplayArea = 999'999;
Ady Abrahamed3290f2021-05-17 15:12:14 -0700263 mScheduler->onActiveDisplayAreaChanged(kDisplayArea);
Marin Shalamanov4c7831e2021-06-08 20:44:06 +0200264
ramindani69b58e82022-09-26 16:48:36 -0700265 EXPECT_CALL(mSchedulerCallback, requestDisplayModes(Is120Hz())).Times(1);
Ady Abraham822ecbd2023-07-07 16:16:09 -0700266 mScheduler->chooseRefreshRateForContent(/*LayerHierarchy*/ nullptr,
267 /*updateAttachedChoreographer*/ false);
Dominik Laskowski0c41ffa2021-12-24 16:45:12 -0800268
269 // No-op if layer requirements have not changed.
ramindani69b58e82022-09-26 16:48:36 -0700270 EXPECT_CALL(mSchedulerCallback, requestDisplayModes(_)).Times(0);
Ady Abraham822ecbd2023-07-07 16:16:09 -0700271 mScheduler->chooseRefreshRateForContent(/*LayerHierarchy*/ nullptr,
272 /*updateAttachedChoreographer*/ false);
Marin Shalamanov4c7831e2021-06-08 20:44:06 +0200273}
274
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400275TEST_F(SchedulerTest, chooseDisplayModesSingleDisplay) {
Dominik Laskowskib5a094b2022-10-27 12:00:12 -0400276 mScheduler->registerDisplay(kDisplayId1,
277 std::make_shared<RefreshRateSelector>(kDisplay1Modes,
278 kDisplay1Mode60->getId()));
ramindani69b58e82022-09-26 16:48:36 -0700279
Dominik Laskowskid82e0f02022-10-26 15:23:04 -0400280 std::vector<RefreshRateSelector::LayerRequirement> layers =
281 std::vector<RefreshRateSelector::LayerRequirement>({{.weight = 1.f}, {.weight = 1.f}});
ramindani69b58e82022-09-26 16:48:36 -0700282 mScheduler->setContentRequirements(layers);
283 GlobalSignals globalSignals = {.idle = true};
284 mScheduler->setTouchStateAndIdleTimerPolicy(globalSignals);
285
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400286 using DisplayModeChoice = TestableScheduler::DisplayModeChoice;
287
288 auto modeChoices = mScheduler->chooseDisplayModes();
289 ASSERT_EQ(1u, modeChoices.size());
290
291 auto choice = modeChoices.get(kDisplayId1);
292 ASSERT_TRUE(choice);
Ady Abrahamace3d052022-11-17 16:25:05 -0800293 EXPECT_EQ(choice->get(), DisplayModeChoice({60_Hz, kDisplay1Mode60}, globalSignals));
ramindani69b58e82022-09-26 16:48:36 -0700294
295 globalSignals = {.idle = false};
296 mScheduler->setTouchStateAndIdleTimerPolicy(globalSignals);
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400297
298 modeChoices = mScheduler->chooseDisplayModes();
299 ASSERT_EQ(1u, modeChoices.size());
300
301 choice = modeChoices.get(kDisplayId1);
302 ASSERT_TRUE(choice);
Ady Abrahamace3d052022-11-17 16:25:05 -0800303 EXPECT_EQ(choice->get(), DisplayModeChoice({120_Hz, kDisplay1Mode120}, globalSignals));
ramindani69b58e82022-09-26 16:48:36 -0700304
305 globalSignals = {.touch = true};
306 mScheduler->replaceTouchTimer(10);
307 mScheduler->setTouchStateAndIdleTimerPolicy(globalSignals);
ramindani69b58e82022-09-26 16:48:36 -0700308
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400309 modeChoices = mScheduler->chooseDisplayModes();
310 ASSERT_EQ(1u, modeChoices.size());
311
312 choice = modeChoices.get(kDisplayId1);
313 ASSERT_TRUE(choice);
Ady Abrahamace3d052022-11-17 16:25:05 -0800314 EXPECT_EQ(choice->get(), DisplayModeChoice({120_Hz, kDisplay1Mode120}, globalSignals));
ramindani69b58e82022-09-26 16:48:36 -0700315}
316
Rachel Lee6ed96c92024-02-07 14:37:38 -0800317TEST_F(SchedulerTest, chooseDisplayModesSingleDisplayHighHintTouchSignal) {
318 mScheduler->registerDisplay(kDisplayId1,
319 std::make_shared<RefreshRateSelector>(kDisplay1Modes,
320 kDisplay1Mode60->getId()));
321
322 using DisplayModeChoice = TestableScheduler::DisplayModeChoice;
323
324 std::vector<RefreshRateSelector::LayerRequirement> layers =
325 std::vector<RefreshRateSelector::LayerRequirement>({{.weight = 1.f}, {.weight = 1.f}});
326 auto& lr1 = layers[0];
327 auto& lr2 = layers[1];
328
329 // Scenario that is similar to game. Expects no touch boost.
330 lr1.vote = RefreshRateSelector::LayerVoteType::ExplicitCategory;
331 lr1.frameRateCategory = FrameRateCategory::HighHint;
332 lr1.name = "ExplicitCategory HighHint";
333 lr2.vote = RefreshRateSelector::LayerVoteType::ExplicitDefault;
334 lr2.desiredRefreshRate = 30_Hz;
335 lr2.name = "30Hz ExplicitDefault";
336 mScheduler->setContentRequirements(layers);
337 auto modeChoices = mScheduler->chooseDisplayModes();
338 ASSERT_EQ(1u, modeChoices.size());
339 auto choice = modeChoices.get(kDisplayId1);
340 ASSERT_TRUE(choice);
341 EXPECT_EQ(choice->get(), DisplayModeChoice({60_Hz, kDisplay1Mode60}, {.touch = false}));
342
343 // Scenario that is similar to video playback and interaction. Expects touch boost.
344 lr1.vote = RefreshRateSelector::LayerVoteType::ExplicitCategory;
345 lr1.frameRateCategory = FrameRateCategory::HighHint;
346 lr1.name = "ExplicitCategory HighHint";
347 lr2.vote = RefreshRateSelector::LayerVoteType::ExplicitExactOrMultiple;
348 lr2.desiredRefreshRate = 30_Hz;
349 lr2.name = "30Hz ExplicitExactOrMultiple";
350 mScheduler->setContentRequirements(layers);
351 modeChoices = mScheduler->chooseDisplayModes();
352 ASSERT_EQ(1u, modeChoices.size());
353 choice = modeChoices.get(kDisplayId1);
354 ASSERT_TRUE(choice);
355 EXPECT_EQ(choice->get(), DisplayModeChoice({120_Hz, kDisplay1Mode120}, {.touch = true}));
356
357 // Scenario with explicit category and HighHint. Expects touch boost.
358 lr1.vote = RefreshRateSelector::LayerVoteType::ExplicitCategory;
359 lr1.frameRateCategory = FrameRateCategory::HighHint;
360 lr1.name = "ExplicitCategory HighHint";
361 lr2.vote = RefreshRateSelector::LayerVoteType::ExplicitCategory;
362 lr2.frameRateCategory = FrameRateCategory::Low;
363 lr2.name = "ExplicitCategory Low";
364 mScheduler->setContentRequirements(layers);
365 modeChoices = mScheduler->chooseDisplayModes();
366 ASSERT_EQ(1u, modeChoices.size());
367 choice = modeChoices.get(kDisplayId1);
368 ASSERT_TRUE(choice);
369 EXPECT_EQ(choice->get(), DisplayModeChoice({120_Hz, kDisplay1Mode120}, {.touch = true}));
370}
371
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400372TEST_F(SchedulerTest, chooseDisplayModesMultipleDisplays) {
Dominik Laskowski3ff44c72024-06-17 11:03:30 -0400373 constexpr PhysicalDisplayId kActiveDisplayId = kDisplayId1;
Dominik Laskowskib5a094b2022-10-27 12:00:12 -0400374 mScheduler->registerDisplay(kDisplayId1,
375 std::make_shared<RefreshRateSelector>(kDisplay1Modes,
Dominik Laskowski3ff44c72024-06-17 11:03:30 -0400376 kDisplay1Mode60->getId()),
377 kActiveDisplayId);
Dominik Laskowskib5a094b2022-10-27 12:00:12 -0400378 mScheduler->registerDisplay(kDisplayId2,
379 std::make_shared<RefreshRateSelector>(kDisplay2Modes,
Dominik Laskowski3ff44c72024-06-17 11:03:30 -0400380 kDisplay2Mode60->getId()),
381 kActiveDisplayId);
ramindani69b58e82022-09-26 16:48:36 -0700382
Dominik Laskowski086507b2024-05-16 15:33:16 -0400383 mScheduler->setDisplayPowerMode(kDisplayId1, hal::PowerMode::ON);
384 mScheduler->setDisplayPowerMode(kDisplayId2, hal::PowerMode::ON);
385
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400386 using DisplayModeChoice = TestableScheduler::DisplayModeChoice;
387 TestableScheduler::DisplayModeChoiceMap expectedChoices;
ramindani69b58e82022-09-26 16:48:36 -0700388
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400389 {
390 const GlobalSignals globalSignals = {.idle = true};
391 expectedChoices =
392 ftl::init::map<const PhysicalDisplayId&,
Ady Abrahamace3d052022-11-17 16:25:05 -0800393 DisplayModeChoice>(kDisplayId1,
394 FrameRateMode{60_Hz, kDisplay1Mode60},
395 globalSignals)(kDisplayId2,
396 FrameRateMode{60_Hz,
397 kDisplay2Mode60},
Dominik Laskowski9e88d622024-03-06 17:42:39 -0500398 GlobalSignals{});
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400399
Dominik Laskowskid82e0f02022-10-26 15:23:04 -0400400 std::vector<RefreshRateSelector::LayerRequirement> layers = {{.weight = 1.f},
401 {.weight = 1.f}};
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400402 mScheduler->setContentRequirements(layers);
403 mScheduler->setTouchStateAndIdleTimerPolicy(globalSignals);
404
405 const auto actualChoices = mScheduler->chooseDisplayModes();
406 EXPECT_EQ(expectedChoices, actualChoices);
ramindani69b58e82022-09-26 16:48:36 -0700407 }
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400408 {
409 const GlobalSignals globalSignals = {.idle = false};
410 expectedChoices =
411 ftl::init::map<const PhysicalDisplayId&,
Ady Abrahamace3d052022-11-17 16:25:05 -0800412 DisplayModeChoice>(kDisplayId1,
413 FrameRateMode{120_Hz, kDisplay1Mode120},
414 globalSignals)(kDisplayId2,
415 FrameRateMode{120_Hz,
416 kDisplay2Mode120},
Dominik Laskowski9e88d622024-03-06 17:42:39 -0500417 GlobalSignals{});
ramindani69b58e82022-09-26 16:48:36 -0700418
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400419 mScheduler->setTouchStateAndIdleTimerPolicy(globalSignals);
ramindani69b58e82022-09-26 16:48:36 -0700420
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400421 const auto actualChoices = mScheduler->chooseDisplayModes();
422 EXPECT_EQ(expectedChoices, actualChoices);
ramindani69b58e82022-09-26 16:48:36 -0700423 }
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400424 {
425 const GlobalSignals globalSignals = {.touch = true};
426 mScheduler->replaceTouchTimer(10);
427 mScheduler->setTouchStateAndIdleTimerPolicy(globalSignals);
ramindani69b58e82022-09-26 16:48:36 -0700428
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400429 expectedChoices =
430 ftl::init::map<const PhysicalDisplayId&,
Ady Abrahamace3d052022-11-17 16:25:05 -0800431 DisplayModeChoice>(kDisplayId1,
432 FrameRateMode{120_Hz, kDisplay1Mode120},
433 globalSignals)(kDisplayId2,
434 FrameRateMode{120_Hz,
435 kDisplay2Mode120},
Dominik Laskowski9e88d622024-03-06 17:42:39 -0500436 GlobalSignals{});
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400437
438 const auto actualChoices = mScheduler->chooseDisplayModes();
439 EXPECT_EQ(expectedChoices, actualChoices);
ramindani69b58e82022-09-26 16:48:36 -0700440 }
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400441 {
ramindani22f2ead2023-04-21 10:27:11 -0700442 // The kDisplayId3 does not support 120Hz, The pacesetter display rate is chosen to be 120
443 // Hz. In this case only the display kDisplayId3 choose 60Hz as it does not support 120Hz.
Dominik Laskowski3ff44c72024-06-17 11:03:30 -0400444 mScheduler->registerDisplay(kDisplayId3,
445 std::make_shared<RefreshRateSelector>(kDisplay3Modes,
446 kDisplay3Mode60->getId()),
447 kActiveDisplayId);
Dominik Laskowski086507b2024-05-16 15:33:16 -0400448 mScheduler->setDisplayPowerMode(kDisplayId3, hal::PowerMode::ON);
Dominik Laskowski327d6092022-10-11 18:05:08 -0400449
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400450 const GlobalSignals globalSignals = {.touch = true};
451 mScheduler->replaceTouchTimer(10);
452 mScheduler->setTouchStateAndIdleTimerPolicy(globalSignals);
ramindani7c487282022-10-10 16:17:51 -0700453
Ady Abrahamace3d052022-11-17 16:25:05 -0800454 expectedChoices = ftl::init::map<
455 const PhysicalDisplayId&,
ramindani22f2ead2023-04-21 10:27:11 -0700456 DisplayModeChoice>(kDisplayId1, FrameRateMode{120_Hz, kDisplay1Mode120},
457 globalSignals)(kDisplayId2,
458 FrameRateMode{120_Hz, kDisplay2Mode120},
Dominik Laskowski9e88d622024-03-06 17:42:39 -0500459 GlobalSignals{})(kDisplayId3,
460 FrameRateMode{60_Hz,
461 kDisplay3Mode60},
462 GlobalSignals{});
ramindani22f2ead2023-04-21 10:27:11 -0700463
464 const auto actualChoices = mScheduler->chooseDisplayModes();
465 EXPECT_EQ(expectedChoices, actualChoices);
466 }
467 {
468 // We should choose 60Hz despite the touch signal as pacesetter only supports 60Hz
469 mScheduler->setPacesetterDisplay(kDisplayId3);
470 const GlobalSignals globalSignals = {.touch = true};
471 mScheduler->replaceTouchTimer(10);
472 mScheduler->setTouchStateAndIdleTimerPolicy(globalSignals);
473
474 expectedChoices = ftl::init::map<
475 const PhysicalDisplayId&,
Ady Abrahamace3d052022-11-17 16:25:05 -0800476 DisplayModeChoice>(kDisplayId1, FrameRateMode{60_Hz, kDisplay1Mode60},
Dominik Laskowski9e88d622024-03-06 17:42:39 -0500477 GlobalSignals{})(kDisplayId2,
478 FrameRateMode{60_Hz, kDisplay2Mode60},
479 GlobalSignals{})(kDisplayId3,
480 FrameRateMode{60_Hz,
481 kDisplay3Mode60},
482 globalSignals);
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400483
484 const auto actualChoices = mScheduler->chooseDisplayModes();
485 EXPECT_EQ(expectedChoices, actualChoices);
ramindani7c487282022-10-10 16:17:51 -0700486 }
ramindani69b58e82022-09-26 16:48:36 -0700487}
488
Dominik Laskowski50e2e4d2023-10-04 10:58:28 -0400489TEST_F(SchedulerTest, onFrameSignalMultipleDisplays) {
Dominik Laskowski3ff44c72024-06-17 11:03:30 -0400490 constexpr PhysicalDisplayId kActiveDisplayId = kDisplayId1;
Dominik Laskowski50e2e4d2023-10-04 10:58:28 -0400491 mScheduler->registerDisplay(kDisplayId1,
492 std::make_shared<RefreshRateSelector>(kDisplay1Modes,
Dominik Laskowski3ff44c72024-06-17 11:03:30 -0400493 kDisplay1Mode60->getId()),
494 kActiveDisplayId);
Dominik Laskowski50e2e4d2023-10-04 10:58:28 -0400495 mScheduler->registerDisplay(kDisplayId2,
496 std::make_shared<RefreshRateSelector>(kDisplay2Modes,
Dominik Laskowski3ff44c72024-06-17 11:03:30 -0400497 kDisplay2Mode60->getId()),
498 kActiveDisplayId);
Dominik Laskowski50e2e4d2023-10-04 10:58:28 -0400499
500 using VsyncIds = std::vector<std::pair<PhysicalDisplayId, VsyncId>>;
501
502 struct Compositor final : ICompositor {
Dominik Laskowskifb4b7372023-11-22 09:56:54 -0500503 explicit Compositor(TestableScheduler& scheduler) : scheduler(scheduler) {}
504
505 TestableScheduler& scheduler;
506
507 struct {
508 PhysicalDisplayId commit;
509 PhysicalDisplayId composite;
510 } pacesetterIds;
511
512 struct {
513 VsyncIds commit;
514 VsyncIds composite;
515 } vsyncIds;
516
Dominik Laskowski50e2e4d2023-10-04 10:58:28 -0400517 bool committed = true;
Dominik Laskowskifb4b7372023-11-22 09:56:54 -0500518 bool changePacesetter = false;
Dominik Laskowski50e2e4d2023-10-04 10:58:28 -0400519
520 void configure() override {}
521
Dominik Laskowskifb4b7372023-11-22 09:56:54 -0500522 bool commit(PhysicalDisplayId pacesetterId,
523 const scheduler::FrameTargets& targets) override {
524 pacesetterIds.commit = pacesetterId;
525
526 vsyncIds.commit.clear();
527 vsyncIds.composite.clear();
Dominik Laskowski50e2e4d2023-10-04 10:58:28 -0400528
529 for (const auto& [id, target] : targets) {
Dominik Laskowskifb4b7372023-11-22 09:56:54 -0500530 vsyncIds.commit.emplace_back(id, target->vsyncId());
531 }
532
533 if (changePacesetter) {
534 scheduler.setPacesetterDisplay(kDisplayId2);
Dominik Laskowski50e2e4d2023-10-04 10:58:28 -0400535 }
536
537 return committed;
538 }
539
Dominik Laskowskifb4b7372023-11-22 09:56:54 -0500540 CompositeResultsPerDisplay composite(PhysicalDisplayId pacesetterId,
541 const scheduler::FrameTargeters& targeters) override {
542 pacesetterIds.composite = pacesetterId;
543
Dominik Laskowski50e2e4d2023-10-04 10:58:28 -0400544 CompositeResultsPerDisplay results;
545
Dominik Laskowskifb4b7372023-11-22 09:56:54 -0500546 for (const auto& [id, targeter] : targeters) {
547 vsyncIds.composite.emplace_back(id, targeter->target().vsyncId());
Dominik Laskowski50e2e4d2023-10-04 10:58:28 -0400548 results.try_emplace(id,
549 CompositeResult{.compositionCoverage =
550 CompositionCoverage::Hwc});
551 }
552
553 return results;
554 }
555
556 void sample() override {}
ramindaniae645822024-01-11 10:57:29 -0800557 void sendNotifyExpectedPresentHint(PhysicalDisplayId) override {}
Dominik Laskowskifb4b7372023-11-22 09:56:54 -0500558 } compositor(*mScheduler);
Dominik Laskowski50e2e4d2023-10-04 10:58:28 -0400559
560 mScheduler->doFrameSignal(compositor, VsyncId(42));
561
Dominik Laskowskifb4b7372023-11-22 09:56:54 -0500562 const auto makeVsyncIds = [](VsyncId vsyncId, bool swap = false) -> VsyncIds {
563 if (swap) {
564 return {{kDisplayId2, vsyncId}, {kDisplayId1, vsyncId}};
565 } else {
566 return {{kDisplayId1, vsyncId}, {kDisplayId2, vsyncId}};
567 }
Dominik Laskowski50e2e4d2023-10-04 10:58:28 -0400568 };
569
Dominik Laskowskifb4b7372023-11-22 09:56:54 -0500570 EXPECT_EQ(kDisplayId1, compositor.pacesetterIds.commit);
571 EXPECT_EQ(kDisplayId1, compositor.pacesetterIds.composite);
572 EXPECT_EQ(makeVsyncIds(VsyncId(42)), compositor.vsyncIds.commit);
573 EXPECT_EQ(makeVsyncIds(VsyncId(42)), compositor.vsyncIds.composite);
Dominik Laskowski50e2e4d2023-10-04 10:58:28 -0400574
Dominik Laskowskifb4b7372023-11-22 09:56:54 -0500575 // FrameTargets should be updated despite the skipped commit.
Dominik Laskowski50e2e4d2023-10-04 10:58:28 -0400576 compositor.committed = false;
577 mScheduler->doFrameSignal(compositor, VsyncId(43));
578
Dominik Laskowskifb4b7372023-11-22 09:56:54 -0500579 EXPECT_EQ(kDisplayId1, compositor.pacesetterIds.commit);
580 EXPECT_EQ(kDisplayId1, compositor.pacesetterIds.composite);
581 EXPECT_EQ(makeVsyncIds(VsyncId(43)), compositor.vsyncIds.commit);
582 EXPECT_TRUE(compositor.vsyncIds.composite.empty());
583
584 // The pacesetter may change during commit.
585 compositor.committed = true;
586 compositor.changePacesetter = true;
587 mScheduler->doFrameSignal(compositor, VsyncId(44));
588
589 EXPECT_EQ(kDisplayId1, compositor.pacesetterIds.commit);
590 EXPECT_EQ(kDisplayId2, compositor.pacesetterIds.composite);
591 EXPECT_EQ(makeVsyncIds(VsyncId(44)), compositor.vsyncIds.commit);
592 EXPECT_EQ(makeVsyncIds(VsyncId(44), true), compositor.vsyncIds.composite);
Dominik Laskowski50e2e4d2023-10-04 10:58:28 -0400593}
594
ramindani0491e642023-11-16 17:42:14 -0800595TEST_F(SchedulerTest, nextFrameIntervalTest) {
596 SET_FLAG_FOR_TEST(flags::vrr_config, true);
597
598 static constexpr size_t kHistorySize = 10;
599 static constexpr size_t kMinimumSamplesForPrediction = 6;
600 static constexpr size_t kOutlierTolerancePercent = 25;
601 const auto refreshRate = Fps::fromPeriodNsecs(500);
602 auto frameRate = Fps::fromPeriodNsecs(1000);
603
604 const ftl::NonNull<DisplayModePtr> kMode = ftl::as_non_null(
605 createVrrDisplayMode(DisplayModeId(0), refreshRate,
606 hal::VrrConfig{.minFrameIntervalNs = static_cast<int32_t>(
607 frameRate.getPeriodNsecs())}));
608 std::shared_ptr<VSyncPredictor> vrrTracker =
Ady Abraham77b4fb12024-03-05 17:51:53 -0800609 std::make_shared<VSyncPredictor>(std::make_unique<ZeroClock>(), kMode, kHistorySize,
Ady Abraham20024aa2024-03-05 01:32:49 +0000610 kMinimumSamplesForPrediction,
ramindaniae645822024-01-11 10:57:29 -0800611 kOutlierTolerancePercent);
ramindani0491e642023-11-16 17:42:14 -0800612 std::shared_ptr<RefreshRateSelector> vrrSelectorPtr =
613 std::make_shared<RefreshRateSelector>(makeModes(kMode), kMode->getId());
614 TestableScheduler scheduler{std::make_unique<android::mock::VsyncController>(),
615 vrrTracker,
616 vrrSelectorPtr,
Leon Scroggins III823d4ca2023-12-12 16:57:34 -0500617 mFlinger.getFactory(),
618 mFlinger.getTimeStats(),
ramindaniae645822024-01-11 10:57:29 -0800619 mSchedulerCallback};
ramindani0491e642023-11-16 17:42:14 -0800620
Dominik Laskowski3ff44c72024-06-17 11:03:30 -0400621 scheduler.registerDisplay(kMode->getPhysicalDisplayId(), vrrSelectorPtr, std::nullopt,
622 vrrTracker);
ramindani0491e642023-11-16 17:42:14 -0800623 vrrSelectorPtr->setActiveMode(kMode->getId(), frameRate);
Ady Abrahamee6365b2024-03-06 14:31:45 -0800624 scheduler.setRenderRate(kMode->getPhysicalDisplayId(), frameRate, /*applyImmediately*/ false);
ramindani0491e642023-11-16 17:42:14 -0800625 vrrTracker->addVsyncTimestamp(0);
Ady Abraham20024aa2024-03-05 01:32:49 +0000626 // Set 1000 as vsync seq #0
627 vrrTracker->nextAnticipatedVSyncTimeFrom(700);
ramindani0491e642023-11-16 17:42:14 -0800628
ramindani0491e642023-11-16 17:42:14 -0800629 EXPECT_EQ(Fps::fromPeriodNsecs(1000),
630 scheduler.getNextFrameInterval(kMode->getPhysicalDisplayId(),
Ady Abraham4335afd2023-12-18 19:10:47 -0800631 TimePoint::fromNs(1000)));
ramindani0491e642023-11-16 17:42:14 -0800632 EXPECT_EQ(Fps::fromPeriodNsecs(1000),
633 scheduler.getNextFrameInterval(kMode->getPhysicalDisplayId(),
Ady Abraham4335afd2023-12-18 19:10:47 -0800634 TimePoint::fromNs(2000)));
ramindani0491e642023-11-16 17:42:14 -0800635
Ady Abraham4335afd2023-12-18 19:10:47 -0800636 // Not crossing the min frame period
ramindani7b32b3a2024-07-02 10:17:47 -0700637 vrrTracker->onFrameBegin(TimePoint::fromNs(2000),
638 {TimePoint::fromNs(1500), TimePoint::fromNs(1500)});
Ady Abraham20024aa2024-03-05 01:32:49 +0000639 EXPECT_EQ(Fps::fromPeriodNsecs(1000),
Ady Abraham4335afd2023-12-18 19:10:47 -0800640 scheduler.getNextFrameInterval(kMode->getPhysicalDisplayId(),
641 TimePoint::fromNs(2500)));
ramindani0491e642023-11-16 17:42:14 -0800642 // Change render rate
643 frameRate = Fps::fromPeriodNsecs(2000);
644 vrrSelectorPtr->setActiveMode(kMode->getId(), frameRate);
Ady Abrahamee6365b2024-03-06 14:31:45 -0800645 scheduler.setRenderRate(kMode->getPhysicalDisplayId(), frameRate, /*applyImmediately*/ false);
ramindani0491e642023-11-16 17:42:14 -0800646
647 EXPECT_EQ(Fps::fromPeriodNsecs(2000),
648 scheduler.getNextFrameInterval(kMode->getPhysicalDisplayId(),
Ady Abrahamfe15a352024-03-19 10:49:17 -0700649 TimePoint::fromNs(5500)));
ramindani0491e642023-11-16 17:42:14 -0800650 EXPECT_EQ(Fps::fromPeriodNsecs(2000),
651 scheduler.getNextFrameInterval(kMode->getPhysicalDisplayId(),
Ady Abrahamfe15a352024-03-19 10:49:17 -0700652 TimePoint::fromNs(7500)));
ramindani0491e642023-11-16 17:42:14 -0800653}
654
Leon Scroggins III792ea802023-11-27 17:32:51 -0500655TEST_F(SchedulerTest, resyncAllToHardwareVsync) FTL_FAKE_GUARD(kMainThreadContext) {
656 // resyncAllToHardwareVsync will result in requesting hardware VSYNC on both displays, since
657 // they are both on.
658 EXPECT_CALL(mScheduler->mockRequestHardwareVsync, Call(kDisplayId1, true)).Times(1);
659 EXPECT_CALL(mScheduler->mockRequestHardwareVsync, Call(kDisplayId2, true)).Times(1);
660
661 mScheduler->registerDisplay(kDisplayId2,
662 std::make_shared<RefreshRateSelector>(kDisplay2Modes,
663 kDisplay2Mode60->getId()));
664 mScheduler->setDisplayPowerMode(kDisplayId1, hal::PowerMode::ON);
665 mScheduler->setDisplayPowerMode(kDisplayId2, hal::PowerMode::ON);
666
667 static constexpr bool kDisallow = true;
668 mScheduler->disableHardwareVsync(kDisplayId1, kDisallow);
669 mScheduler->disableHardwareVsync(kDisplayId2, kDisallow);
670
671 static constexpr bool kAllowToEnable = true;
672 mScheduler->resyncAllToHardwareVsync(kAllowToEnable);
673}
674
675TEST_F(SchedulerTest, resyncAllDoNotAllow) FTL_FAKE_GUARD(kMainThreadContext) {
676 // Without setting allowToEnable to true, resyncAllToHardwareVsync does not
677 // result in requesting hardware VSYNC.
678 EXPECT_CALL(mScheduler->mockRequestHardwareVsync, Call(kDisplayId1, _)).Times(0);
679
680 mScheduler->setDisplayPowerMode(kDisplayId1, hal::PowerMode::ON);
681
682 static constexpr bool kDisallow = true;
683 mScheduler->disableHardwareVsync(kDisplayId1, kDisallow);
684
685 static constexpr bool kAllowToEnable = false;
686 mScheduler->resyncAllToHardwareVsync(kAllowToEnable);
687}
688
689TEST_F(SchedulerTest, resyncAllSkipsOffDisplays) FTL_FAKE_GUARD(kMainThreadContext) {
690 SET_FLAG_FOR_TEST(flags::multithreaded_present, true);
691
692 // resyncAllToHardwareVsync will result in requesting hardware VSYNC on display 1, which is on,
693 // but not on display 2, which is off.
694 EXPECT_CALL(mScheduler->mockRequestHardwareVsync, Call(kDisplayId1, true)).Times(1);
695 EXPECT_CALL(mScheduler->mockRequestHardwareVsync, Call(kDisplayId2, _)).Times(0);
696
697 mScheduler->setDisplayPowerMode(kDisplayId1, hal::PowerMode::ON);
698
699 mScheduler->registerDisplay(kDisplayId2,
700 std::make_shared<RefreshRateSelector>(kDisplay2Modes,
701 kDisplay2Mode60->getId()));
702 ASSERT_EQ(hal::PowerMode::OFF, mScheduler->getDisplayPowerMode(kDisplayId2));
703
704 static constexpr bool kDisallow = true;
705 mScheduler->disableHardwareVsync(kDisplayId1, kDisallow);
706 mScheduler->disableHardwareVsync(kDisplayId2, kDisallow);
707
708 static constexpr bool kAllowToEnable = true;
709 mScheduler->resyncAllToHardwareVsync(kAllowToEnable);
710}
711
712TEST_F(SchedulerTest, resyncAllLegacyAppliesToOffDisplays) FTL_FAKE_GUARD(kMainThreadContext) {
713 SET_FLAG_FOR_TEST(flags::multithreaded_present, false);
714
715 // In the legacy code, prior to the flag, resync applied to OFF displays.
716 EXPECT_CALL(mScheduler->mockRequestHardwareVsync, Call(kDisplayId1, true)).Times(1);
717 EXPECT_CALL(mScheduler->mockRequestHardwareVsync, Call(kDisplayId2, true)).Times(1);
718
719 mScheduler->setDisplayPowerMode(kDisplayId1, hal::PowerMode::ON);
720
721 mScheduler->registerDisplay(kDisplayId2,
722 std::make_shared<RefreshRateSelector>(kDisplay2Modes,
723 kDisplay2Mode60->getId()));
724 ASSERT_EQ(hal::PowerMode::OFF, mScheduler->getDisplayPowerMode(kDisplayId2));
725
726 static constexpr bool kDisallow = true;
727 mScheduler->disableHardwareVsync(kDisplayId1, kDisallow);
728 mScheduler->disableHardwareVsync(kDisplayId2, kDisallow);
729
730 static constexpr bool kAllowToEnable = true;
731 mScheduler->resyncAllToHardwareVsync(kAllowToEnable);
732}
733
Ady Abraham822ecbd2023-07-07 16:16:09 -0700734class AttachedChoreographerTest : public SchedulerTest {
735protected:
736 void frameRateTestScenario(Fps layerFps, int8_t frameRateCompatibility, Fps displayFps,
737 Fps expectedChoreographerFps);
738};
739
740TEST_F(AttachedChoreographerTest, registerSingle) {
741 EXPECT_TRUE(mScheduler->mutableAttachedChoreographers().empty());
742
743 const sp<MockLayer> layer = sp<MockLayer>::make(mFlinger.flinger());
744
745 EXPECT_CALL(mSchedulerCallback, onChoreographerAttached);
746 const sp<IDisplayEventConnection> connection =
Dominik Laskowski4babfc42024-02-16 12:28:40 -0500747 mScheduler->createDisplayEventConnection(Cycle::Render, {}, layer->getHandle());
Ady Abraham822ecbd2023-07-07 16:16:09 -0700748
749 EXPECT_EQ(1u, mScheduler->mutableAttachedChoreographers().size());
750 ASSERT_EQ(1u, mScheduler->mutableAttachedChoreographers().count(layer->getSequence()));
751 EXPECT_EQ(1u,
752 mScheduler->mutableAttachedChoreographers()[layer->getSequence()].connections.size());
753 EXPECT_FALSE(
754 mScheduler->mutableAttachedChoreographers()[layer->getSequence()].frameRate.isValid());
755}
756
757TEST_F(AttachedChoreographerTest, registerMultipleOnSameLayer) {
758 EXPECT_TRUE(mScheduler->mutableAttachedChoreographers().empty());
759
760 const sp<MockLayer> layer = sp<MockLayer>::make(mFlinger.flinger());
761 const auto handle = layer->getHandle();
762
763 EXPECT_CALL(mSchedulerCallback, onChoreographerAttached).Times(2);
764
765 EXPECT_CALL(*mEventThread, registerDisplayEventConnection(_))
766 .WillOnce(Return(0))
767 .WillOnce(Return(0));
768
769 const auto mockConnection1 = sp<MockEventThreadConnection>::make(mEventThread);
770 const auto mockConnection2 = sp<MockEventThreadConnection>::make(mEventThread);
771 EXPECT_CALL(*mEventThread, createEventConnection(_, _))
772 .WillOnce(Return(mockConnection1))
773 .WillOnce(Return(mockConnection2));
774
775 const sp<IDisplayEventConnection> connection1 =
Dominik Laskowski4babfc42024-02-16 12:28:40 -0500776 mScheduler->createDisplayEventConnection(Cycle::Render, {}, handle);
Ady Abraham822ecbd2023-07-07 16:16:09 -0700777 const sp<IDisplayEventConnection> connection2 =
Dominik Laskowski4babfc42024-02-16 12:28:40 -0500778 mScheduler->createDisplayEventConnection(Cycle::Render, {}, handle);
Ady Abraham822ecbd2023-07-07 16:16:09 -0700779
780 EXPECT_EQ(1u, mScheduler->mutableAttachedChoreographers().size());
781 ASSERT_EQ(1u, mScheduler->mutableAttachedChoreographers().count(layer->getSequence()));
782 EXPECT_EQ(2u,
783 mScheduler->mutableAttachedChoreographers()[layer->getSequence()].connections.size());
784 EXPECT_FALSE(
785 mScheduler->mutableAttachedChoreographers()[layer->getSequence()].frameRate.isValid());
786}
787
788TEST_F(AttachedChoreographerTest, registerMultipleOnDifferentLayers) {
789 EXPECT_TRUE(mScheduler->mutableAttachedChoreographers().empty());
790
791 const sp<MockLayer> layer1 = sp<MockLayer>::make(mFlinger.flinger());
792 const sp<MockLayer> layer2 = sp<MockLayer>::make(mFlinger.flinger());
793
794 EXPECT_CALL(mSchedulerCallback, onChoreographerAttached).Times(2);
795 const sp<IDisplayEventConnection> connection1 =
Dominik Laskowski4babfc42024-02-16 12:28:40 -0500796 mScheduler->createDisplayEventConnection(Cycle::Render, {}, layer1->getHandle());
Ady Abraham822ecbd2023-07-07 16:16:09 -0700797 const sp<IDisplayEventConnection> connection2 =
Dominik Laskowski4babfc42024-02-16 12:28:40 -0500798 mScheduler->createDisplayEventConnection(Cycle::Render, {}, layer2->getHandle());
Ady Abraham822ecbd2023-07-07 16:16:09 -0700799
800 EXPECT_EQ(2u, mScheduler->mutableAttachedChoreographers().size());
801
802 ASSERT_EQ(1u, mScheduler->mutableAttachedChoreographers().count(layer1->getSequence()));
803 EXPECT_EQ(1u,
804 mScheduler->mutableAttachedChoreographers()[layer1->getSequence()]
805 .connections.size());
806 EXPECT_FALSE(
807 mScheduler->mutableAttachedChoreographers()[layer1->getSequence()].frameRate.isValid());
808
809 ASSERT_EQ(1u, mScheduler->mutableAttachedChoreographers().count(layer2->getSequence()));
810 EXPECT_EQ(1u,
811 mScheduler->mutableAttachedChoreographers()[layer2->getSequence()]
812 .connections.size());
813 EXPECT_FALSE(
814 mScheduler->mutableAttachedChoreographers()[layer2->getSequence()].frameRate.isValid());
815}
816
817TEST_F(AttachedChoreographerTest, removedWhenConnectionIsGone) {
818 EXPECT_TRUE(mScheduler->mutableAttachedChoreographers().empty());
819
820 const sp<MockLayer> layer = sp<MockLayer>::make(mFlinger.flinger());
821
822 EXPECT_CALL(mSchedulerCallback, onChoreographerAttached);
823
824 sp<IDisplayEventConnection> connection =
Dominik Laskowski4babfc42024-02-16 12:28:40 -0500825 mScheduler->createDisplayEventConnection(Cycle::Render, {}, layer->getHandle());
Ady Abraham822ecbd2023-07-07 16:16:09 -0700826
827 ASSERT_EQ(1u, mScheduler->mutableAttachedChoreographers().count(layer->getSequence()));
828 EXPECT_EQ(1u,
829 mScheduler->mutableAttachedChoreographers()[layer->getSequence()].connections.size());
830
831 // The connection is used all over this test, so it is quite hard to release it from here.
832 // Instead, we just do a small shortcut.
833 {
834 EXPECT_CALL(*mEventThread, registerDisplayEventConnection(_)).WillOnce(Return(0));
835 sp<MockEventThreadConnection> mockConnection =
836 sp<MockEventThreadConnection>::make(mEventThread);
837 mScheduler->mutableAttachedChoreographers()[layer->getSequence()].connections.clear();
838 mScheduler->mutableAttachedChoreographers()[layer->getSequence()].connections.emplace(
839 mockConnection);
840 }
841
842 RequestedLayerState layerState(LayerCreationArgs(layer->getSequence()));
843 LayerHierarchy hierarchy(&layerState);
844 mScheduler->updateAttachedChoreographers(hierarchy, 60_Hz);
845 EXPECT_TRUE(mScheduler->mutableAttachedChoreographers().empty());
846}
847
848TEST_F(AttachedChoreographerTest, removedWhenLayerIsGone) {
849 EXPECT_TRUE(mScheduler->mutableAttachedChoreographers().empty());
850
851 sp<MockLayer> layer = sp<MockLayer>::make(mFlinger.flinger());
852
853 EXPECT_CALL(mSchedulerCallback, onChoreographerAttached);
854 const sp<IDisplayEventConnection> connection =
Dominik Laskowski4babfc42024-02-16 12:28:40 -0500855 mScheduler->createDisplayEventConnection(Cycle::Render, {}, layer->getHandle());
Ady Abraham822ecbd2023-07-07 16:16:09 -0700856
857 layer.clear();
858 mFlinger.mutableLayersPendingRemoval().clear();
859 EXPECT_TRUE(mScheduler->mutableAttachedChoreographers().empty());
860}
861
862void AttachedChoreographerTest::frameRateTestScenario(Fps layerFps, int8_t frameRateCompatibility,
863 Fps displayFps,
864 Fps expectedChoreographerFps) {
865 const sp<MockLayer> layer = sp<MockLayer>::make(mFlinger.flinger());
866
867 EXPECT_CALL(mSchedulerCallback, onChoreographerAttached);
868 sp<IDisplayEventConnection> connection =
Dominik Laskowski4babfc42024-02-16 12:28:40 -0500869 mScheduler->createDisplayEventConnection(Cycle::Render, {}, layer->getHandle());
Ady Abraham822ecbd2023-07-07 16:16:09 -0700870
871 RequestedLayerState layerState(LayerCreationArgs(layer->getSequence()));
872 LayerHierarchy hierarchy(&layerState);
873
874 layerState.frameRate = layerFps.getValue();
875 layerState.frameRateCompatibility = frameRateCompatibility;
876
877 mScheduler->updateAttachedChoreographers(hierarchy, displayFps);
878
879 ASSERT_EQ(1u, mScheduler->mutableAttachedChoreographers().count(layer->getSequence()));
880 EXPECT_EQ(expectedChoreographerFps,
881 mScheduler->mutableAttachedChoreographers()[layer->getSequence()].frameRate);
882 EXPECT_EQ(expectedChoreographerFps, mEventThreadConnection->frameRate);
883}
884
885TEST_F(AttachedChoreographerTest, setsFrameRateDefault) {
886 Fps layerFps = 30_Hz;
887 int8_t frameRateCompatibility = ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT;
888 Fps displayFps = 60_Hz;
889 Fps expectedChoreographerFps = 30_Hz;
890
891 frameRateTestScenario(layerFps, frameRateCompatibility, displayFps, expectedChoreographerFps);
892
893 layerFps = Fps::fromValue(32.7f);
894 frameRateTestScenario(layerFps, frameRateCompatibility, displayFps, expectedChoreographerFps);
895}
896
897TEST_F(AttachedChoreographerTest, setsFrameRateExact) {
898 Fps layerFps = 30_Hz;
899 int8_t frameRateCompatibility = ANATIVEWINDOW_FRAME_RATE_EXACT;
900 Fps displayFps = 60_Hz;
901 Fps expectedChoreographerFps = 30_Hz;
902
903 frameRateTestScenario(layerFps, frameRateCompatibility, displayFps, expectedChoreographerFps);
904
905 layerFps = Fps::fromValue(32.7f);
906 expectedChoreographerFps = {};
907 frameRateTestScenario(layerFps, frameRateCompatibility, displayFps, expectedChoreographerFps);
908}
909
910TEST_F(AttachedChoreographerTest, setsFrameRateExactOrMultiple) {
911 Fps layerFps = 30_Hz;
912 int8_t frameRateCompatibility = ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_FIXED_SOURCE;
913 Fps displayFps = 60_Hz;
914 Fps expectedChoreographerFps = 30_Hz;
915
916 frameRateTestScenario(layerFps, frameRateCompatibility, displayFps, expectedChoreographerFps);
917
918 layerFps = Fps::fromValue(32.7f);
919 expectedChoreographerFps = {};
920 frameRateTestScenario(layerFps, frameRateCompatibility, displayFps, expectedChoreographerFps);
921}
922
923TEST_F(AttachedChoreographerTest, setsFrameRateParent) {
924 const sp<MockLayer> layer = sp<MockLayer>::make(mFlinger.flinger());
925 const sp<MockLayer> parent = sp<MockLayer>::make(mFlinger.flinger());
926
927 EXPECT_CALL(mSchedulerCallback, onChoreographerAttached);
928 sp<IDisplayEventConnection> connection =
Dominik Laskowski4babfc42024-02-16 12:28:40 -0500929 mScheduler->createDisplayEventConnection(Cycle::Render, {}, parent->getHandle());
Ady Abraham822ecbd2023-07-07 16:16:09 -0700930
931 RequestedLayerState parentState(LayerCreationArgs(parent->getSequence()));
932 LayerHierarchy parentHierarchy(&parentState);
933
934 RequestedLayerState layerState(LayerCreationArgs(layer->getSequence()));
935 LayerHierarchy hierarchy(&layerState);
936 parentHierarchy.mChildren.push_back(
937 std::make_pair(&hierarchy, LayerHierarchy::Variant::Attached));
938
939 layerState.frameRate = (30_Hz).getValue();
940 layerState.frameRateCompatibility = ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT;
941
942 mScheduler->updateAttachedChoreographers(parentHierarchy, 120_Hz);
943
944 ASSERT_EQ(1u, mScheduler->mutableAttachedChoreographers().count(parent->getSequence()));
945
946 EXPECT_EQ(30_Hz, mScheduler->mutableAttachedChoreographers()[parent->getSequence()].frameRate);
947}
948
949TEST_F(AttachedChoreographerTest, setsFrameRateParent2Children) {
950 const sp<MockLayer> layer1 = sp<MockLayer>::make(mFlinger.flinger());
951 const sp<MockLayer> layer2 = sp<MockLayer>::make(mFlinger.flinger());
952 const sp<MockLayer> parent = sp<MockLayer>::make(mFlinger.flinger());
953
954 EXPECT_CALL(mSchedulerCallback, onChoreographerAttached);
955 sp<IDisplayEventConnection> connection =
Dominik Laskowski4babfc42024-02-16 12:28:40 -0500956 mScheduler->createDisplayEventConnection(Cycle::Render, {}, parent->getHandle());
Ady Abraham822ecbd2023-07-07 16:16:09 -0700957
958 RequestedLayerState parentState(LayerCreationArgs(parent->getSequence()));
959 LayerHierarchy parentHierarchy(&parentState);
960
961 RequestedLayerState layer1State(LayerCreationArgs(layer1->getSequence()));
962 LayerHierarchy layer1Hierarchy(&layer1State);
963 parentHierarchy.mChildren.push_back(
964 std::make_pair(&layer1Hierarchy, LayerHierarchy::Variant::Attached));
965
966 RequestedLayerState layer2State(LayerCreationArgs(layer1->getSequence()));
967 LayerHierarchy layer2Hierarchy(&layer2State);
968 parentHierarchy.mChildren.push_back(
969 std::make_pair(&layer2Hierarchy, LayerHierarchy::Variant::Attached));
970
971 layer1State.frameRate = (30_Hz).getValue();
972 layer1State.frameRateCompatibility = ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT;
973
974 layer2State.frameRate = (20_Hz).getValue();
975 layer2State.frameRateCompatibility = ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT;
976
977 mScheduler->updateAttachedChoreographers(parentHierarchy, 120_Hz);
978
979 ASSERT_EQ(1u, mScheduler->mutableAttachedChoreographers().count(parent->getSequence()));
980
981 EXPECT_EQ(60_Hz, mScheduler->mutableAttachedChoreographers()[parent->getSequence()].frameRate);
982}
983
984TEST_F(AttachedChoreographerTest, setsFrameRateParentConflictingChildren) {
985 const sp<MockLayer> layer1 = sp<MockLayer>::make(mFlinger.flinger());
986 const sp<MockLayer> layer2 = sp<MockLayer>::make(mFlinger.flinger());
987 const sp<MockLayer> parent = sp<MockLayer>::make(mFlinger.flinger());
988
989 EXPECT_CALL(mSchedulerCallback, onChoreographerAttached);
990 sp<IDisplayEventConnection> connection =
Dominik Laskowski4babfc42024-02-16 12:28:40 -0500991 mScheduler->createDisplayEventConnection(Cycle::Render, {}, parent->getHandle());
Ady Abraham822ecbd2023-07-07 16:16:09 -0700992
993 RequestedLayerState parentState(LayerCreationArgs(parent->getSequence()));
994 LayerHierarchy parentHierarchy(&parentState);
995
996 RequestedLayerState layer1State(LayerCreationArgs(layer1->getSequence()));
997 LayerHierarchy layer1Hierarchy(&layer1State);
998 parentHierarchy.mChildren.push_back(
999 std::make_pair(&layer1Hierarchy, LayerHierarchy::Variant::Attached));
1000
1001 RequestedLayerState layer2State(LayerCreationArgs(layer1->getSequence()));
1002 LayerHierarchy layer2Hierarchy(&layer2State);
1003 parentHierarchy.mChildren.push_back(
1004 std::make_pair(&layer2Hierarchy, LayerHierarchy::Variant::Attached));
1005
1006 layer1State.frameRate = (30_Hz).getValue();
1007 layer1State.frameRateCompatibility = ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT;
1008
1009 layer2State.frameRate = (25_Hz).getValue();
1010 layer2State.frameRateCompatibility = ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT;
1011
1012 mScheduler->updateAttachedChoreographers(parentHierarchy, 120_Hz);
1013
1014 ASSERT_EQ(1u, mScheduler->mutableAttachedChoreographers().count(parent->getSequence()));
1015
1016 EXPECT_EQ(Fps(), mScheduler->mutableAttachedChoreographers()[parent->getSequence()].frameRate);
1017}
1018
1019TEST_F(AttachedChoreographerTest, setsFrameRateChild) {
1020 const sp<MockLayer> layer = sp<MockLayer>::make(mFlinger.flinger());
1021 const sp<MockLayer> parent = sp<MockLayer>::make(mFlinger.flinger());
1022
1023 EXPECT_CALL(mSchedulerCallback, onChoreographerAttached);
1024 sp<IDisplayEventConnection> connection =
Dominik Laskowski4babfc42024-02-16 12:28:40 -05001025 mScheduler->createDisplayEventConnection(Cycle::Render, {}, layer->getHandle());
Ady Abraham822ecbd2023-07-07 16:16:09 -07001026
1027 RequestedLayerState parentState(LayerCreationArgs(parent->getSequence()));
1028 LayerHierarchy parentHierarchy(&parentState);
1029
1030 RequestedLayerState layerState(LayerCreationArgs(layer->getSequence()));
1031 LayerHierarchy hierarchy(&layerState);
1032 parentHierarchy.mChildren.push_back(
1033 std::make_pair(&hierarchy, LayerHierarchy::Variant::Attached));
1034
1035 parentState.frameRate = (30_Hz).getValue();
1036 parentState.frameRateCompatibility = ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT;
1037
1038 mScheduler->updateAttachedChoreographers(parentHierarchy, 120_Hz);
1039
1040 ASSERT_EQ(1u, mScheduler->mutableAttachedChoreographers().count(layer->getSequence()));
1041
1042 EXPECT_EQ(30_Hz, mScheduler->mutableAttachedChoreographers()[layer->getSequence()].frameRate);
1043}
1044
1045TEST_F(AttachedChoreographerTest, setsFrameRateChildNotOverriddenByParent) {
1046 const sp<MockLayer> layer = sp<MockLayer>::make(mFlinger.flinger());
1047 const sp<MockLayer> parent = sp<MockLayer>::make(mFlinger.flinger());
1048
1049 EXPECT_CALL(mSchedulerCallback, onChoreographerAttached);
1050 sp<IDisplayEventConnection> connection =
Dominik Laskowski4babfc42024-02-16 12:28:40 -05001051 mScheduler->createDisplayEventConnection(Cycle::Render, {}, layer->getHandle());
Ady Abraham822ecbd2023-07-07 16:16:09 -07001052
1053 RequestedLayerState parentState(LayerCreationArgs(parent->getSequence()));
1054 LayerHierarchy parentHierarchy(&parentState);
1055
1056 RequestedLayerState layerState(LayerCreationArgs(layer->getSequence()));
1057 LayerHierarchy hierarchy(&layerState);
1058 parentHierarchy.mChildren.push_back(
1059 std::make_pair(&hierarchy, LayerHierarchy::Variant::Attached));
1060
1061 parentState.frameRate = (30_Hz).getValue();
1062 parentState.frameRateCompatibility = ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT;
1063
1064 layerState.frameRate = (60_Hz).getValue();
1065 layerState.frameRateCompatibility = ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT;
1066
1067 mScheduler->updateAttachedChoreographers(parentHierarchy, 120_Hz);
1068
1069 ASSERT_EQ(1u, mScheduler->mutableAttachedChoreographers().count(layer->getSequence()));
1070
1071 EXPECT_EQ(60_Hz, mScheduler->mutableAttachedChoreographers()[layer->getSequence()].frameRate);
1072}
1073
Dominik Laskowski068173d2021-08-11 17:22:59 -07001074} // namespace android::scheduler