blob: 4fb06907d041dcf4d8595bb773e8a2582442c8ee [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 Laskowskib5a094b2022-10-27 12:00:12 -0400346 mScheduler->registerDisplay(kDisplayId1,
347 std::make_shared<RefreshRateSelector>(kDisplay1Modes,
348 kDisplay1Mode60->getId()));
349 mScheduler->registerDisplay(kDisplayId2,
350 std::make_shared<RefreshRateSelector>(kDisplay2Modes,
351 kDisplay2Mode60->getId()));
ramindani69b58e82022-09-26 16:48:36 -0700352
Dominik Laskowski086507b2024-05-16 15:33:16 -0400353 mScheduler->setDisplayPowerMode(kDisplayId1, hal::PowerMode::ON);
354 mScheduler->setDisplayPowerMode(kDisplayId2, hal::PowerMode::ON);
355
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400356 using DisplayModeChoice = TestableScheduler::DisplayModeChoice;
357 TestableScheduler::DisplayModeChoiceMap expectedChoices;
ramindani69b58e82022-09-26 16:48:36 -0700358
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400359 {
360 const GlobalSignals globalSignals = {.idle = true};
361 expectedChoices =
362 ftl::init::map<const PhysicalDisplayId&,
Ady Abrahamace3d052022-11-17 16:25:05 -0800363 DisplayModeChoice>(kDisplayId1,
364 FrameRateMode{60_Hz, kDisplay1Mode60},
365 globalSignals)(kDisplayId2,
366 FrameRateMode{60_Hz,
367 kDisplay2Mode60},
Dominik Laskowski9e88d622024-03-06 17:42:39 -0500368 GlobalSignals{});
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400369
Dominik Laskowskid82e0f02022-10-26 15:23:04 -0400370 std::vector<RefreshRateSelector::LayerRequirement> layers = {{.weight = 1.f},
371 {.weight = 1.f}};
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400372 mScheduler->setContentRequirements(layers);
373 mScheduler->setTouchStateAndIdleTimerPolicy(globalSignals);
374
375 const auto actualChoices = mScheduler->chooseDisplayModes();
376 EXPECT_EQ(expectedChoices, actualChoices);
ramindani69b58e82022-09-26 16:48:36 -0700377 }
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400378 {
379 const GlobalSignals globalSignals = {.idle = false};
380 expectedChoices =
381 ftl::init::map<const PhysicalDisplayId&,
Ady Abrahamace3d052022-11-17 16:25:05 -0800382 DisplayModeChoice>(kDisplayId1,
383 FrameRateMode{120_Hz, kDisplay1Mode120},
384 globalSignals)(kDisplayId2,
385 FrameRateMode{120_Hz,
386 kDisplay2Mode120},
Dominik Laskowski9e88d622024-03-06 17:42:39 -0500387 GlobalSignals{});
ramindani69b58e82022-09-26 16:48:36 -0700388
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400389 mScheduler->setTouchStateAndIdleTimerPolicy(globalSignals);
ramindani69b58e82022-09-26 16:48:36 -0700390
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400391 const auto actualChoices = mScheduler->chooseDisplayModes();
392 EXPECT_EQ(expectedChoices, actualChoices);
ramindani69b58e82022-09-26 16:48:36 -0700393 }
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400394 {
395 const GlobalSignals globalSignals = {.touch = true};
396 mScheduler->replaceTouchTimer(10);
397 mScheduler->setTouchStateAndIdleTimerPolicy(globalSignals);
ramindani69b58e82022-09-26 16:48:36 -0700398
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400399 expectedChoices =
400 ftl::init::map<const PhysicalDisplayId&,
Ady Abrahamace3d052022-11-17 16:25:05 -0800401 DisplayModeChoice>(kDisplayId1,
402 FrameRateMode{120_Hz, kDisplay1Mode120},
403 globalSignals)(kDisplayId2,
404 FrameRateMode{120_Hz,
405 kDisplay2Mode120},
Dominik Laskowski9e88d622024-03-06 17:42:39 -0500406 GlobalSignals{});
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400407
408 const auto actualChoices = mScheduler->chooseDisplayModes();
409 EXPECT_EQ(expectedChoices, actualChoices);
ramindani69b58e82022-09-26 16:48:36 -0700410 }
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400411 {
ramindani22f2ead2023-04-21 10:27:11 -0700412 // The kDisplayId3 does not support 120Hz, The pacesetter display rate is chosen to be 120
413 // Hz. In this case only the display kDisplayId3 choose 60Hz as it does not support 120Hz.
Dominik Laskowskib5a094b2022-10-27 12:00:12 -0400414 mScheduler
415 ->registerDisplay(kDisplayId3,
416 std::make_shared<RefreshRateSelector>(kDisplay3Modes,
417 kDisplay3Mode60->getId()));
Dominik Laskowski086507b2024-05-16 15:33:16 -0400418 mScheduler->setDisplayPowerMode(kDisplayId3, hal::PowerMode::ON);
Dominik Laskowski327d6092022-10-11 18:05:08 -0400419
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400420 const GlobalSignals globalSignals = {.touch = true};
421 mScheduler->replaceTouchTimer(10);
422 mScheduler->setTouchStateAndIdleTimerPolicy(globalSignals);
ramindani7c487282022-10-10 16:17:51 -0700423
Ady Abrahamace3d052022-11-17 16:25:05 -0800424 expectedChoices = ftl::init::map<
425 const PhysicalDisplayId&,
ramindani22f2ead2023-04-21 10:27:11 -0700426 DisplayModeChoice>(kDisplayId1, FrameRateMode{120_Hz, kDisplay1Mode120},
427 globalSignals)(kDisplayId2,
428 FrameRateMode{120_Hz, kDisplay2Mode120},
Dominik Laskowski9e88d622024-03-06 17:42:39 -0500429 GlobalSignals{})(kDisplayId3,
430 FrameRateMode{60_Hz,
431 kDisplay3Mode60},
432 GlobalSignals{});
ramindani22f2ead2023-04-21 10:27:11 -0700433
434 const auto actualChoices = mScheduler->chooseDisplayModes();
435 EXPECT_EQ(expectedChoices, actualChoices);
436 }
437 {
438 // We should choose 60Hz despite the touch signal as pacesetter only supports 60Hz
439 mScheduler->setPacesetterDisplay(kDisplayId3);
440 const GlobalSignals globalSignals = {.touch = true};
441 mScheduler->replaceTouchTimer(10);
442 mScheduler->setTouchStateAndIdleTimerPolicy(globalSignals);
443
444 expectedChoices = ftl::init::map<
445 const PhysicalDisplayId&,
Ady Abrahamace3d052022-11-17 16:25:05 -0800446 DisplayModeChoice>(kDisplayId1, FrameRateMode{60_Hz, kDisplay1Mode60},
Dominik Laskowski9e88d622024-03-06 17:42:39 -0500447 GlobalSignals{})(kDisplayId2,
448 FrameRateMode{60_Hz, kDisplay2Mode60},
449 GlobalSignals{})(kDisplayId3,
450 FrameRateMode{60_Hz,
451 kDisplay3Mode60},
452 globalSignals);
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400453
454 const auto actualChoices = mScheduler->chooseDisplayModes();
455 EXPECT_EQ(expectedChoices, actualChoices);
ramindani7c487282022-10-10 16:17:51 -0700456 }
ramindani69b58e82022-09-26 16:48:36 -0700457}
458
Dominik Laskowski50e2e4d2023-10-04 10:58:28 -0400459TEST_F(SchedulerTest, onFrameSignalMultipleDisplays) {
460 mScheduler->registerDisplay(kDisplayId1,
461 std::make_shared<RefreshRateSelector>(kDisplay1Modes,
462 kDisplay1Mode60->getId()));
463 mScheduler->registerDisplay(kDisplayId2,
464 std::make_shared<RefreshRateSelector>(kDisplay2Modes,
465 kDisplay2Mode60->getId()));
466
467 using VsyncIds = std::vector<std::pair<PhysicalDisplayId, VsyncId>>;
468
469 struct Compositor final : ICompositor {
Dominik Laskowskifb4b7372023-11-22 09:56:54 -0500470 explicit Compositor(TestableScheduler& scheduler) : scheduler(scheduler) {}
471
472 TestableScheduler& scheduler;
473
474 struct {
475 PhysicalDisplayId commit;
476 PhysicalDisplayId composite;
477 } pacesetterIds;
478
479 struct {
480 VsyncIds commit;
481 VsyncIds composite;
482 } vsyncIds;
483
Dominik Laskowski50e2e4d2023-10-04 10:58:28 -0400484 bool committed = true;
Dominik Laskowskifb4b7372023-11-22 09:56:54 -0500485 bool changePacesetter = false;
Dominik Laskowski50e2e4d2023-10-04 10:58:28 -0400486
487 void configure() override {}
488
Dominik Laskowskifb4b7372023-11-22 09:56:54 -0500489 bool commit(PhysicalDisplayId pacesetterId,
490 const scheduler::FrameTargets& targets) override {
491 pacesetterIds.commit = pacesetterId;
492
493 vsyncIds.commit.clear();
494 vsyncIds.composite.clear();
Dominik Laskowski50e2e4d2023-10-04 10:58:28 -0400495
496 for (const auto& [id, target] : targets) {
Dominik Laskowskifb4b7372023-11-22 09:56:54 -0500497 vsyncIds.commit.emplace_back(id, target->vsyncId());
498 }
499
500 if (changePacesetter) {
501 scheduler.setPacesetterDisplay(kDisplayId2);
Dominik Laskowski50e2e4d2023-10-04 10:58:28 -0400502 }
503
504 return committed;
505 }
506
Dominik Laskowskifb4b7372023-11-22 09:56:54 -0500507 CompositeResultsPerDisplay composite(PhysicalDisplayId pacesetterId,
508 const scheduler::FrameTargeters& targeters) override {
509 pacesetterIds.composite = pacesetterId;
510
Dominik Laskowski50e2e4d2023-10-04 10:58:28 -0400511 CompositeResultsPerDisplay results;
512
Dominik Laskowskifb4b7372023-11-22 09:56:54 -0500513 for (const auto& [id, targeter] : targeters) {
514 vsyncIds.composite.emplace_back(id, targeter->target().vsyncId());
Dominik Laskowski50e2e4d2023-10-04 10:58:28 -0400515 results.try_emplace(id,
516 CompositeResult{.compositionCoverage =
517 CompositionCoverage::Hwc});
518 }
519
520 return results;
521 }
522
523 void sample() override {}
ramindaniae645822024-01-11 10:57:29 -0800524 void sendNotifyExpectedPresentHint(PhysicalDisplayId) override {}
Dominik Laskowskifb4b7372023-11-22 09:56:54 -0500525 } compositor(*mScheduler);
Dominik Laskowski50e2e4d2023-10-04 10:58:28 -0400526
527 mScheduler->doFrameSignal(compositor, VsyncId(42));
528
Dominik Laskowskifb4b7372023-11-22 09:56:54 -0500529 const auto makeVsyncIds = [](VsyncId vsyncId, bool swap = false) -> VsyncIds {
530 if (swap) {
531 return {{kDisplayId2, vsyncId}, {kDisplayId1, vsyncId}};
532 } else {
533 return {{kDisplayId1, vsyncId}, {kDisplayId2, vsyncId}};
534 }
Dominik Laskowski50e2e4d2023-10-04 10:58:28 -0400535 };
536
Dominik Laskowskifb4b7372023-11-22 09:56:54 -0500537 EXPECT_EQ(kDisplayId1, compositor.pacesetterIds.commit);
538 EXPECT_EQ(kDisplayId1, compositor.pacesetterIds.composite);
539 EXPECT_EQ(makeVsyncIds(VsyncId(42)), compositor.vsyncIds.commit);
540 EXPECT_EQ(makeVsyncIds(VsyncId(42)), compositor.vsyncIds.composite);
Dominik Laskowski50e2e4d2023-10-04 10:58:28 -0400541
Dominik Laskowskifb4b7372023-11-22 09:56:54 -0500542 // FrameTargets should be updated despite the skipped commit.
Dominik Laskowski50e2e4d2023-10-04 10:58:28 -0400543 compositor.committed = false;
544 mScheduler->doFrameSignal(compositor, VsyncId(43));
545
Dominik Laskowskifb4b7372023-11-22 09:56:54 -0500546 EXPECT_EQ(kDisplayId1, compositor.pacesetterIds.commit);
547 EXPECT_EQ(kDisplayId1, compositor.pacesetterIds.composite);
548 EXPECT_EQ(makeVsyncIds(VsyncId(43)), compositor.vsyncIds.commit);
549 EXPECT_TRUE(compositor.vsyncIds.composite.empty());
550
551 // The pacesetter may change during commit.
552 compositor.committed = true;
553 compositor.changePacesetter = true;
554 mScheduler->doFrameSignal(compositor, VsyncId(44));
555
556 EXPECT_EQ(kDisplayId1, compositor.pacesetterIds.commit);
557 EXPECT_EQ(kDisplayId2, compositor.pacesetterIds.composite);
558 EXPECT_EQ(makeVsyncIds(VsyncId(44)), compositor.vsyncIds.commit);
559 EXPECT_EQ(makeVsyncIds(VsyncId(44), true), compositor.vsyncIds.composite);
Dominik Laskowski50e2e4d2023-10-04 10:58:28 -0400560}
561
ramindani0491e642023-11-16 17:42:14 -0800562TEST_F(SchedulerTest, nextFrameIntervalTest) {
563 SET_FLAG_FOR_TEST(flags::vrr_config, true);
564
565 static constexpr size_t kHistorySize = 10;
566 static constexpr size_t kMinimumSamplesForPrediction = 6;
567 static constexpr size_t kOutlierTolerancePercent = 25;
568 const auto refreshRate = Fps::fromPeriodNsecs(500);
569 auto frameRate = Fps::fromPeriodNsecs(1000);
570
571 const ftl::NonNull<DisplayModePtr> kMode = ftl::as_non_null(
572 createVrrDisplayMode(DisplayModeId(0), refreshRate,
573 hal::VrrConfig{.minFrameIntervalNs = static_cast<int32_t>(
574 frameRate.getPeriodNsecs())}));
575 std::shared_ptr<VSyncPredictor> vrrTracker =
Ady Abraham77b4fb12024-03-05 17:51:53 -0800576 std::make_shared<VSyncPredictor>(std::make_unique<ZeroClock>(), kMode, kHistorySize,
Ady Abraham20024aa2024-03-05 01:32:49 +0000577 kMinimumSamplesForPrediction,
ramindaniae645822024-01-11 10:57:29 -0800578 kOutlierTolerancePercent);
ramindani0491e642023-11-16 17:42:14 -0800579 std::shared_ptr<RefreshRateSelector> vrrSelectorPtr =
580 std::make_shared<RefreshRateSelector>(makeModes(kMode), kMode->getId());
581 TestableScheduler scheduler{std::make_unique<android::mock::VsyncController>(),
582 vrrTracker,
583 vrrSelectorPtr,
Leon Scroggins III823d4ca2023-12-12 16:57:34 -0500584 mFlinger.getFactory(),
585 mFlinger.getTimeStats(),
ramindaniae645822024-01-11 10:57:29 -0800586 mSchedulerCallback};
ramindani0491e642023-11-16 17:42:14 -0800587
588 scheduler.registerDisplay(kMode->getPhysicalDisplayId(), vrrSelectorPtr, vrrTracker);
589 vrrSelectorPtr->setActiveMode(kMode->getId(), frameRate);
Ady Abrahamee6365b2024-03-06 14:31:45 -0800590 scheduler.setRenderRate(kMode->getPhysicalDisplayId(), frameRate, /*applyImmediately*/ false);
ramindani0491e642023-11-16 17:42:14 -0800591 vrrTracker->addVsyncTimestamp(0);
Ady Abraham20024aa2024-03-05 01:32:49 +0000592 // Set 1000 as vsync seq #0
593 vrrTracker->nextAnticipatedVSyncTimeFrom(700);
ramindani0491e642023-11-16 17:42:14 -0800594
ramindani0491e642023-11-16 17:42:14 -0800595 EXPECT_EQ(Fps::fromPeriodNsecs(1000),
596 scheduler.getNextFrameInterval(kMode->getPhysicalDisplayId(),
Ady Abraham4335afd2023-12-18 19:10:47 -0800597 TimePoint::fromNs(1000)));
ramindani0491e642023-11-16 17:42:14 -0800598 EXPECT_EQ(Fps::fromPeriodNsecs(1000),
599 scheduler.getNextFrameInterval(kMode->getPhysicalDisplayId(),
Ady Abraham4335afd2023-12-18 19:10:47 -0800600 TimePoint::fromNs(2000)));
ramindani0491e642023-11-16 17:42:14 -0800601
Ady Abraham4335afd2023-12-18 19:10:47 -0800602 // Not crossing the min frame period
Ady Abrahame54ce102024-03-04 23:18:38 +0000603 vrrTracker->onFrameBegin(TimePoint::fromNs(2000), TimePoint::fromNs(1500));
Ady Abraham20024aa2024-03-05 01:32:49 +0000604 EXPECT_EQ(Fps::fromPeriodNsecs(1000),
Ady Abraham4335afd2023-12-18 19:10:47 -0800605 scheduler.getNextFrameInterval(kMode->getPhysicalDisplayId(),
606 TimePoint::fromNs(2500)));
ramindani0491e642023-11-16 17:42:14 -0800607 // Change render rate
608 frameRate = Fps::fromPeriodNsecs(2000);
609 vrrSelectorPtr->setActiveMode(kMode->getId(), frameRate);
Ady Abrahamee6365b2024-03-06 14:31:45 -0800610 scheduler.setRenderRate(kMode->getPhysicalDisplayId(), frameRate, /*applyImmediately*/ false);
ramindani0491e642023-11-16 17:42:14 -0800611
612 EXPECT_EQ(Fps::fromPeriodNsecs(2000),
613 scheduler.getNextFrameInterval(kMode->getPhysicalDisplayId(),
Ady Abrahamfe15a352024-03-19 10:49:17 -0700614 TimePoint::fromNs(5500)));
ramindani0491e642023-11-16 17:42:14 -0800615 EXPECT_EQ(Fps::fromPeriodNsecs(2000),
616 scheduler.getNextFrameInterval(kMode->getPhysicalDisplayId(),
Ady Abrahamfe15a352024-03-19 10:49:17 -0700617 TimePoint::fromNs(7500)));
ramindani0491e642023-11-16 17:42:14 -0800618}
619
Leon Scroggins III792ea802023-11-27 17:32:51 -0500620TEST_F(SchedulerTest, resyncAllToHardwareVsync) FTL_FAKE_GUARD(kMainThreadContext) {
621 // resyncAllToHardwareVsync will result in requesting hardware VSYNC on both displays, since
622 // they are both on.
623 EXPECT_CALL(mScheduler->mockRequestHardwareVsync, Call(kDisplayId1, true)).Times(1);
624 EXPECT_CALL(mScheduler->mockRequestHardwareVsync, Call(kDisplayId2, true)).Times(1);
625
626 mScheduler->registerDisplay(kDisplayId2,
627 std::make_shared<RefreshRateSelector>(kDisplay2Modes,
628 kDisplay2Mode60->getId()));
629 mScheduler->setDisplayPowerMode(kDisplayId1, hal::PowerMode::ON);
630 mScheduler->setDisplayPowerMode(kDisplayId2, hal::PowerMode::ON);
631
632 static constexpr bool kDisallow = true;
633 mScheduler->disableHardwareVsync(kDisplayId1, kDisallow);
634 mScheduler->disableHardwareVsync(kDisplayId2, kDisallow);
635
636 static constexpr bool kAllowToEnable = true;
637 mScheduler->resyncAllToHardwareVsync(kAllowToEnable);
638}
639
640TEST_F(SchedulerTest, resyncAllDoNotAllow) FTL_FAKE_GUARD(kMainThreadContext) {
641 // Without setting allowToEnable to true, resyncAllToHardwareVsync does not
642 // result in requesting hardware VSYNC.
643 EXPECT_CALL(mScheduler->mockRequestHardwareVsync, Call(kDisplayId1, _)).Times(0);
644
645 mScheduler->setDisplayPowerMode(kDisplayId1, hal::PowerMode::ON);
646
647 static constexpr bool kDisallow = true;
648 mScheduler->disableHardwareVsync(kDisplayId1, kDisallow);
649
650 static constexpr bool kAllowToEnable = false;
651 mScheduler->resyncAllToHardwareVsync(kAllowToEnable);
652}
653
654TEST_F(SchedulerTest, resyncAllSkipsOffDisplays) FTL_FAKE_GUARD(kMainThreadContext) {
655 SET_FLAG_FOR_TEST(flags::multithreaded_present, true);
656
657 // resyncAllToHardwareVsync will result in requesting hardware VSYNC on display 1, which is on,
658 // but not on display 2, which is off.
659 EXPECT_CALL(mScheduler->mockRequestHardwareVsync, Call(kDisplayId1, true)).Times(1);
660 EXPECT_CALL(mScheduler->mockRequestHardwareVsync, Call(kDisplayId2, _)).Times(0);
661
662 mScheduler->setDisplayPowerMode(kDisplayId1, hal::PowerMode::ON);
663
664 mScheduler->registerDisplay(kDisplayId2,
665 std::make_shared<RefreshRateSelector>(kDisplay2Modes,
666 kDisplay2Mode60->getId()));
667 ASSERT_EQ(hal::PowerMode::OFF, mScheduler->getDisplayPowerMode(kDisplayId2));
668
669 static constexpr bool kDisallow = true;
670 mScheduler->disableHardwareVsync(kDisplayId1, kDisallow);
671 mScheduler->disableHardwareVsync(kDisplayId2, kDisallow);
672
673 static constexpr bool kAllowToEnable = true;
674 mScheduler->resyncAllToHardwareVsync(kAllowToEnable);
675}
676
677TEST_F(SchedulerTest, resyncAllLegacyAppliesToOffDisplays) FTL_FAKE_GUARD(kMainThreadContext) {
678 SET_FLAG_FOR_TEST(flags::multithreaded_present, false);
679
680 // In the legacy code, prior to the flag, resync applied to OFF displays.
681 EXPECT_CALL(mScheduler->mockRequestHardwareVsync, Call(kDisplayId1, true)).Times(1);
682 EXPECT_CALL(mScheduler->mockRequestHardwareVsync, Call(kDisplayId2, true)).Times(1);
683
684 mScheduler->setDisplayPowerMode(kDisplayId1, hal::PowerMode::ON);
685
686 mScheduler->registerDisplay(kDisplayId2,
687 std::make_shared<RefreshRateSelector>(kDisplay2Modes,
688 kDisplay2Mode60->getId()));
689 ASSERT_EQ(hal::PowerMode::OFF, mScheduler->getDisplayPowerMode(kDisplayId2));
690
691 static constexpr bool kDisallow = true;
692 mScheduler->disableHardwareVsync(kDisplayId1, kDisallow);
693 mScheduler->disableHardwareVsync(kDisplayId2, kDisallow);
694
695 static constexpr bool kAllowToEnable = true;
696 mScheduler->resyncAllToHardwareVsync(kAllowToEnable);
697}
698
Ady Abraham822ecbd2023-07-07 16:16:09 -0700699class AttachedChoreographerTest : public SchedulerTest {
700protected:
701 void frameRateTestScenario(Fps layerFps, int8_t frameRateCompatibility, Fps displayFps,
702 Fps expectedChoreographerFps);
703};
704
705TEST_F(AttachedChoreographerTest, registerSingle) {
706 EXPECT_TRUE(mScheduler->mutableAttachedChoreographers().empty());
707
708 const sp<MockLayer> layer = sp<MockLayer>::make(mFlinger.flinger());
709
710 EXPECT_CALL(mSchedulerCallback, onChoreographerAttached);
711 const sp<IDisplayEventConnection> connection =
Dominik Laskowski4babfc42024-02-16 12:28:40 -0500712 mScheduler->createDisplayEventConnection(Cycle::Render, {}, layer->getHandle());
Ady Abraham822ecbd2023-07-07 16:16:09 -0700713
714 EXPECT_EQ(1u, mScheduler->mutableAttachedChoreographers().size());
715 ASSERT_EQ(1u, mScheduler->mutableAttachedChoreographers().count(layer->getSequence()));
716 EXPECT_EQ(1u,
717 mScheduler->mutableAttachedChoreographers()[layer->getSequence()].connections.size());
718 EXPECT_FALSE(
719 mScheduler->mutableAttachedChoreographers()[layer->getSequence()].frameRate.isValid());
720}
721
722TEST_F(AttachedChoreographerTest, registerMultipleOnSameLayer) {
723 EXPECT_TRUE(mScheduler->mutableAttachedChoreographers().empty());
724
725 const sp<MockLayer> layer = sp<MockLayer>::make(mFlinger.flinger());
726 const auto handle = layer->getHandle();
727
728 EXPECT_CALL(mSchedulerCallback, onChoreographerAttached).Times(2);
729
730 EXPECT_CALL(*mEventThread, registerDisplayEventConnection(_))
731 .WillOnce(Return(0))
732 .WillOnce(Return(0));
733
734 const auto mockConnection1 = sp<MockEventThreadConnection>::make(mEventThread);
735 const auto mockConnection2 = sp<MockEventThreadConnection>::make(mEventThread);
736 EXPECT_CALL(*mEventThread, createEventConnection(_, _))
737 .WillOnce(Return(mockConnection1))
738 .WillOnce(Return(mockConnection2));
739
740 const sp<IDisplayEventConnection> connection1 =
Dominik Laskowski4babfc42024-02-16 12:28:40 -0500741 mScheduler->createDisplayEventConnection(Cycle::Render, {}, handle);
Ady Abraham822ecbd2023-07-07 16:16:09 -0700742 const sp<IDisplayEventConnection> connection2 =
Dominik Laskowski4babfc42024-02-16 12:28:40 -0500743 mScheduler->createDisplayEventConnection(Cycle::Render, {}, handle);
Ady Abraham822ecbd2023-07-07 16:16:09 -0700744
745 EXPECT_EQ(1u, mScheduler->mutableAttachedChoreographers().size());
746 ASSERT_EQ(1u, mScheduler->mutableAttachedChoreographers().count(layer->getSequence()));
747 EXPECT_EQ(2u,
748 mScheduler->mutableAttachedChoreographers()[layer->getSequence()].connections.size());
749 EXPECT_FALSE(
750 mScheduler->mutableAttachedChoreographers()[layer->getSequence()].frameRate.isValid());
751}
752
753TEST_F(AttachedChoreographerTest, registerMultipleOnDifferentLayers) {
754 EXPECT_TRUE(mScheduler->mutableAttachedChoreographers().empty());
755
756 const sp<MockLayer> layer1 = sp<MockLayer>::make(mFlinger.flinger());
757 const sp<MockLayer> layer2 = sp<MockLayer>::make(mFlinger.flinger());
758
759 EXPECT_CALL(mSchedulerCallback, onChoreographerAttached).Times(2);
760 const sp<IDisplayEventConnection> connection1 =
Dominik Laskowski4babfc42024-02-16 12:28:40 -0500761 mScheduler->createDisplayEventConnection(Cycle::Render, {}, layer1->getHandle());
Ady Abraham822ecbd2023-07-07 16:16:09 -0700762 const sp<IDisplayEventConnection> connection2 =
Dominik Laskowski4babfc42024-02-16 12:28:40 -0500763 mScheduler->createDisplayEventConnection(Cycle::Render, {}, layer2->getHandle());
Ady Abraham822ecbd2023-07-07 16:16:09 -0700764
765 EXPECT_EQ(2u, mScheduler->mutableAttachedChoreographers().size());
766
767 ASSERT_EQ(1u, mScheduler->mutableAttachedChoreographers().count(layer1->getSequence()));
768 EXPECT_EQ(1u,
769 mScheduler->mutableAttachedChoreographers()[layer1->getSequence()]
770 .connections.size());
771 EXPECT_FALSE(
772 mScheduler->mutableAttachedChoreographers()[layer1->getSequence()].frameRate.isValid());
773
774 ASSERT_EQ(1u, mScheduler->mutableAttachedChoreographers().count(layer2->getSequence()));
775 EXPECT_EQ(1u,
776 mScheduler->mutableAttachedChoreographers()[layer2->getSequence()]
777 .connections.size());
778 EXPECT_FALSE(
779 mScheduler->mutableAttachedChoreographers()[layer2->getSequence()].frameRate.isValid());
780}
781
782TEST_F(AttachedChoreographerTest, removedWhenConnectionIsGone) {
783 EXPECT_TRUE(mScheduler->mutableAttachedChoreographers().empty());
784
785 const sp<MockLayer> layer = sp<MockLayer>::make(mFlinger.flinger());
786
787 EXPECT_CALL(mSchedulerCallback, onChoreographerAttached);
788
789 sp<IDisplayEventConnection> connection =
Dominik Laskowski4babfc42024-02-16 12:28:40 -0500790 mScheduler->createDisplayEventConnection(Cycle::Render, {}, layer->getHandle());
Ady Abraham822ecbd2023-07-07 16:16:09 -0700791
792 ASSERT_EQ(1u, mScheduler->mutableAttachedChoreographers().count(layer->getSequence()));
793 EXPECT_EQ(1u,
794 mScheduler->mutableAttachedChoreographers()[layer->getSequence()].connections.size());
795
796 // The connection is used all over this test, so it is quite hard to release it from here.
797 // Instead, we just do a small shortcut.
798 {
799 EXPECT_CALL(*mEventThread, registerDisplayEventConnection(_)).WillOnce(Return(0));
800 sp<MockEventThreadConnection> mockConnection =
801 sp<MockEventThreadConnection>::make(mEventThread);
802 mScheduler->mutableAttachedChoreographers()[layer->getSequence()].connections.clear();
803 mScheduler->mutableAttachedChoreographers()[layer->getSequence()].connections.emplace(
804 mockConnection);
805 }
806
807 RequestedLayerState layerState(LayerCreationArgs(layer->getSequence()));
808 LayerHierarchy hierarchy(&layerState);
809 mScheduler->updateAttachedChoreographers(hierarchy, 60_Hz);
810 EXPECT_TRUE(mScheduler->mutableAttachedChoreographers().empty());
811}
812
813TEST_F(AttachedChoreographerTest, removedWhenLayerIsGone) {
814 EXPECT_TRUE(mScheduler->mutableAttachedChoreographers().empty());
815
816 sp<MockLayer> layer = sp<MockLayer>::make(mFlinger.flinger());
817
818 EXPECT_CALL(mSchedulerCallback, onChoreographerAttached);
819 const sp<IDisplayEventConnection> connection =
Dominik Laskowski4babfc42024-02-16 12:28:40 -0500820 mScheduler->createDisplayEventConnection(Cycle::Render, {}, layer->getHandle());
Ady Abraham822ecbd2023-07-07 16:16:09 -0700821
822 layer.clear();
823 mFlinger.mutableLayersPendingRemoval().clear();
824 EXPECT_TRUE(mScheduler->mutableAttachedChoreographers().empty());
825}
826
827void AttachedChoreographerTest::frameRateTestScenario(Fps layerFps, int8_t frameRateCompatibility,
828 Fps displayFps,
829 Fps expectedChoreographerFps) {
830 const sp<MockLayer> layer = sp<MockLayer>::make(mFlinger.flinger());
831
832 EXPECT_CALL(mSchedulerCallback, onChoreographerAttached);
833 sp<IDisplayEventConnection> connection =
Dominik Laskowski4babfc42024-02-16 12:28:40 -0500834 mScheduler->createDisplayEventConnection(Cycle::Render, {}, layer->getHandle());
Ady Abraham822ecbd2023-07-07 16:16:09 -0700835
836 RequestedLayerState layerState(LayerCreationArgs(layer->getSequence()));
837 LayerHierarchy hierarchy(&layerState);
838
839 layerState.frameRate = layerFps.getValue();
840 layerState.frameRateCompatibility = frameRateCompatibility;
841
842 mScheduler->updateAttachedChoreographers(hierarchy, displayFps);
843
844 ASSERT_EQ(1u, mScheduler->mutableAttachedChoreographers().count(layer->getSequence()));
845 EXPECT_EQ(expectedChoreographerFps,
846 mScheduler->mutableAttachedChoreographers()[layer->getSequence()].frameRate);
847 EXPECT_EQ(expectedChoreographerFps, mEventThreadConnection->frameRate);
848}
849
850TEST_F(AttachedChoreographerTest, setsFrameRateDefault) {
851 Fps layerFps = 30_Hz;
852 int8_t frameRateCompatibility = ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT;
853 Fps displayFps = 60_Hz;
854 Fps expectedChoreographerFps = 30_Hz;
855
856 frameRateTestScenario(layerFps, frameRateCompatibility, displayFps, expectedChoreographerFps);
857
858 layerFps = Fps::fromValue(32.7f);
859 frameRateTestScenario(layerFps, frameRateCompatibility, displayFps, expectedChoreographerFps);
860}
861
862TEST_F(AttachedChoreographerTest, setsFrameRateExact) {
863 Fps layerFps = 30_Hz;
864 int8_t frameRateCompatibility = ANATIVEWINDOW_FRAME_RATE_EXACT;
865 Fps displayFps = 60_Hz;
866 Fps expectedChoreographerFps = 30_Hz;
867
868 frameRateTestScenario(layerFps, frameRateCompatibility, displayFps, expectedChoreographerFps);
869
870 layerFps = Fps::fromValue(32.7f);
871 expectedChoreographerFps = {};
872 frameRateTestScenario(layerFps, frameRateCompatibility, displayFps, expectedChoreographerFps);
873}
874
875TEST_F(AttachedChoreographerTest, setsFrameRateExactOrMultiple) {
876 Fps layerFps = 30_Hz;
877 int8_t frameRateCompatibility = ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_FIXED_SOURCE;
878 Fps displayFps = 60_Hz;
879 Fps expectedChoreographerFps = 30_Hz;
880
881 frameRateTestScenario(layerFps, frameRateCompatibility, displayFps, expectedChoreographerFps);
882
883 layerFps = Fps::fromValue(32.7f);
884 expectedChoreographerFps = {};
885 frameRateTestScenario(layerFps, frameRateCompatibility, displayFps, expectedChoreographerFps);
886}
887
888TEST_F(AttachedChoreographerTest, setsFrameRateParent) {
889 const sp<MockLayer> layer = sp<MockLayer>::make(mFlinger.flinger());
890 const sp<MockLayer> parent = sp<MockLayer>::make(mFlinger.flinger());
891
892 EXPECT_CALL(mSchedulerCallback, onChoreographerAttached);
893 sp<IDisplayEventConnection> connection =
Dominik Laskowski4babfc42024-02-16 12:28:40 -0500894 mScheduler->createDisplayEventConnection(Cycle::Render, {}, parent->getHandle());
Ady Abraham822ecbd2023-07-07 16:16:09 -0700895
896 RequestedLayerState parentState(LayerCreationArgs(parent->getSequence()));
897 LayerHierarchy parentHierarchy(&parentState);
898
899 RequestedLayerState layerState(LayerCreationArgs(layer->getSequence()));
900 LayerHierarchy hierarchy(&layerState);
901 parentHierarchy.mChildren.push_back(
902 std::make_pair(&hierarchy, LayerHierarchy::Variant::Attached));
903
904 layerState.frameRate = (30_Hz).getValue();
905 layerState.frameRateCompatibility = ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT;
906
907 mScheduler->updateAttachedChoreographers(parentHierarchy, 120_Hz);
908
909 ASSERT_EQ(1u, mScheduler->mutableAttachedChoreographers().count(parent->getSequence()));
910
911 EXPECT_EQ(30_Hz, mScheduler->mutableAttachedChoreographers()[parent->getSequence()].frameRate);
912}
913
914TEST_F(AttachedChoreographerTest, setsFrameRateParent2Children) {
915 const sp<MockLayer> layer1 = sp<MockLayer>::make(mFlinger.flinger());
916 const sp<MockLayer> layer2 = sp<MockLayer>::make(mFlinger.flinger());
917 const sp<MockLayer> parent = sp<MockLayer>::make(mFlinger.flinger());
918
919 EXPECT_CALL(mSchedulerCallback, onChoreographerAttached);
920 sp<IDisplayEventConnection> connection =
Dominik Laskowski4babfc42024-02-16 12:28:40 -0500921 mScheduler->createDisplayEventConnection(Cycle::Render, {}, parent->getHandle());
Ady Abraham822ecbd2023-07-07 16:16:09 -0700922
923 RequestedLayerState parentState(LayerCreationArgs(parent->getSequence()));
924 LayerHierarchy parentHierarchy(&parentState);
925
926 RequestedLayerState layer1State(LayerCreationArgs(layer1->getSequence()));
927 LayerHierarchy layer1Hierarchy(&layer1State);
928 parentHierarchy.mChildren.push_back(
929 std::make_pair(&layer1Hierarchy, LayerHierarchy::Variant::Attached));
930
931 RequestedLayerState layer2State(LayerCreationArgs(layer1->getSequence()));
932 LayerHierarchy layer2Hierarchy(&layer2State);
933 parentHierarchy.mChildren.push_back(
934 std::make_pair(&layer2Hierarchy, LayerHierarchy::Variant::Attached));
935
936 layer1State.frameRate = (30_Hz).getValue();
937 layer1State.frameRateCompatibility = ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT;
938
939 layer2State.frameRate = (20_Hz).getValue();
940 layer2State.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(60_Hz, mScheduler->mutableAttachedChoreographers()[parent->getSequence()].frameRate);
947}
948
949TEST_F(AttachedChoreographerTest, setsFrameRateParentConflictingChildren) {
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 = (25_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(Fps(), mScheduler->mutableAttachedChoreographers()[parent->getSequence()].frameRate);
982}
983
984TEST_F(AttachedChoreographerTest, setsFrameRateChild) {
985 const sp<MockLayer> layer = sp<MockLayer>::make(mFlinger.flinger());
986 const sp<MockLayer> parent = sp<MockLayer>::make(mFlinger.flinger());
987
988 EXPECT_CALL(mSchedulerCallback, onChoreographerAttached);
989 sp<IDisplayEventConnection> connection =
Dominik Laskowski4babfc42024-02-16 12:28:40 -0500990 mScheduler->createDisplayEventConnection(Cycle::Render, {}, layer->getHandle());
Ady Abraham822ecbd2023-07-07 16:16:09 -0700991
992 RequestedLayerState parentState(LayerCreationArgs(parent->getSequence()));
993 LayerHierarchy parentHierarchy(&parentState);
994
995 RequestedLayerState layerState(LayerCreationArgs(layer->getSequence()));
996 LayerHierarchy hierarchy(&layerState);
997 parentHierarchy.mChildren.push_back(
998 std::make_pair(&hierarchy, LayerHierarchy::Variant::Attached));
999
1000 parentState.frameRate = (30_Hz).getValue();
1001 parentState.frameRateCompatibility = ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT;
1002
1003 mScheduler->updateAttachedChoreographers(parentHierarchy, 120_Hz);
1004
1005 ASSERT_EQ(1u, mScheduler->mutableAttachedChoreographers().count(layer->getSequence()));
1006
1007 EXPECT_EQ(30_Hz, mScheduler->mutableAttachedChoreographers()[layer->getSequence()].frameRate);
1008}
1009
1010TEST_F(AttachedChoreographerTest, setsFrameRateChildNotOverriddenByParent) {
1011 const sp<MockLayer> layer = sp<MockLayer>::make(mFlinger.flinger());
1012 const sp<MockLayer> parent = sp<MockLayer>::make(mFlinger.flinger());
1013
1014 EXPECT_CALL(mSchedulerCallback, onChoreographerAttached);
1015 sp<IDisplayEventConnection> connection =
Dominik Laskowski4babfc42024-02-16 12:28:40 -05001016 mScheduler->createDisplayEventConnection(Cycle::Render, {}, layer->getHandle());
Ady Abraham822ecbd2023-07-07 16:16:09 -07001017
1018 RequestedLayerState parentState(LayerCreationArgs(parent->getSequence()));
1019 LayerHierarchy parentHierarchy(&parentState);
1020
1021 RequestedLayerState layerState(LayerCreationArgs(layer->getSequence()));
1022 LayerHierarchy hierarchy(&layerState);
1023 parentHierarchy.mChildren.push_back(
1024 std::make_pair(&hierarchy, LayerHierarchy::Variant::Attached));
1025
1026 parentState.frameRate = (30_Hz).getValue();
1027 parentState.frameRateCompatibility = ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT;
1028
1029 layerState.frameRate = (60_Hz).getValue();
1030 layerState.frameRateCompatibility = ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT;
1031
1032 mScheduler->updateAttachedChoreographers(parentHierarchy, 120_Hz);
1033
1034 ASSERT_EQ(1u, mScheduler->mutableAttachedChoreographers().count(layer->getSequence()));
1035
1036 EXPECT_EQ(60_Hz, mScheduler->mutableAttachedChoreographers()[layer->getSequence()].frameRate);
1037}
1038
Dominik Laskowski068173d2021-08-11 17:22:59 -07001039} // namespace android::scheduler