blob: fc54a8b74f812741bd3546452074491294529d29 [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>
37
ramindani0491e642023-11-16 17:42:14 -080038#include <com_android_graphics_surfaceflinger_flags.h>
Ady Abraham822ecbd2023-07-07 16:16:09 -070039#include "FpsOps.h"
40
ramindani0491e642023-11-16 17:42:14 -080041using namespace com::android::graphics::surfaceflinger;
42
Dominik Laskowski068173d2021-08-11 17:22:59 -070043namespace android::scheduler {
44
Dominik Laskowskib0054a22022-03-03 09:03:06 -080045using android::mock::createDisplayMode;
ramindani0491e642023-11-16 17:42:14 -080046using android::mock::createVrrDisplayMode;
Dominik Laskowskib0054a22022-03-03 09:03:06 -080047
Ana Krulec0c8cd522018-08-31 12:27:28 -070048using testing::_;
49using testing::Return;
50
Dominik Laskowski8b01cc02020-07-14 19:02:41 -070051namespace {
Ana Krulec0c8cd522018-08-31 12:27:28 -070052
Dominik Laskowski068173d2021-08-11 17:22:59 -070053using MockEventThread = android::mock::EventThread;
54using MockLayer = android::mock::MockLayer;
55
Ady Abraham822ecbd2023-07-07 16:16:09 -070056using LayerHierarchy = surfaceflinger::frontend::LayerHierarchy;
57using LayerHierarchyBuilder = surfaceflinger::frontend::LayerHierarchyBuilder;
58using RequestedLayerState = surfaceflinger::frontend::RequestedLayerState;
59
Ady Abraham77b4fb12024-03-05 17:51:53 -080060class ZeroClock : public Clock {
61public:
62 nsecs_t now() const override { return 0; }
63};
64
Ana Krulec0c8cd522018-08-31 12:27:28 -070065class SchedulerTest : public testing::Test {
66protected:
Ana Krulec85c39af2018-12-26 17:29:57 -080067 class MockEventThreadConnection : public android::EventThreadConnection {
Ana Krulec0c8cd522018-08-31 12:27:28 -070068 public:
Ana Krulec85c39af2018-12-26 17:29:57 -080069 explicit MockEventThreadConnection(EventThread* eventThread)
Ady Abrahamf2851612023-09-25 17:19:00 -070070 : EventThreadConnection(eventThread, /*callingUid*/ static_cast<uid_t>(0)) {}
Ana Krulec0c8cd522018-08-31 12:27:28 -070071 ~MockEventThreadConnection() = default;
72
Huihong Luo6fac5232021-11-22 16:05:23 -080073 MOCK_METHOD1(stealReceiveChannel, binder::Status(gui::BitTube* outChannel));
74 MOCK_METHOD1(setVsyncRate, binder::Status(int count));
75 MOCK_METHOD0(requestNextVsync, binder::Status());
Ana Krulec0c8cd522018-08-31 12:27:28 -070076 };
77
Ana Krulec0c8cd522018-08-31 12:27:28 -070078 SchedulerTest();
Ana Krulec0c8cd522018-08-31 12:27:28 -070079
Dominik Laskowski530d6bd2022-10-10 16:55:54 -040080 static constexpr PhysicalDisplayId kDisplayId1 = PhysicalDisplayId::fromPort(255u);
Ady Abrahamace3d052022-11-17 16:25:05 -080081 static inline const ftl::NonNull<DisplayModePtr> kDisplay1Mode60 =
82 ftl::as_non_null(createDisplayMode(kDisplayId1, DisplayModeId(0), 60_Hz));
83 static inline const ftl::NonNull<DisplayModePtr> kDisplay1Mode120 =
84 ftl::as_non_null(createDisplayMode(kDisplayId1, DisplayModeId(1), 120_Hz));
Dominik Laskowski530d6bd2022-10-10 16:55:54 -040085 static inline const DisplayModes kDisplay1Modes = makeModes(kDisplay1Mode60, kDisplay1Mode120);
86
87 static constexpr PhysicalDisplayId kDisplayId2 = PhysicalDisplayId::fromPort(254u);
Ady Abrahamace3d052022-11-17 16:25:05 -080088 static inline const ftl::NonNull<DisplayModePtr> kDisplay2Mode60 =
89 ftl::as_non_null(createDisplayMode(kDisplayId2, DisplayModeId(0), 60_Hz));
90 static inline const ftl::NonNull<DisplayModePtr> kDisplay2Mode120 =
91 ftl::as_non_null(createDisplayMode(kDisplayId2, DisplayModeId(1), 120_Hz));
Dominik Laskowski530d6bd2022-10-10 16:55:54 -040092 static inline const DisplayModes kDisplay2Modes = makeModes(kDisplay2Mode60, kDisplay2Mode120);
93
94 static constexpr PhysicalDisplayId kDisplayId3 = PhysicalDisplayId::fromPort(253u);
Ady Abrahamace3d052022-11-17 16:25:05 -080095 static inline const ftl::NonNull<DisplayModePtr> kDisplay3Mode60 =
96 ftl::as_non_null(createDisplayMode(kDisplayId3, DisplayModeId(0), 60_Hz));
Dominik Laskowski530d6bd2022-10-10 16:55:54 -040097 static inline const DisplayModes kDisplay3Modes = makeModes(kDisplay3Mode60);
Marin Shalamanov2cde1002021-06-08 19:50:10 +020098
Dominik Laskowskid82e0f02022-10-26 15:23:04 -040099 std::shared_ptr<RefreshRateSelector> mSelector =
100 std::make_shared<RefreshRateSelector>(makeModes(kDisplay1Mode60),
101 kDisplay1Mode60->getId());
Dominik Laskowski983f2b52020-06-25 16:54:06 -0700102
Dominik Laskowski8b01cc02020-07-14 19:02:41 -0700103 mock::SchedulerCallback mSchedulerCallback;
Leon Scroggins III823d4ca2023-12-12 16:57:34 -0500104 TestableSurfaceFlinger mFlinger;
ramindaniae645822024-01-11 10:57:29 -0800105 TestableScheduler* mScheduler = new TestableScheduler{mSelector, mFlinger, mSchedulerCallback};
Vishnu Naira0292282023-12-16 14:32:00 -0800106 surfaceflinger::frontend::LayerHierarchyBuilder mLayerHierarchyBuilder;
Dominik Laskowski98041832019-08-01 18:35:59 -0700107
Dominik Laskowski068173d2021-08-11 17:22:59 -0700108 MockEventThread* mEventThread;
Ana Krulec0c8cd522018-08-31 12:27:28 -0700109 sp<MockEventThreadConnection> mEventThreadConnection;
Ana Krulec0c8cd522018-08-31 12:27:28 -0700110};
111
112SchedulerTest::SchedulerTest() {
Dominik Laskowski068173d2021-08-11 17:22:59 -0700113 auto eventThread = std::make_unique<MockEventThread>();
Ana Krulec0c8cd522018-08-31 12:27:28 -0700114 mEventThread = eventThread.get();
Ana Krulec85c39af2018-12-26 17:29:57 -0800115 EXPECT_CALL(*mEventThread, registerDisplayEventConnection(_)).WillOnce(Return(0));
116
Ady Abrahamd11bade2022-08-01 16:18:03 -0700117 mEventThreadConnection = sp<MockEventThreadConnection>::make(mEventThread);
Ana Krulec0c8cd522018-08-31 12:27:28 -0700118
119 // createConnection call to scheduler makes a createEventConnection call to EventThread. Make
120 // sure that call gets executed and returns an EventThread::Connection object.
Ady Abraham0f4a1b12019-06-04 16:04:04 -0700121 EXPECT_CALL(*mEventThread, createEventConnection(_, _))
Ana Krulec0c8cd522018-08-31 12:27:28 -0700122 .WillRepeatedly(Return(mEventThreadConnection));
123
Dominik Laskowski4babfc42024-02-16 12:28:40 -0500124 mScheduler->setEventThread(Cycle::Render, std::move(eventThread));
Ady Abrahama0a16272021-03-03 15:23:35 -0800125
126 mFlinger.resetScheduler(mScheduler);
Ana Krulec0c8cd522018-08-31 12:27:28 -0700127}
128
Dominik Laskowski8b01cc02020-07-14 19:02:41 -0700129} // namespace
Ana Krulec0c8cd522018-08-31 12:27:28 -0700130
Dominik Laskowski66295432023-03-14 12:25:36 -0400131TEST_F(SchedulerTest, registerDisplay) FTL_FAKE_GUARD(kMainThreadContext) {
Dominik Laskowski008bec02023-03-14 12:04:58 -0400132 // Hardware VSYNC should not change if the display is already registered.
Dominik Laskowski66295432023-03-14 12:25:36 -0400133 EXPECT_CALL(mSchedulerCallback, requestHardwareVsync(kDisplayId1, false)).Times(0);
Dominik Laskowski008bec02023-03-14 12:04:58 -0400134 mScheduler->registerDisplay(kDisplayId1,
135 std::make_shared<RefreshRateSelector>(kDisplay1Modes,
136 kDisplay1Mode60->getId()));
137
Dominik Laskowski66295432023-03-14 12:25:36 -0400138 // TODO(b/241285191): Restore once VsyncSchedule::getPendingHardwareVsyncState is called by
139 // Scheduler::setDisplayPowerMode rather than SF::setPowerModeInternal.
140#if 0
Dominik Laskowski008bec02023-03-14 12:04:58 -0400141 // Hardware VSYNC should be disabled for newly registered displays.
Dominik Laskowski66295432023-03-14 12:25:36 -0400142 EXPECT_CALL(mSchedulerCallback, requestHardwareVsync(kDisplayId2, false)).Times(1);
143 EXPECT_CALL(mSchedulerCallback, requestHardwareVsync(kDisplayId3, false)).Times(1);
144#endif
Dominik Laskowski008bec02023-03-14 12:04:58 -0400145
146 mScheduler->registerDisplay(kDisplayId2,
147 std::make_shared<RefreshRateSelector>(kDisplay2Modes,
148 kDisplay2Mode60->getId()));
149 mScheduler->registerDisplay(kDisplayId3,
150 std::make_shared<RefreshRateSelector>(kDisplay3Modes,
151 kDisplay3Mode60->getId()));
Dominik Laskowski66295432023-03-14 12:25:36 -0400152
153 EXPECT_FALSE(mScheduler->getVsyncSchedule(kDisplayId1)->getPendingHardwareVsyncState());
154 EXPECT_FALSE(mScheduler->getVsyncSchedule(kDisplayId2)->getPendingHardwareVsyncState());
155 EXPECT_FALSE(mScheduler->getVsyncSchedule(kDisplayId3)->getPendingHardwareVsyncState());
Dominik Laskowski008bec02023-03-14 12:04:58 -0400156}
157
Marin Shalamanov2cde1002021-06-08 19:50:10 +0200158TEST_F(SchedulerTest, chooseRefreshRateForContentIsNoopWhenModeSwitchingIsNotSupported) {
159 // The layer is registered at creation time and deregistered at destruction time.
Dominik Laskowski068173d2021-08-11 17:22:59 -0700160 sp<MockLayer> layer = sp<MockLayer>::make(mFlinger.flinger());
Dominik Laskowski983f2b52020-06-25 16:54:06 -0700161
Marin Shalamanov2cde1002021-06-08 19:50:10 +0200162 // recordLayerHistory should be a noop
Dominik Laskowski9c93d602021-10-07 19:38:26 -0700163 ASSERT_EQ(0u, mScheduler->getNumActiveLayers());
Vishnu Nair47b7bb42023-09-29 16:27:33 -0700164 mScheduler->recordLayerHistory(layer->getSequence(), layer->getLayerProps(), 0, 0,
Vishnu Nairef68d6d2023-02-28 06:18:27 +0000165 LayerHistory::LayerUpdateType::Buffer);
Dominik Laskowski9c93d602021-10-07 19:38:26 -0700166 ASSERT_EQ(0u, mScheduler->getNumActiveLayers());
Dominik Laskowski983f2b52020-06-25 16:54:06 -0700167
Rachel Lee6a9731d2022-06-06 17:08:14 -0700168 constexpr hal::PowerMode kPowerModeOn = hal::PowerMode::ON;
Leon Scroggins III67388622023-02-06 20:36:20 -0500169 FTL_FAKE_GUARD(kMainThreadContext, mScheduler->setDisplayPowerMode(kDisplayId1, kPowerModeOn));
Dominik Laskowski983f2b52020-06-25 16:54:06 -0700170
171 constexpr uint32_t kDisplayArea = 999'999;
Ady Abrahamed3290f2021-05-17 15:12:14 -0700172 mScheduler->onActiveDisplayAreaChanged(kDisplayArea);
Dominik Laskowski983f2b52020-06-25 16:54:06 -0700173
ramindani69b58e82022-09-26 16:48:36 -0700174 EXPECT_CALL(mSchedulerCallback, requestDisplayModes(_)).Times(0);
Ady Abraham822ecbd2023-07-07 16:16:09 -0700175 mScheduler->chooseRefreshRateForContent(/*LayerHierarchy*/ nullptr,
176 /*updateAttachedChoreographer*/ false);
Dominik Laskowski983f2b52020-06-25 16:54:06 -0700177}
178
Marin Shalamanov2cde1002021-06-08 19:50:10 +0200179TEST_F(SchedulerTest, updateDisplayModes) {
Dominik Laskowski9c93d602021-10-07 19:38:26 -0700180 ASSERT_EQ(0u, mScheduler->layerHistorySize());
Dominik Laskowski068173d2021-08-11 17:22:59 -0700181 sp<MockLayer> layer = sp<MockLayer>::make(mFlinger.flinger());
Dominik Laskowski9c93d602021-10-07 19:38:26 -0700182 ASSERT_EQ(1u, mScheduler->layerHistorySize());
Marin Shalamanov2cde1002021-06-08 19:50:10 +0200183
Dominik Laskowski596a2562022-10-28 11:26:12 -0400184 // Replace `mSelector` with a new `RefreshRateSelector` that has different display modes.
185 mScheduler->registerDisplay(kDisplayId1,
186 std::make_shared<RefreshRateSelector>(kDisplay1Modes,
187 kDisplay1Mode60->getId()));
Marin Shalamanov2cde1002021-06-08 19:50:10 +0200188
Dominik Laskowski9c93d602021-10-07 19:38:26 -0700189 ASSERT_EQ(0u, mScheduler->getNumActiveLayers());
Vishnu Nair47b7bb42023-09-29 16:27:33 -0700190 mScheduler->recordLayerHistory(layer->getSequence(), layer->getLayerProps(), 0, 0,
Vishnu Nairef68d6d2023-02-28 06:18:27 +0000191 LayerHistory::LayerUpdateType::Buffer);
Dominik Laskowski9c93d602021-10-07 19:38:26 -0700192 ASSERT_EQ(1u, mScheduler->getNumActiveLayers());
Marin Shalamanov2cde1002021-06-08 19:50:10 +0200193}
194
Dominik Laskowski068173d2021-08-11 17:22:59 -0700195TEST_F(SchedulerTest, dispatchCachedReportedMode) {
196 mScheduler->clearCachedReportedMode();
197
Ady Abraham690f4612021-07-01 23:24:03 -0700198 EXPECT_CALL(*mEventThread, onModeChanged(_)).Times(0);
Dominik Laskowski068173d2021-08-11 17:22:59 -0700199 EXPECT_NO_FATAL_FAILURE(mScheduler->dispatchCachedReportedMode());
Ana Krulec6ddd2612020-09-24 13:06:33 -0700200}
201
Ady Abraham899dcdb2021-06-15 16:56:21 -0700202TEST_F(SchedulerTest, calculateMaxAcquiredBufferCount) {
Dominik Laskowski6eab42d2021-09-13 14:34:13 -0700203 EXPECT_EQ(1, mFlinger.calculateMaxAcquiredBufferCount(60_Hz, 30ms));
204 EXPECT_EQ(2, mFlinger.calculateMaxAcquiredBufferCount(90_Hz, 30ms));
205 EXPECT_EQ(3, mFlinger.calculateMaxAcquiredBufferCount(120_Hz, 30ms));
Ady Abraham564f9de2021-02-03 18:34:33 -0800206
Dominik Laskowski6eab42d2021-09-13 14:34:13 -0700207 EXPECT_EQ(2, mFlinger.calculateMaxAcquiredBufferCount(60_Hz, 40ms));
Ady Abraham564f9de2021-02-03 18:34:33 -0800208
Dominik Laskowski6eab42d2021-09-13 14:34:13 -0700209 EXPECT_EQ(1, mFlinger.calculateMaxAcquiredBufferCount(60_Hz, 10ms));
Lloyd Piquea1456c12023-05-17 12:11:15 -0700210
Lloyd Pique30db6402023-06-26 18:56:51 +0000211 const auto savedMinAcquiredBuffers = mFlinger.mutableMinAcquiredBuffers();
212 mFlinger.mutableMinAcquiredBuffers() = 2;
Lloyd Piquea1456c12023-05-17 12:11:15 -0700213 EXPECT_EQ(2, mFlinger.calculateMaxAcquiredBufferCount(60_Hz, 10ms));
Lloyd Pique30db6402023-06-26 18:56:51 +0000214 mFlinger.mutableMinAcquiredBuffers() = savedMinAcquiredBuffers;
Ady Abraham564f9de2021-02-03 18:34:33 -0800215}
216
Marin Shalamanov4c7831e2021-06-08 20:44:06 +0200217MATCHER(Is120Hz, "") {
Ady Abrahamace3d052022-11-17 16:25:05 -0800218 return isApproxEqual(arg.front().mode.fps, 120_Hz);
Marin Shalamanov4c7831e2021-06-08 20:44:06 +0200219}
220
221TEST_F(SchedulerTest, chooseRefreshRateForContentSelectsMaxRefreshRate) {
Dominik Laskowski596a2562022-10-28 11:26:12 -0400222 mScheduler->registerDisplay(kDisplayId1,
223 std::make_shared<RefreshRateSelector>(kDisplay1Modes,
224 kDisplay1Mode60->getId()));
Marin Shalamanov4c7831e2021-06-08 20:44:06 +0200225
Dominik Laskowski0c41ffa2021-12-24 16:45:12 -0800226 const sp<MockLayer> layer = sp<MockLayer>::make(mFlinger.flinger());
227 EXPECT_CALL(*layer, isVisible()).WillOnce(Return(true));
Marin Shalamanov4c7831e2021-06-08 20:44:06 +0200228
Vishnu Nair47b7bb42023-09-29 16:27:33 -0700229 mScheduler->recordLayerHistory(layer->getSequence(), layer->getLayerProps(), 0, systemTime(),
Vishnu Nairef68d6d2023-02-28 06:18:27 +0000230 LayerHistory::LayerUpdateType::Buffer);
Marin Shalamanov4c7831e2021-06-08 20:44:06 +0200231
Rachel Lee6a9731d2022-06-06 17:08:14 -0700232 constexpr hal::PowerMode kPowerModeOn = hal::PowerMode::ON;
Leon Scroggins III67388622023-02-06 20:36:20 -0500233 FTL_FAKE_GUARD(kMainThreadContext, mScheduler->setDisplayPowerMode(kDisplayId1, kPowerModeOn));
Marin Shalamanov4c7831e2021-06-08 20:44:06 +0200234
235 constexpr uint32_t kDisplayArea = 999'999;
Ady Abrahamed3290f2021-05-17 15:12:14 -0700236 mScheduler->onActiveDisplayAreaChanged(kDisplayArea);
Marin Shalamanov4c7831e2021-06-08 20:44:06 +0200237
ramindani69b58e82022-09-26 16:48:36 -0700238 EXPECT_CALL(mSchedulerCallback, requestDisplayModes(Is120Hz())).Times(1);
Ady Abraham822ecbd2023-07-07 16:16:09 -0700239 mScheduler->chooseRefreshRateForContent(/*LayerHierarchy*/ nullptr,
240 /*updateAttachedChoreographer*/ false);
Dominik Laskowski0c41ffa2021-12-24 16:45:12 -0800241
242 // No-op if layer requirements have not changed.
ramindani69b58e82022-09-26 16:48:36 -0700243 EXPECT_CALL(mSchedulerCallback, requestDisplayModes(_)).Times(0);
Ady Abraham822ecbd2023-07-07 16:16:09 -0700244 mScheduler->chooseRefreshRateForContent(/*LayerHierarchy*/ nullptr,
245 /*updateAttachedChoreographer*/ false);
Marin Shalamanov4c7831e2021-06-08 20:44:06 +0200246}
247
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400248TEST_F(SchedulerTest, chooseDisplayModesSingleDisplay) {
Dominik Laskowskib5a094b2022-10-27 12:00:12 -0400249 mScheduler->registerDisplay(kDisplayId1,
250 std::make_shared<RefreshRateSelector>(kDisplay1Modes,
251 kDisplay1Mode60->getId()));
ramindani69b58e82022-09-26 16:48:36 -0700252
Dominik Laskowskid82e0f02022-10-26 15:23:04 -0400253 std::vector<RefreshRateSelector::LayerRequirement> layers =
254 std::vector<RefreshRateSelector::LayerRequirement>({{.weight = 1.f}, {.weight = 1.f}});
ramindani69b58e82022-09-26 16:48:36 -0700255 mScheduler->setContentRequirements(layers);
256 GlobalSignals globalSignals = {.idle = true};
257 mScheduler->setTouchStateAndIdleTimerPolicy(globalSignals);
258
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400259 using DisplayModeChoice = TestableScheduler::DisplayModeChoice;
260
261 auto modeChoices = mScheduler->chooseDisplayModes();
262 ASSERT_EQ(1u, modeChoices.size());
263
264 auto choice = modeChoices.get(kDisplayId1);
265 ASSERT_TRUE(choice);
Ady Abrahamace3d052022-11-17 16:25:05 -0800266 EXPECT_EQ(choice->get(), DisplayModeChoice({60_Hz, kDisplay1Mode60}, globalSignals));
ramindani69b58e82022-09-26 16:48:36 -0700267
268 globalSignals = {.idle = false};
269 mScheduler->setTouchStateAndIdleTimerPolicy(globalSignals);
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400270
271 modeChoices = mScheduler->chooseDisplayModes();
272 ASSERT_EQ(1u, modeChoices.size());
273
274 choice = modeChoices.get(kDisplayId1);
275 ASSERT_TRUE(choice);
Ady Abrahamace3d052022-11-17 16:25:05 -0800276 EXPECT_EQ(choice->get(), DisplayModeChoice({120_Hz, kDisplay1Mode120}, globalSignals));
ramindani69b58e82022-09-26 16:48:36 -0700277
278 globalSignals = {.touch = true};
279 mScheduler->replaceTouchTimer(10);
280 mScheduler->setTouchStateAndIdleTimerPolicy(globalSignals);
ramindani69b58e82022-09-26 16:48:36 -0700281
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400282 modeChoices = mScheduler->chooseDisplayModes();
283 ASSERT_EQ(1u, modeChoices.size());
284
285 choice = modeChoices.get(kDisplayId1);
286 ASSERT_TRUE(choice);
Ady Abrahamace3d052022-11-17 16:25:05 -0800287 EXPECT_EQ(choice->get(), DisplayModeChoice({120_Hz, kDisplay1Mode120}, globalSignals));
ramindani69b58e82022-09-26 16:48:36 -0700288}
289
Rachel Lee6ed96c92024-02-07 14:37:38 -0800290TEST_F(SchedulerTest, chooseDisplayModesSingleDisplayHighHintTouchSignal) {
291 mScheduler->registerDisplay(kDisplayId1,
292 std::make_shared<RefreshRateSelector>(kDisplay1Modes,
293 kDisplay1Mode60->getId()));
294
295 using DisplayModeChoice = TestableScheduler::DisplayModeChoice;
296
297 std::vector<RefreshRateSelector::LayerRequirement> layers =
298 std::vector<RefreshRateSelector::LayerRequirement>({{.weight = 1.f}, {.weight = 1.f}});
299 auto& lr1 = layers[0];
300 auto& lr2 = layers[1];
301
302 // Scenario that is similar to game. Expects no touch boost.
303 lr1.vote = RefreshRateSelector::LayerVoteType::ExplicitCategory;
304 lr1.frameRateCategory = FrameRateCategory::HighHint;
305 lr1.name = "ExplicitCategory HighHint";
306 lr2.vote = RefreshRateSelector::LayerVoteType::ExplicitDefault;
307 lr2.desiredRefreshRate = 30_Hz;
308 lr2.name = "30Hz ExplicitDefault";
309 mScheduler->setContentRequirements(layers);
310 auto modeChoices = mScheduler->chooseDisplayModes();
311 ASSERT_EQ(1u, modeChoices.size());
312 auto choice = modeChoices.get(kDisplayId1);
313 ASSERT_TRUE(choice);
314 EXPECT_EQ(choice->get(), DisplayModeChoice({60_Hz, kDisplay1Mode60}, {.touch = false}));
315
316 // Scenario that is similar to video playback and interaction. Expects touch boost.
317 lr1.vote = RefreshRateSelector::LayerVoteType::ExplicitCategory;
318 lr1.frameRateCategory = FrameRateCategory::HighHint;
319 lr1.name = "ExplicitCategory HighHint";
320 lr2.vote = RefreshRateSelector::LayerVoteType::ExplicitExactOrMultiple;
321 lr2.desiredRefreshRate = 30_Hz;
322 lr2.name = "30Hz ExplicitExactOrMultiple";
323 mScheduler->setContentRequirements(layers);
324 modeChoices = mScheduler->chooseDisplayModes();
325 ASSERT_EQ(1u, modeChoices.size());
326 choice = modeChoices.get(kDisplayId1);
327 ASSERT_TRUE(choice);
328 EXPECT_EQ(choice->get(), DisplayModeChoice({120_Hz, kDisplay1Mode120}, {.touch = true}));
329
330 // Scenario with explicit category and HighHint. Expects touch boost.
331 lr1.vote = RefreshRateSelector::LayerVoteType::ExplicitCategory;
332 lr1.frameRateCategory = FrameRateCategory::HighHint;
333 lr1.name = "ExplicitCategory HighHint";
334 lr2.vote = RefreshRateSelector::LayerVoteType::ExplicitCategory;
335 lr2.frameRateCategory = FrameRateCategory::Low;
336 lr2.name = "ExplicitCategory Low";
337 mScheduler->setContentRequirements(layers);
338 modeChoices = mScheduler->chooseDisplayModes();
339 ASSERT_EQ(1u, modeChoices.size());
340 choice = modeChoices.get(kDisplayId1);
341 ASSERT_TRUE(choice);
342 EXPECT_EQ(choice->get(), DisplayModeChoice({120_Hz, kDisplay1Mode120}, {.touch = true}));
343}
344
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400345TEST_F(SchedulerTest, chooseDisplayModesMultipleDisplays) {
Dominik Laskowski3ff44c72024-06-17 11:03:30 -0400346 constexpr PhysicalDisplayId kActiveDisplayId = kDisplayId1;
Dominik Laskowskib5a094b2022-10-27 12:00:12 -0400347 mScheduler->registerDisplay(kDisplayId1,
348 std::make_shared<RefreshRateSelector>(kDisplay1Modes,
Dominik Laskowski3ff44c72024-06-17 11:03:30 -0400349 kDisplay1Mode60->getId()),
350 kActiveDisplayId);
Dominik Laskowskib5a094b2022-10-27 12:00:12 -0400351 mScheduler->registerDisplay(kDisplayId2,
352 std::make_shared<RefreshRateSelector>(kDisplay2Modes,
Dominik Laskowski3ff44c72024-06-17 11:03:30 -0400353 kDisplay2Mode60->getId()),
354 kActiveDisplayId);
ramindani69b58e82022-09-26 16:48:36 -0700355
Dominik Laskowski086507b2024-05-16 15:33:16 -0400356 mScheduler->setDisplayPowerMode(kDisplayId1, hal::PowerMode::ON);
357 mScheduler->setDisplayPowerMode(kDisplayId2, hal::PowerMode::ON);
358
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400359 using DisplayModeChoice = TestableScheduler::DisplayModeChoice;
360 TestableScheduler::DisplayModeChoiceMap expectedChoices;
ramindani69b58e82022-09-26 16:48:36 -0700361
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400362 {
363 const GlobalSignals globalSignals = {.idle = true};
364 expectedChoices =
365 ftl::init::map<const PhysicalDisplayId&,
Ady Abrahamace3d052022-11-17 16:25:05 -0800366 DisplayModeChoice>(kDisplayId1,
367 FrameRateMode{60_Hz, kDisplay1Mode60},
368 globalSignals)(kDisplayId2,
369 FrameRateMode{60_Hz,
370 kDisplay2Mode60},
Dominik Laskowski9e88d622024-03-06 17:42:39 -0500371 GlobalSignals{});
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400372
Dominik Laskowskid82e0f02022-10-26 15:23:04 -0400373 std::vector<RefreshRateSelector::LayerRequirement> layers = {{.weight = 1.f},
374 {.weight = 1.f}};
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400375 mScheduler->setContentRequirements(layers);
376 mScheduler->setTouchStateAndIdleTimerPolicy(globalSignals);
377
378 const auto actualChoices = mScheduler->chooseDisplayModes();
379 EXPECT_EQ(expectedChoices, actualChoices);
ramindani69b58e82022-09-26 16:48:36 -0700380 }
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400381 {
382 const GlobalSignals globalSignals = {.idle = false};
383 expectedChoices =
384 ftl::init::map<const PhysicalDisplayId&,
Ady Abrahamace3d052022-11-17 16:25:05 -0800385 DisplayModeChoice>(kDisplayId1,
386 FrameRateMode{120_Hz, kDisplay1Mode120},
387 globalSignals)(kDisplayId2,
388 FrameRateMode{120_Hz,
389 kDisplay2Mode120},
Dominik Laskowski9e88d622024-03-06 17:42:39 -0500390 GlobalSignals{});
ramindani69b58e82022-09-26 16:48:36 -0700391
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400392 mScheduler->setTouchStateAndIdleTimerPolicy(globalSignals);
ramindani69b58e82022-09-26 16:48:36 -0700393
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400394 const auto actualChoices = mScheduler->chooseDisplayModes();
395 EXPECT_EQ(expectedChoices, actualChoices);
ramindani69b58e82022-09-26 16:48:36 -0700396 }
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400397 {
398 const GlobalSignals globalSignals = {.touch = true};
399 mScheduler->replaceTouchTimer(10);
400 mScheduler->setTouchStateAndIdleTimerPolicy(globalSignals);
ramindani69b58e82022-09-26 16:48:36 -0700401
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400402 expectedChoices =
403 ftl::init::map<const PhysicalDisplayId&,
Ady Abrahamace3d052022-11-17 16:25:05 -0800404 DisplayModeChoice>(kDisplayId1,
405 FrameRateMode{120_Hz, kDisplay1Mode120},
406 globalSignals)(kDisplayId2,
407 FrameRateMode{120_Hz,
408 kDisplay2Mode120},
Dominik Laskowski9e88d622024-03-06 17:42:39 -0500409 GlobalSignals{});
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400410
411 const auto actualChoices = mScheduler->chooseDisplayModes();
412 EXPECT_EQ(expectedChoices, actualChoices);
ramindani69b58e82022-09-26 16:48:36 -0700413 }
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400414 {
ramindani22f2ead2023-04-21 10:27:11 -0700415 // The kDisplayId3 does not support 120Hz, The pacesetter display rate is chosen to be 120
416 // Hz. In this case only the display kDisplayId3 choose 60Hz as it does not support 120Hz.
Dominik Laskowski3ff44c72024-06-17 11:03:30 -0400417 mScheduler->registerDisplay(kDisplayId3,
418 std::make_shared<RefreshRateSelector>(kDisplay3Modes,
419 kDisplay3Mode60->getId()),
420 kActiveDisplayId);
Dominik Laskowski086507b2024-05-16 15:33:16 -0400421 mScheduler->setDisplayPowerMode(kDisplayId3, hal::PowerMode::ON);
Dominik Laskowski327d6092022-10-11 18:05:08 -0400422
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400423 const GlobalSignals globalSignals = {.touch = true};
424 mScheduler->replaceTouchTimer(10);
425 mScheduler->setTouchStateAndIdleTimerPolicy(globalSignals);
ramindani7c487282022-10-10 16:17:51 -0700426
Ady Abrahamace3d052022-11-17 16:25:05 -0800427 expectedChoices = ftl::init::map<
428 const PhysicalDisplayId&,
ramindani22f2ead2023-04-21 10:27:11 -0700429 DisplayModeChoice>(kDisplayId1, FrameRateMode{120_Hz, kDisplay1Mode120},
430 globalSignals)(kDisplayId2,
431 FrameRateMode{120_Hz, kDisplay2Mode120},
Dominik Laskowski9e88d622024-03-06 17:42:39 -0500432 GlobalSignals{})(kDisplayId3,
433 FrameRateMode{60_Hz,
434 kDisplay3Mode60},
435 GlobalSignals{});
ramindani22f2ead2023-04-21 10:27:11 -0700436
437 const auto actualChoices = mScheduler->chooseDisplayModes();
438 EXPECT_EQ(expectedChoices, actualChoices);
439 }
440 {
441 // We should choose 60Hz despite the touch signal as pacesetter only supports 60Hz
442 mScheduler->setPacesetterDisplay(kDisplayId3);
443 const GlobalSignals globalSignals = {.touch = true};
444 mScheduler->replaceTouchTimer(10);
445 mScheduler->setTouchStateAndIdleTimerPolicy(globalSignals);
446
447 expectedChoices = ftl::init::map<
448 const PhysicalDisplayId&,
Ady Abrahamace3d052022-11-17 16:25:05 -0800449 DisplayModeChoice>(kDisplayId1, FrameRateMode{60_Hz, kDisplay1Mode60},
Dominik Laskowski9e88d622024-03-06 17:42:39 -0500450 GlobalSignals{})(kDisplayId2,
451 FrameRateMode{60_Hz, kDisplay2Mode60},
452 GlobalSignals{})(kDisplayId3,
453 FrameRateMode{60_Hz,
454 kDisplay3Mode60},
455 globalSignals);
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400456
457 const auto actualChoices = mScheduler->chooseDisplayModes();
458 EXPECT_EQ(expectedChoices, actualChoices);
ramindani7c487282022-10-10 16:17:51 -0700459 }
ramindani69b58e82022-09-26 16:48:36 -0700460}
461
Dominik Laskowski50e2e4d2023-10-04 10:58:28 -0400462TEST_F(SchedulerTest, onFrameSignalMultipleDisplays) {
Dominik Laskowski3ff44c72024-06-17 11:03:30 -0400463 constexpr PhysicalDisplayId kActiveDisplayId = kDisplayId1;
Dominik Laskowski50e2e4d2023-10-04 10:58:28 -0400464 mScheduler->registerDisplay(kDisplayId1,
465 std::make_shared<RefreshRateSelector>(kDisplay1Modes,
Dominik Laskowski3ff44c72024-06-17 11:03:30 -0400466 kDisplay1Mode60->getId()),
467 kActiveDisplayId);
Dominik Laskowski50e2e4d2023-10-04 10:58:28 -0400468 mScheduler->registerDisplay(kDisplayId2,
469 std::make_shared<RefreshRateSelector>(kDisplay2Modes,
Dominik Laskowski3ff44c72024-06-17 11:03:30 -0400470 kDisplay2Mode60->getId()),
471 kActiveDisplayId);
Dominik Laskowski50e2e4d2023-10-04 10:58:28 -0400472
473 using VsyncIds = std::vector<std::pair<PhysicalDisplayId, VsyncId>>;
474
475 struct Compositor final : ICompositor {
Dominik Laskowskifb4b7372023-11-22 09:56:54 -0500476 explicit Compositor(TestableScheduler& scheduler) : scheduler(scheduler) {}
477
478 TestableScheduler& scheduler;
479
480 struct {
481 PhysicalDisplayId commit;
482 PhysicalDisplayId composite;
483 } pacesetterIds;
484
485 struct {
486 VsyncIds commit;
487 VsyncIds composite;
488 } vsyncIds;
489
Dominik Laskowski50e2e4d2023-10-04 10:58:28 -0400490 bool committed = true;
Dominik Laskowskifb4b7372023-11-22 09:56:54 -0500491 bool changePacesetter = false;
Dominik Laskowski50e2e4d2023-10-04 10:58:28 -0400492
493 void configure() override {}
494
Dominik Laskowskifb4b7372023-11-22 09:56:54 -0500495 bool commit(PhysicalDisplayId pacesetterId,
496 const scheduler::FrameTargets& targets) override {
497 pacesetterIds.commit = pacesetterId;
498
499 vsyncIds.commit.clear();
500 vsyncIds.composite.clear();
Dominik Laskowski50e2e4d2023-10-04 10:58:28 -0400501
502 for (const auto& [id, target] : targets) {
Dominik Laskowskifb4b7372023-11-22 09:56:54 -0500503 vsyncIds.commit.emplace_back(id, target->vsyncId());
504 }
505
506 if (changePacesetter) {
507 scheduler.setPacesetterDisplay(kDisplayId2);
Dominik Laskowski50e2e4d2023-10-04 10:58:28 -0400508 }
509
510 return committed;
511 }
512
Dominik Laskowskifb4b7372023-11-22 09:56:54 -0500513 CompositeResultsPerDisplay composite(PhysicalDisplayId pacesetterId,
514 const scheduler::FrameTargeters& targeters) override {
515 pacesetterIds.composite = pacesetterId;
516
Dominik Laskowski50e2e4d2023-10-04 10:58:28 -0400517 CompositeResultsPerDisplay results;
518
Dominik Laskowskifb4b7372023-11-22 09:56:54 -0500519 for (const auto& [id, targeter] : targeters) {
520 vsyncIds.composite.emplace_back(id, targeter->target().vsyncId());
Dominik Laskowski50e2e4d2023-10-04 10:58:28 -0400521 results.try_emplace(id,
522 CompositeResult{.compositionCoverage =
523 CompositionCoverage::Hwc});
524 }
525
526 return results;
527 }
528
529 void sample() override {}
ramindaniae645822024-01-11 10:57:29 -0800530 void sendNotifyExpectedPresentHint(PhysicalDisplayId) override {}
Dominik Laskowskifb4b7372023-11-22 09:56:54 -0500531 } compositor(*mScheduler);
Dominik Laskowski50e2e4d2023-10-04 10:58:28 -0400532
533 mScheduler->doFrameSignal(compositor, VsyncId(42));
534
Dominik Laskowskifb4b7372023-11-22 09:56:54 -0500535 const auto makeVsyncIds = [](VsyncId vsyncId, bool swap = false) -> VsyncIds {
536 if (swap) {
537 return {{kDisplayId2, vsyncId}, {kDisplayId1, vsyncId}};
538 } else {
539 return {{kDisplayId1, vsyncId}, {kDisplayId2, vsyncId}};
540 }
Dominik Laskowski50e2e4d2023-10-04 10:58:28 -0400541 };
542
Dominik Laskowskifb4b7372023-11-22 09:56:54 -0500543 EXPECT_EQ(kDisplayId1, compositor.pacesetterIds.commit);
544 EXPECT_EQ(kDisplayId1, compositor.pacesetterIds.composite);
545 EXPECT_EQ(makeVsyncIds(VsyncId(42)), compositor.vsyncIds.commit);
546 EXPECT_EQ(makeVsyncIds(VsyncId(42)), compositor.vsyncIds.composite);
Dominik Laskowski50e2e4d2023-10-04 10:58:28 -0400547
Dominik Laskowskifb4b7372023-11-22 09:56:54 -0500548 // FrameTargets should be updated despite the skipped commit.
Dominik Laskowski50e2e4d2023-10-04 10:58:28 -0400549 compositor.committed = false;
550 mScheduler->doFrameSignal(compositor, VsyncId(43));
551
Dominik Laskowskifb4b7372023-11-22 09:56:54 -0500552 EXPECT_EQ(kDisplayId1, compositor.pacesetterIds.commit);
553 EXPECT_EQ(kDisplayId1, compositor.pacesetterIds.composite);
554 EXPECT_EQ(makeVsyncIds(VsyncId(43)), compositor.vsyncIds.commit);
555 EXPECT_TRUE(compositor.vsyncIds.composite.empty());
556
557 // The pacesetter may change during commit.
558 compositor.committed = true;
559 compositor.changePacesetter = true;
560 mScheduler->doFrameSignal(compositor, VsyncId(44));
561
562 EXPECT_EQ(kDisplayId1, compositor.pacesetterIds.commit);
563 EXPECT_EQ(kDisplayId2, compositor.pacesetterIds.composite);
564 EXPECT_EQ(makeVsyncIds(VsyncId(44)), compositor.vsyncIds.commit);
565 EXPECT_EQ(makeVsyncIds(VsyncId(44), true), compositor.vsyncIds.composite);
Dominik Laskowski50e2e4d2023-10-04 10:58:28 -0400566}
567
ramindani0491e642023-11-16 17:42:14 -0800568TEST_F(SchedulerTest, nextFrameIntervalTest) {
569 SET_FLAG_FOR_TEST(flags::vrr_config, true);
570
571 static constexpr size_t kHistorySize = 10;
572 static constexpr size_t kMinimumSamplesForPrediction = 6;
573 static constexpr size_t kOutlierTolerancePercent = 25;
574 const auto refreshRate = Fps::fromPeriodNsecs(500);
575 auto frameRate = Fps::fromPeriodNsecs(1000);
576
577 const ftl::NonNull<DisplayModePtr> kMode = ftl::as_non_null(
578 createVrrDisplayMode(DisplayModeId(0), refreshRate,
579 hal::VrrConfig{.minFrameIntervalNs = static_cast<int32_t>(
580 frameRate.getPeriodNsecs())}));
581 std::shared_ptr<VSyncPredictor> vrrTracker =
Ady Abraham77b4fb12024-03-05 17:51:53 -0800582 std::make_shared<VSyncPredictor>(std::make_unique<ZeroClock>(), kMode, kHistorySize,
Ady Abraham20024aa2024-03-05 01:32:49 +0000583 kMinimumSamplesForPrediction,
ramindaniae645822024-01-11 10:57:29 -0800584 kOutlierTolerancePercent);
ramindani0491e642023-11-16 17:42:14 -0800585 std::shared_ptr<RefreshRateSelector> vrrSelectorPtr =
586 std::make_shared<RefreshRateSelector>(makeModes(kMode), kMode->getId());
587 TestableScheduler scheduler{std::make_unique<android::mock::VsyncController>(),
588 vrrTracker,
589 vrrSelectorPtr,
Leon Scroggins III823d4ca2023-12-12 16:57:34 -0500590 mFlinger.getFactory(),
591 mFlinger.getTimeStats(),
ramindaniae645822024-01-11 10:57:29 -0800592 mSchedulerCallback};
ramindani0491e642023-11-16 17:42:14 -0800593
Dominik Laskowski3ff44c72024-06-17 11:03:30 -0400594 scheduler.registerDisplay(kMode->getPhysicalDisplayId(), vrrSelectorPtr, std::nullopt,
595 vrrTracker);
ramindani0491e642023-11-16 17:42:14 -0800596 vrrSelectorPtr->setActiveMode(kMode->getId(), frameRate);
Ady Abrahamee6365b2024-03-06 14:31:45 -0800597 scheduler.setRenderRate(kMode->getPhysicalDisplayId(), frameRate, /*applyImmediately*/ false);
ramindani0491e642023-11-16 17:42:14 -0800598 vrrTracker->addVsyncTimestamp(0);
Ady Abraham20024aa2024-03-05 01:32:49 +0000599 // Set 1000 as vsync seq #0
600 vrrTracker->nextAnticipatedVSyncTimeFrom(700);
ramindani0491e642023-11-16 17:42:14 -0800601
ramindani0491e642023-11-16 17:42:14 -0800602 EXPECT_EQ(Fps::fromPeriodNsecs(1000),
603 scheduler.getNextFrameInterval(kMode->getPhysicalDisplayId(),
Ady Abraham4335afd2023-12-18 19:10:47 -0800604 TimePoint::fromNs(1000)));
ramindani0491e642023-11-16 17:42:14 -0800605 EXPECT_EQ(Fps::fromPeriodNsecs(1000),
606 scheduler.getNextFrameInterval(kMode->getPhysicalDisplayId(),
Ady Abraham4335afd2023-12-18 19:10:47 -0800607 TimePoint::fromNs(2000)));
ramindani0491e642023-11-16 17:42:14 -0800608
Ady Abraham4335afd2023-12-18 19:10:47 -0800609 // Not crossing the min frame period
Ady Abrahame54ce102024-03-04 23:18:38 +0000610 vrrTracker->onFrameBegin(TimePoint::fromNs(2000), TimePoint::fromNs(1500));
Ady Abraham20024aa2024-03-05 01:32:49 +0000611 EXPECT_EQ(Fps::fromPeriodNsecs(1000),
Ady Abraham4335afd2023-12-18 19:10:47 -0800612 scheduler.getNextFrameInterval(kMode->getPhysicalDisplayId(),
613 TimePoint::fromNs(2500)));
ramindani0491e642023-11-16 17:42:14 -0800614 // Change render rate
615 frameRate = Fps::fromPeriodNsecs(2000);
616 vrrSelectorPtr->setActiveMode(kMode->getId(), frameRate);
Ady Abrahamee6365b2024-03-06 14:31:45 -0800617 scheduler.setRenderRate(kMode->getPhysicalDisplayId(), frameRate, /*applyImmediately*/ false);
ramindani0491e642023-11-16 17:42:14 -0800618
619 EXPECT_EQ(Fps::fromPeriodNsecs(2000),
620 scheduler.getNextFrameInterval(kMode->getPhysicalDisplayId(),
Ady Abrahamfe15a352024-03-19 10:49:17 -0700621 TimePoint::fromNs(5500)));
ramindani0491e642023-11-16 17:42:14 -0800622 EXPECT_EQ(Fps::fromPeriodNsecs(2000),
623 scheduler.getNextFrameInterval(kMode->getPhysicalDisplayId(),
Ady Abrahamfe15a352024-03-19 10:49:17 -0700624 TimePoint::fromNs(7500)));
ramindani0491e642023-11-16 17:42:14 -0800625}
626
Leon Scroggins III792ea802023-11-27 17:32:51 -0500627TEST_F(SchedulerTest, resyncAllToHardwareVsync) FTL_FAKE_GUARD(kMainThreadContext) {
628 // resyncAllToHardwareVsync will result in requesting hardware VSYNC on both displays, since
629 // they are both on.
630 EXPECT_CALL(mScheduler->mockRequestHardwareVsync, Call(kDisplayId1, true)).Times(1);
631 EXPECT_CALL(mScheduler->mockRequestHardwareVsync, Call(kDisplayId2, true)).Times(1);
632
633 mScheduler->registerDisplay(kDisplayId2,
634 std::make_shared<RefreshRateSelector>(kDisplay2Modes,
635 kDisplay2Mode60->getId()));
636 mScheduler->setDisplayPowerMode(kDisplayId1, hal::PowerMode::ON);
637 mScheduler->setDisplayPowerMode(kDisplayId2, hal::PowerMode::ON);
638
639 static constexpr bool kDisallow = true;
640 mScheduler->disableHardwareVsync(kDisplayId1, kDisallow);
641 mScheduler->disableHardwareVsync(kDisplayId2, kDisallow);
642
643 static constexpr bool kAllowToEnable = true;
644 mScheduler->resyncAllToHardwareVsync(kAllowToEnable);
645}
646
647TEST_F(SchedulerTest, resyncAllDoNotAllow) FTL_FAKE_GUARD(kMainThreadContext) {
648 // Without setting allowToEnable to true, resyncAllToHardwareVsync does not
649 // result in requesting hardware VSYNC.
650 EXPECT_CALL(mScheduler->mockRequestHardwareVsync, Call(kDisplayId1, _)).Times(0);
651
652 mScheduler->setDisplayPowerMode(kDisplayId1, hal::PowerMode::ON);
653
654 static constexpr bool kDisallow = true;
655 mScheduler->disableHardwareVsync(kDisplayId1, kDisallow);
656
657 static constexpr bool kAllowToEnable = false;
658 mScheduler->resyncAllToHardwareVsync(kAllowToEnable);
659}
660
661TEST_F(SchedulerTest, resyncAllSkipsOffDisplays) FTL_FAKE_GUARD(kMainThreadContext) {
662 SET_FLAG_FOR_TEST(flags::multithreaded_present, true);
663
664 // resyncAllToHardwareVsync will result in requesting hardware VSYNC on display 1, which is on,
665 // but not on display 2, which is off.
666 EXPECT_CALL(mScheduler->mockRequestHardwareVsync, Call(kDisplayId1, true)).Times(1);
667 EXPECT_CALL(mScheduler->mockRequestHardwareVsync, Call(kDisplayId2, _)).Times(0);
668
669 mScheduler->setDisplayPowerMode(kDisplayId1, hal::PowerMode::ON);
670
671 mScheduler->registerDisplay(kDisplayId2,
672 std::make_shared<RefreshRateSelector>(kDisplay2Modes,
673 kDisplay2Mode60->getId()));
674 ASSERT_EQ(hal::PowerMode::OFF, mScheduler->getDisplayPowerMode(kDisplayId2));
675
676 static constexpr bool kDisallow = true;
677 mScheduler->disableHardwareVsync(kDisplayId1, kDisallow);
678 mScheduler->disableHardwareVsync(kDisplayId2, kDisallow);
679
680 static constexpr bool kAllowToEnable = true;
681 mScheduler->resyncAllToHardwareVsync(kAllowToEnable);
682}
683
684TEST_F(SchedulerTest, resyncAllLegacyAppliesToOffDisplays) FTL_FAKE_GUARD(kMainThreadContext) {
685 SET_FLAG_FOR_TEST(flags::multithreaded_present, false);
686
687 // In the legacy code, prior to the flag, resync applied to OFF displays.
688 EXPECT_CALL(mScheduler->mockRequestHardwareVsync, Call(kDisplayId1, true)).Times(1);
689 EXPECT_CALL(mScheduler->mockRequestHardwareVsync, Call(kDisplayId2, true)).Times(1);
690
691 mScheduler->setDisplayPowerMode(kDisplayId1, hal::PowerMode::ON);
692
693 mScheduler->registerDisplay(kDisplayId2,
694 std::make_shared<RefreshRateSelector>(kDisplay2Modes,
695 kDisplay2Mode60->getId()));
696 ASSERT_EQ(hal::PowerMode::OFF, mScheduler->getDisplayPowerMode(kDisplayId2));
697
698 static constexpr bool kDisallow = true;
699 mScheduler->disableHardwareVsync(kDisplayId1, kDisallow);
700 mScheduler->disableHardwareVsync(kDisplayId2, kDisallow);
701
702 static constexpr bool kAllowToEnable = true;
703 mScheduler->resyncAllToHardwareVsync(kAllowToEnable);
704}
705
Ady Abraham822ecbd2023-07-07 16:16:09 -0700706class AttachedChoreographerTest : public SchedulerTest {
707protected:
708 void frameRateTestScenario(Fps layerFps, int8_t frameRateCompatibility, Fps displayFps,
709 Fps expectedChoreographerFps);
710};
711
712TEST_F(AttachedChoreographerTest, registerSingle) {
713 EXPECT_TRUE(mScheduler->mutableAttachedChoreographers().empty());
714
715 const sp<MockLayer> layer = sp<MockLayer>::make(mFlinger.flinger());
716
717 EXPECT_CALL(mSchedulerCallback, onChoreographerAttached);
718 const sp<IDisplayEventConnection> connection =
Dominik Laskowski4babfc42024-02-16 12:28:40 -0500719 mScheduler->createDisplayEventConnection(Cycle::Render, {}, layer->getHandle());
Ady Abraham822ecbd2023-07-07 16:16:09 -0700720
721 EXPECT_EQ(1u, mScheduler->mutableAttachedChoreographers().size());
722 ASSERT_EQ(1u, mScheduler->mutableAttachedChoreographers().count(layer->getSequence()));
723 EXPECT_EQ(1u,
724 mScheduler->mutableAttachedChoreographers()[layer->getSequence()].connections.size());
725 EXPECT_FALSE(
726 mScheduler->mutableAttachedChoreographers()[layer->getSequence()].frameRate.isValid());
727}
728
729TEST_F(AttachedChoreographerTest, registerMultipleOnSameLayer) {
730 EXPECT_TRUE(mScheduler->mutableAttachedChoreographers().empty());
731
732 const sp<MockLayer> layer = sp<MockLayer>::make(mFlinger.flinger());
733 const auto handle = layer->getHandle();
734
735 EXPECT_CALL(mSchedulerCallback, onChoreographerAttached).Times(2);
736
737 EXPECT_CALL(*mEventThread, registerDisplayEventConnection(_))
738 .WillOnce(Return(0))
739 .WillOnce(Return(0));
740
741 const auto mockConnection1 = sp<MockEventThreadConnection>::make(mEventThread);
742 const auto mockConnection2 = sp<MockEventThreadConnection>::make(mEventThread);
743 EXPECT_CALL(*mEventThread, createEventConnection(_, _))
744 .WillOnce(Return(mockConnection1))
745 .WillOnce(Return(mockConnection2));
746
747 const sp<IDisplayEventConnection> connection1 =
Dominik Laskowski4babfc42024-02-16 12:28:40 -0500748 mScheduler->createDisplayEventConnection(Cycle::Render, {}, handle);
Ady Abraham822ecbd2023-07-07 16:16:09 -0700749 const sp<IDisplayEventConnection> connection2 =
Dominik Laskowski4babfc42024-02-16 12:28:40 -0500750 mScheduler->createDisplayEventConnection(Cycle::Render, {}, handle);
Ady Abraham822ecbd2023-07-07 16:16:09 -0700751
752 EXPECT_EQ(1u, mScheduler->mutableAttachedChoreographers().size());
753 ASSERT_EQ(1u, mScheduler->mutableAttachedChoreographers().count(layer->getSequence()));
754 EXPECT_EQ(2u,
755 mScheduler->mutableAttachedChoreographers()[layer->getSequence()].connections.size());
756 EXPECT_FALSE(
757 mScheduler->mutableAttachedChoreographers()[layer->getSequence()].frameRate.isValid());
758}
759
760TEST_F(AttachedChoreographerTest, registerMultipleOnDifferentLayers) {
761 EXPECT_TRUE(mScheduler->mutableAttachedChoreographers().empty());
762
763 const sp<MockLayer> layer1 = sp<MockLayer>::make(mFlinger.flinger());
764 const sp<MockLayer> layer2 = sp<MockLayer>::make(mFlinger.flinger());
765
766 EXPECT_CALL(mSchedulerCallback, onChoreographerAttached).Times(2);
767 const sp<IDisplayEventConnection> connection1 =
Dominik Laskowski4babfc42024-02-16 12:28:40 -0500768 mScheduler->createDisplayEventConnection(Cycle::Render, {}, layer1->getHandle());
Ady Abraham822ecbd2023-07-07 16:16:09 -0700769 const sp<IDisplayEventConnection> connection2 =
Dominik Laskowski4babfc42024-02-16 12:28:40 -0500770 mScheduler->createDisplayEventConnection(Cycle::Render, {}, layer2->getHandle());
Ady Abraham822ecbd2023-07-07 16:16:09 -0700771
772 EXPECT_EQ(2u, mScheduler->mutableAttachedChoreographers().size());
773
774 ASSERT_EQ(1u, mScheduler->mutableAttachedChoreographers().count(layer1->getSequence()));
775 EXPECT_EQ(1u,
776 mScheduler->mutableAttachedChoreographers()[layer1->getSequence()]
777 .connections.size());
778 EXPECT_FALSE(
779 mScheduler->mutableAttachedChoreographers()[layer1->getSequence()].frameRate.isValid());
780
781 ASSERT_EQ(1u, mScheduler->mutableAttachedChoreographers().count(layer2->getSequence()));
782 EXPECT_EQ(1u,
783 mScheduler->mutableAttachedChoreographers()[layer2->getSequence()]
784 .connections.size());
785 EXPECT_FALSE(
786 mScheduler->mutableAttachedChoreographers()[layer2->getSequence()].frameRate.isValid());
787}
788
789TEST_F(AttachedChoreographerTest, removedWhenConnectionIsGone) {
790 EXPECT_TRUE(mScheduler->mutableAttachedChoreographers().empty());
791
792 const sp<MockLayer> layer = sp<MockLayer>::make(mFlinger.flinger());
793
794 EXPECT_CALL(mSchedulerCallback, onChoreographerAttached);
795
796 sp<IDisplayEventConnection> connection =
Dominik Laskowski4babfc42024-02-16 12:28:40 -0500797 mScheduler->createDisplayEventConnection(Cycle::Render, {}, layer->getHandle());
Ady Abraham822ecbd2023-07-07 16:16:09 -0700798
799 ASSERT_EQ(1u, mScheduler->mutableAttachedChoreographers().count(layer->getSequence()));
800 EXPECT_EQ(1u,
801 mScheduler->mutableAttachedChoreographers()[layer->getSequence()].connections.size());
802
803 // The connection is used all over this test, so it is quite hard to release it from here.
804 // Instead, we just do a small shortcut.
805 {
806 EXPECT_CALL(*mEventThread, registerDisplayEventConnection(_)).WillOnce(Return(0));
807 sp<MockEventThreadConnection> mockConnection =
808 sp<MockEventThreadConnection>::make(mEventThread);
809 mScheduler->mutableAttachedChoreographers()[layer->getSequence()].connections.clear();
810 mScheduler->mutableAttachedChoreographers()[layer->getSequence()].connections.emplace(
811 mockConnection);
812 }
813
814 RequestedLayerState layerState(LayerCreationArgs(layer->getSequence()));
815 LayerHierarchy hierarchy(&layerState);
816 mScheduler->updateAttachedChoreographers(hierarchy, 60_Hz);
817 EXPECT_TRUE(mScheduler->mutableAttachedChoreographers().empty());
818}
819
820TEST_F(AttachedChoreographerTest, removedWhenLayerIsGone) {
821 EXPECT_TRUE(mScheduler->mutableAttachedChoreographers().empty());
822
823 sp<MockLayer> layer = sp<MockLayer>::make(mFlinger.flinger());
824
825 EXPECT_CALL(mSchedulerCallback, onChoreographerAttached);
826 const sp<IDisplayEventConnection> connection =
Dominik Laskowski4babfc42024-02-16 12:28:40 -0500827 mScheduler->createDisplayEventConnection(Cycle::Render, {}, layer->getHandle());
Ady Abraham822ecbd2023-07-07 16:16:09 -0700828
829 layer.clear();
830 mFlinger.mutableLayersPendingRemoval().clear();
831 EXPECT_TRUE(mScheduler->mutableAttachedChoreographers().empty());
832}
833
834void AttachedChoreographerTest::frameRateTestScenario(Fps layerFps, int8_t frameRateCompatibility,
835 Fps displayFps,
836 Fps expectedChoreographerFps) {
837 const sp<MockLayer> layer = sp<MockLayer>::make(mFlinger.flinger());
838
839 EXPECT_CALL(mSchedulerCallback, onChoreographerAttached);
840 sp<IDisplayEventConnection> connection =
Dominik Laskowski4babfc42024-02-16 12:28:40 -0500841 mScheduler->createDisplayEventConnection(Cycle::Render, {}, layer->getHandle());
Ady Abraham822ecbd2023-07-07 16:16:09 -0700842
843 RequestedLayerState layerState(LayerCreationArgs(layer->getSequence()));
844 LayerHierarchy hierarchy(&layerState);
845
846 layerState.frameRate = layerFps.getValue();
847 layerState.frameRateCompatibility = frameRateCompatibility;
848
849 mScheduler->updateAttachedChoreographers(hierarchy, displayFps);
850
851 ASSERT_EQ(1u, mScheduler->mutableAttachedChoreographers().count(layer->getSequence()));
852 EXPECT_EQ(expectedChoreographerFps,
853 mScheduler->mutableAttachedChoreographers()[layer->getSequence()].frameRate);
854 EXPECT_EQ(expectedChoreographerFps, mEventThreadConnection->frameRate);
855}
856
857TEST_F(AttachedChoreographerTest, setsFrameRateDefault) {
858 Fps layerFps = 30_Hz;
859 int8_t frameRateCompatibility = ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT;
860 Fps displayFps = 60_Hz;
861 Fps expectedChoreographerFps = 30_Hz;
862
863 frameRateTestScenario(layerFps, frameRateCompatibility, displayFps, expectedChoreographerFps);
864
865 layerFps = Fps::fromValue(32.7f);
866 frameRateTestScenario(layerFps, frameRateCompatibility, displayFps, expectedChoreographerFps);
867}
868
869TEST_F(AttachedChoreographerTest, setsFrameRateExact) {
870 Fps layerFps = 30_Hz;
871 int8_t frameRateCompatibility = ANATIVEWINDOW_FRAME_RATE_EXACT;
872 Fps displayFps = 60_Hz;
873 Fps expectedChoreographerFps = 30_Hz;
874
875 frameRateTestScenario(layerFps, frameRateCompatibility, displayFps, expectedChoreographerFps);
876
877 layerFps = Fps::fromValue(32.7f);
878 expectedChoreographerFps = {};
879 frameRateTestScenario(layerFps, frameRateCompatibility, displayFps, expectedChoreographerFps);
880}
881
882TEST_F(AttachedChoreographerTest, setsFrameRateExactOrMultiple) {
883 Fps layerFps = 30_Hz;
884 int8_t frameRateCompatibility = ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_FIXED_SOURCE;
885 Fps displayFps = 60_Hz;
886 Fps expectedChoreographerFps = 30_Hz;
887
888 frameRateTestScenario(layerFps, frameRateCompatibility, displayFps, expectedChoreographerFps);
889
890 layerFps = Fps::fromValue(32.7f);
891 expectedChoreographerFps = {};
892 frameRateTestScenario(layerFps, frameRateCompatibility, displayFps, expectedChoreographerFps);
893}
894
895TEST_F(AttachedChoreographerTest, setsFrameRateParent) {
896 const sp<MockLayer> layer = sp<MockLayer>::make(mFlinger.flinger());
897 const sp<MockLayer> parent = sp<MockLayer>::make(mFlinger.flinger());
898
899 EXPECT_CALL(mSchedulerCallback, onChoreographerAttached);
900 sp<IDisplayEventConnection> connection =
Dominik Laskowski4babfc42024-02-16 12:28:40 -0500901 mScheduler->createDisplayEventConnection(Cycle::Render, {}, parent->getHandle());
Ady Abraham822ecbd2023-07-07 16:16:09 -0700902
903 RequestedLayerState parentState(LayerCreationArgs(parent->getSequence()));
904 LayerHierarchy parentHierarchy(&parentState);
905
906 RequestedLayerState layerState(LayerCreationArgs(layer->getSequence()));
907 LayerHierarchy hierarchy(&layerState);
908 parentHierarchy.mChildren.push_back(
909 std::make_pair(&hierarchy, LayerHierarchy::Variant::Attached));
910
911 layerState.frameRate = (30_Hz).getValue();
912 layerState.frameRateCompatibility = ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT;
913
914 mScheduler->updateAttachedChoreographers(parentHierarchy, 120_Hz);
915
916 ASSERT_EQ(1u, mScheduler->mutableAttachedChoreographers().count(parent->getSequence()));
917
918 EXPECT_EQ(30_Hz, mScheduler->mutableAttachedChoreographers()[parent->getSequence()].frameRate);
919}
920
921TEST_F(AttachedChoreographerTest, setsFrameRateParent2Children) {
922 const sp<MockLayer> layer1 = sp<MockLayer>::make(mFlinger.flinger());
923 const sp<MockLayer> layer2 = sp<MockLayer>::make(mFlinger.flinger());
924 const sp<MockLayer> parent = sp<MockLayer>::make(mFlinger.flinger());
925
926 EXPECT_CALL(mSchedulerCallback, onChoreographerAttached);
927 sp<IDisplayEventConnection> connection =
Dominik Laskowski4babfc42024-02-16 12:28:40 -0500928 mScheduler->createDisplayEventConnection(Cycle::Render, {}, parent->getHandle());
Ady Abraham822ecbd2023-07-07 16:16:09 -0700929
930 RequestedLayerState parentState(LayerCreationArgs(parent->getSequence()));
931 LayerHierarchy parentHierarchy(&parentState);
932
933 RequestedLayerState layer1State(LayerCreationArgs(layer1->getSequence()));
934 LayerHierarchy layer1Hierarchy(&layer1State);
935 parentHierarchy.mChildren.push_back(
936 std::make_pair(&layer1Hierarchy, LayerHierarchy::Variant::Attached));
937
938 RequestedLayerState layer2State(LayerCreationArgs(layer1->getSequence()));
939 LayerHierarchy layer2Hierarchy(&layer2State);
940 parentHierarchy.mChildren.push_back(
941 std::make_pair(&layer2Hierarchy, LayerHierarchy::Variant::Attached));
942
943 layer1State.frameRate = (30_Hz).getValue();
944 layer1State.frameRateCompatibility = ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT;
945
946 layer2State.frameRate = (20_Hz).getValue();
947 layer2State.frameRateCompatibility = ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT;
948
949 mScheduler->updateAttachedChoreographers(parentHierarchy, 120_Hz);
950
951 ASSERT_EQ(1u, mScheduler->mutableAttachedChoreographers().count(parent->getSequence()));
952
953 EXPECT_EQ(60_Hz, mScheduler->mutableAttachedChoreographers()[parent->getSequence()].frameRate);
954}
955
956TEST_F(AttachedChoreographerTest, setsFrameRateParentConflictingChildren) {
957 const sp<MockLayer> layer1 = sp<MockLayer>::make(mFlinger.flinger());
958 const sp<MockLayer> layer2 = sp<MockLayer>::make(mFlinger.flinger());
959 const sp<MockLayer> parent = sp<MockLayer>::make(mFlinger.flinger());
960
961 EXPECT_CALL(mSchedulerCallback, onChoreographerAttached);
962 sp<IDisplayEventConnection> connection =
Dominik Laskowski4babfc42024-02-16 12:28:40 -0500963 mScheduler->createDisplayEventConnection(Cycle::Render, {}, parent->getHandle());
Ady Abraham822ecbd2023-07-07 16:16:09 -0700964
965 RequestedLayerState parentState(LayerCreationArgs(parent->getSequence()));
966 LayerHierarchy parentHierarchy(&parentState);
967
968 RequestedLayerState layer1State(LayerCreationArgs(layer1->getSequence()));
969 LayerHierarchy layer1Hierarchy(&layer1State);
970 parentHierarchy.mChildren.push_back(
971 std::make_pair(&layer1Hierarchy, LayerHierarchy::Variant::Attached));
972
973 RequestedLayerState layer2State(LayerCreationArgs(layer1->getSequence()));
974 LayerHierarchy layer2Hierarchy(&layer2State);
975 parentHierarchy.mChildren.push_back(
976 std::make_pair(&layer2Hierarchy, LayerHierarchy::Variant::Attached));
977
978 layer1State.frameRate = (30_Hz).getValue();
979 layer1State.frameRateCompatibility = ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT;
980
981 layer2State.frameRate = (25_Hz).getValue();
982 layer2State.frameRateCompatibility = ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT;
983
984 mScheduler->updateAttachedChoreographers(parentHierarchy, 120_Hz);
985
986 ASSERT_EQ(1u, mScheduler->mutableAttachedChoreographers().count(parent->getSequence()));
987
988 EXPECT_EQ(Fps(), mScheduler->mutableAttachedChoreographers()[parent->getSequence()].frameRate);
989}
990
991TEST_F(AttachedChoreographerTest, setsFrameRateChild) {
992 const sp<MockLayer> layer = sp<MockLayer>::make(mFlinger.flinger());
993 const sp<MockLayer> parent = sp<MockLayer>::make(mFlinger.flinger());
994
995 EXPECT_CALL(mSchedulerCallback, onChoreographerAttached);
996 sp<IDisplayEventConnection> connection =
Dominik Laskowski4babfc42024-02-16 12:28:40 -0500997 mScheduler->createDisplayEventConnection(Cycle::Render, {}, layer->getHandle());
Ady Abraham822ecbd2023-07-07 16:16:09 -0700998
999 RequestedLayerState parentState(LayerCreationArgs(parent->getSequence()));
1000 LayerHierarchy parentHierarchy(&parentState);
1001
1002 RequestedLayerState layerState(LayerCreationArgs(layer->getSequence()));
1003 LayerHierarchy hierarchy(&layerState);
1004 parentHierarchy.mChildren.push_back(
1005 std::make_pair(&hierarchy, LayerHierarchy::Variant::Attached));
1006
1007 parentState.frameRate = (30_Hz).getValue();
1008 parentState.frameRateCompatibility = ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT;
1009
1010 mScheduler->updateAttachedChoreographers(parentHierarchy, 120_Hz);
1011
1012 ASSERT_EQ(1u, mScheduler->mutableAttachedChoreographers().count(layer->getSequence()));
1013
1014 EXPECT_EQ(30_Hz, mScheduler->mutableAttachedChoreographers()[layer->getSequence()].frameRate);
1015}
1016
1017TEST_F(AttachedChoreographerTest, setsFrameRateChildNotOverriddenByParent) {
1018 const sp<MockLayer> layer = sp<MockLayer>::make(mFlinger.flinger());
1019 const sp<MockLayer> parent = sp<MockLayer>::make(mFlinger.flinger());
1020
1021 EXPECT_CALL(mSchedulerCallback, onChoreographerAttached);
1022 sp<IDisplayEventConnection> connection =
Dominik Laskowski4babfc42024-02-16 12:28:40 -05001023 mScheduler->createDisplayEventConnection(Cycle::Render, {}, layer->getHandle());
Ady Abraham822ecbd2023-07-07 16:16:09 -07001024
1025 RequestedLayerState parentState(LayerCreationArgs(parent->getSequence()));
1026 LayerHierarchy parentHierarchy(&parentState);
1027
1028 RequestedLayerState layerState(LayerCreationArgs(layer->getSequence()));
1029 LayerHierarchy hierarchy(&layerState);
1030 parentHierarchy.mChildren.push_back(
1031 std::make_pair(&hierarchy, LayerHierarchy::Variant::Attached));
1032
1033 parentState.frameRate = (30_Hz).getValue();
1034 parentState.frameRateCompatibility = ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT;
1035
1036 layerState.frameRate = (60_Hz).getValue();
1037 layerState.frameRateCompatibility = ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT;
1038
1039 mScheduler->updateAttachedChoreographers(parentHierarchy, 120_Hz);
1040
1041 ASSERT_EQ(1u, mScheduler->mutableAttachedChoreographers().count(layer->getSequence()));
1042
1043 EXPECT_EQ(60_Hz, mScheduler->mutableAttachedChoreographers()[layer->getSequence()].frameRate);
1044}
1045
Dominik Laskowski068173d2021-08-11 17:22:59 -07001046} // namespace android::scheduler