blob: 049b0923a627e738a55bc819ae8513094fbe6c73 [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
Ana Krulec0c8cd522018-08-31 12:27:28 -070060class SchedulerTest : public testing::Test {
61protected:
Ana Krulec85c39af2018-12-26 17:29:57 -080062 class MockEventThreadConnection : public android::EventThreadConnection {
Ana Krulec0c8cd522018-08-31 12:27:28 -070063 public:
Ana Krulec85c39af2018-12-26 17:29:57 -080064 explicit MockEventThreadConnection(EventThread* eventThread)
Ady Abrahamf2851612023-09-25 17:19:00 -070065 : EventThreadConnection(eventThread, /*callingUid*/ static_cast<uid_t>(0)) {}
Ana Krulec0c8cd522018-08-31 12:27:28 -070066 ~MockEventThreadConnection() = default;
67
Huihong Luo6fac5232021-11-22 16:05:23 -080068 MOCK_METHOD1(stealReceiveChannel, binder::Status(gui::BitTube* outChannel));
69 MOCK_METHOD1(setVsyncRate, binder::Status(int count));
70 MOCK_METHOD0(requestNextVsync, binder::Status());
Ana Krulec0c8cd522018-08-31 12:27:28 -070071 };
72
Ana Krulec0c8cd522018-08-31 12:27:28 -070073 SchedulerTest();
Ana Krulec0c8cd522018-08-31 12:27:28 -070074
Dominik Laskowski530d6bd2022-10-10 16:55:54 -040075 static constexpr PhysicalDisplayId kDisplayId1 = PhysicalDisplayId::fromPort(255u);
Ady Abrahamace3d052022-11-17 16:25:05 -080076 static inline const ftl::NonNull<DisplayModePtr> kDisplay1Mode60 =
77 ftl::as_non_null(createDisplayMode(kDisplayId1, DisplayModeId(0), 60_Hz));
78 static inline const ftl::NonNull<DisplayModePtr> kDisplay1Mode120 =
79 ftl::as_non_null(createDisplayMode(kDisplayId1, DisplayModeId(1), 120_Hz));
Dominik Laskowski530d6bd2022-10-10 16:55:54 -040080 static inline const DisplayModes kDisplay1Modes = makeModes(kDisplay1Mode60, kDisplay1Mode120);
81
82 static constexpr PhysicalDisplayId kDisplayId2 = PhysicalDisplayId::fromPort(254u);
Ady Abrahamace3d052022-11-17 16:25:05 -080083 static inline const ftl::NonNull<DisplayModePtr> kDisplay2Mode60 =
84 ftl::as_non_null(createDisplayMode(kDisplayId2, DisplayModeId(0), 60_Hz));
85 static inline const ftl::NonNull<DisplayModePtr> kDisplay2Mode120 =
86 ftl::as_non_null(createDisplayMode(kDisplayId2, DisplayModeId(1), 120_Hz));
Dominik Laskowski530d6bd2022-10-10 16:55:54 -040087 static inline const DisplayModes kDisplay2Modes = makeModes(kDisplay2Mode60, kDisplay2Mode120);
88
89 static constexpr PhysicalDisplayId kDisplayId3 = PhysicalDisplayId::fromPort(253u);
Ady Abrahamace3d052022-11-17 16:25:05 -080090 static inline const ftl::NonNull<DisplayModePtr> kDisplay3Mode60 =
91 ftl::as_non_null(createDisplayMode(kDisplayId3, DisplayModeId(0), 60_Hz));
Dominik Laskowski530d6bd2022-10-10 16:55:54 -040092 static inline const DisplayModes kDisplay3Modes = makeModes(kDisplay3Mode60);
Marin Shalamanov2cde1002021-06-08 19:50:10 +020093
Dominik Laskowskid82e0f02022-10-26 15:23:04 -040094 std::shared_ptr<RefreshRateSelector> mSelector =
95 std::make_shared<RefreshRateSelector>(makeModes(kDisplay1Mode60),
96 kDisplay1Mode60->getId());
Dominik Laskowski983f2b52020-06-25 16:54:06 -070097
Dominik Laskowski8b01cc02020-07-14 19:02:41 -070098 mock::SchedulerCallback mSchedulerCallback;
Leon Scroggins III823d4ca2023-12-12 16:57:34 -050099 TestableSurfaceFlinger mFlinger;
ramindaniae645822024-01-11 10:57:29 -0800100 TestableScheduler* mScheduler = new TestableScheduler{mSelector, mFlinger, mSchedulerCallback};
Vishnu Naira0292282023-12-16 14:32:00 -0800101 surfaceflinger::frontend::LayerHierarchyBuilder mLayerHierarchyBuilder;
Dominik Laskowski98041832019-08-01 18:35:59 -0700102
Dominik Laskowski068173d2021-08-11 17:22:59 -0700103 MockEventThread* mEventThread;
Ana Krulec0c8cd522018-08-31 12:27:28 -0700104 sp<MockEventThreadConnection> mEventThreadConnection;
Ana Krulec0c8cd522018-08-31 12:27:28 -0700105};
106
107SchedulerTest::SchedulerTest() {
Dominik Laskowski068173d2021-08-11 17:22:59 -0700108 auto eventThread = std::make_unique<MockEventThread>();
Ana Krulec0c8cd522018-08-31 12:27:28 -0700109 mEventThread = eventThread.get();
Ana Krulec85c39af2018-12-26 17:29:57 -0800110 EXPECT_CALL(*mEventThread, registerDisplayEventConnection(_)).WillOnce(Return(0));
111
Ady Abrahamd11bade2022-08-01 16:18:03 -0700112 mEventThreadConnection = sp<MockEventThreadConnection>::make(mEventThread);
Ana Krulec0c8cd522018-08-31 12:27:28 -0700113
114 // createConnection call to scheduler makes a createEventConnection call to EventThread. Make
115 // sure that call gets executed and returns an EventThread::Connection object.
Ady Abraham0f4a1b12019-06-04 16:04:04 -0700116 EXPECT_CALL(*mEventThread, createEventConnection(_, _))
Ana Krulec0c8cd522018-08-31 12:27:28 -0700117 .WillRepeatedly(Return(mEventThreadConnection));
118
Dominik Laskowski4babfc42024-02-16 12:28:40 -0500119 mScheduler->setEventThread(Cycle::Render, std::move(eventThread));
Ady Abrahama0a16272021-03-03 15:23:35 -0800120
121 mFlinger.resetScheduler(mScheduler);
Ana Krulec0c8cd522018-08-31 12:27:28 -0700122}
123
Dominik Laskowski8b01cc02020-07-14 19:02:41 -0700124} // namespace
Ana Krulec0c8cd522018-08-31 12:27:28 -0700125
Dominik Laskowski66295432023-03-14 12:25:36 -0400126TEST_F(SchedulerTest, registerDisplay) FTL_FAKE_GUARD(kMainThreadContext) {
Dominik Laskowski008bec02023-03-14 12:04:58 -0400127 // Hardware VSYNC should not change if the display is already registered.
Dominik Laskowski66295432023-03-14 12:25:36 -0400128 EXPECT_CALL(mSchedulerCallback, requestHardwareVsync(kDisplayId1, false)).Times(0);
Dominik Laskowski008bec02023-03-14 12:04:58 -0400129 mScheduler->registerDisplay(kDisplayId1,
130 std::make_shared<RefreshRateSelector>(kDisplay1Modes,
131 kDisplay1Mode60->getId()));
132
Dominik Laskowski66295432023-03-14 12:25:36 -0400133 // TODO(b/241285191): Restore once VsyncSchedule::getPendingHardwareVsyncState is called by
134 // Scheduler::setDisplayPowerMode rather than SF::setPowerModeInternal.
135#if 0
Dominik Laskowski008bec02023-03-14 12:04:58 -0400136 // Hardware VSYNC should be disabled for newly registered displays.
Dominik Laskowski66295432023-03-14 12:25:36 -0400137 EXPECT_CALL(mSchedulerCallback, requestHardwareVsync(kDisplayId2, false)).Times(1);
138 EXPECT_CALL(mSchedulerCallback, requestHardwareVsync(kDisplayId3, false)).Times(1);
139#endif
Dominik Laskowski008bec02023-03-14 12:04:58 -0400140
141 mScheduler->registerDisplay(kDisplayId2,
142 std::make_shared<RefreshRateSelector>(kDisplay2Modes,
143 kDisplay2Mode60->getId()));
144 mScheduler->registerDisplay(kDisplayId3,
145 std::make_shared<RefreshRateSelector>(kDisplay3Modes,
146 kDisplay3Mode60->getId()));
Dominik Laskowski66295432023-03-14 12:25:36 -0400147
148 EXPECT_FALSE(mScheduler->getVsyncSchedule(kDisplayId1)->getPendingHardwareVsyncState());
149 EXPECT_FALSE(mScheduler->getVsyncSchedule(kDisplayId2)->getPendingHardwareVsyncState());
150 EXPECT_FALSE(mScheduler->getVsyncSchedule(kDisplayId3)->getPendingHardwareVsyncState());
Dominik Laskowski008bec02023-03-14 12:04:58 -0400151}
152
Marin Shalamanov2cde1002021-06-08 19:50:10 +0200153TEST_F(SchedulerTest, chooseRefreshRateForContentIsNoopWhenModeSwitchingIsNotSupported) {
154 // The layer is registered at creation time and deregistered at destruction time.
Dominik Laskowski068173d2021-08-11 17:22:59 -0700155 sp<MockLayer> layer = sp<MockLayer>::make(mFlinger.flinger());
Dominik Laskowski983f2b52020-06-25 16:54:06 -0700156
Marin Shalamanov2cde1002021-06-08 19:50:10 +0200157 // recordLayerHistory should be a noop
Dominik Laskowski9c93d602021-10-07 19:38:26 -0700158 ASSERT_EQ(0u, mScheduler->getNumActiveLayers());
Vishnu Nair47b7bb42023-09-29 16:27:33 -0700159 mScheduler->recordLayerHistory(layer->getSequence(), layer->getLayerProps(), 0, 0,
Vishnu Nairef68d6d2023-02-28 06:18:27 +0000160 LayerHistory::LayerUpdateType::Buffer);
Dominik Laskowski9c93d602021-10-07 19:38:26 -0700161 ASSERT_EQ(0u, mScheduler->getNumActiveLayers());
Dominik Laskowski983f2b52020-06-25 16:54:06 -0700162
Rachel Lee6a9731d2022-06-06 17:08:14 -0700163 constexpr hal::PowerMode kPowerModeOn = hal::PowerMode::ON;
Leon Scroggins III67388622023-02-06 20:36:20 -0500164 FTL_FAKE_GUARD(kMainThreadContext, mScheduler->setDisplayPowerMode(kDisplayId1, kPowerModeOn));
Dominik Laskowski983f2b52020-06-25 16:54:06 -0700165
166 constexpr uint32_t kDisplayArea = 999'999;
Ady Abrahamed3290f2021-05-17 15:12:14 -0700167 mScheduler->onActiveDisplayAreaChanged(kDisplayArea);
Dominik Laskowski983f2b52020-06-25 16:54:06 -0700168
ramindani69b58e82022-09-26 16:48:36 -0700169 EXPECT_CALL(mSchedulerCallback, requestDisplayModes(_)).Times(0);
Ady Abraham822ecbd2023-07-07 16:16:09 -0700170 mScheduler->chooseRefreshRateForContent(/*LayerHierarchy*/ nullptr,
171 /*updateAttachedChoreographer*/ false);
Dominik Laskowski983f2b52020-06-25 16:54:06 -0700172}
173
Marin Shalamanov2cde1002021-06-08 19:50:10 +0200174TEST_F(SchedulerTest, updateDisplayModes) {
Dominik Laskowski9c93d602021-10-07 19:38:26 -0700175 ASSERT_EQ(0u, mScheduler->layerHistorySize());
Dominik Laskowski068173d2021-08-11 17:22:59 -0700176 sp<MockLayer> layer = sp<MockLayer>::make(mFlinger.flinger());
Dominik Laskowski9c93d602021-10-07 19:38:26 -0700177 ASSERT_EQ(1u, mScheduler->layerHistorySize());
Marin Shalamanov2cde1002021-06-08 19:50:10 +0200178
Dominik Laskowski596a2562022-10-28 11:26:12 -0400179 // Replace `mSelector` with a new `RefreshRateSelector` that has different display modes.
180 mScheduler->registerDisplay(kDisplayId1,
181 std::make_shared<RefreshRateSelector>(kDisplay1Modes,
182 kDisplay1Mode60->getId()));
Marin Shalamanov2cde1002021-06-08 19:50:10 +0200183
Dominik Laskowski9c93d602021-10-07 19:38:26 -0700184 ASSERT_EQ(0u, mScheduler->getNumActiveLayers());
Vishnu Nair47b7bb42023-09-29 16:27:33 -0700185 mScheduler->recordLayerHistory(layer->getSequence(), layer->getLayerProps(), 0, 0,
Vishnu Nairef68d6d2023-02-28 06:18:27 +0000186 LayerHistory::LayerUpdateType::Buffer);
Dominik Laskowski9c93d602021-10-07 19:38:26 -0700187 ASSERT_EQ(1u, mScheduler->getNumActiveLayers());
Marin Shalamanov2cde1002021-06-08 19:50:10 +0200188}
189
Dominik Laskowski068173d2021-08-11 17:22:59 -0700190TEST_F(SchedulerTest, dispatchCachedReportedMode) {
191 mScheduler->clearCachedReportedMode();
192
Ady Abraham690f4612021-07-01 23:24:03 -0700193 EXPECT_CALL(*mEventThread, onModeChanged(_)).Times(0);
Dominik Laskowski068173d2021-08-11 17:22:59 -0700194 EXPECT_NO_FATAL_FAILURE(mScheduler->dispatchCachedReportedMode());
Ana Krulec6ddd2612020-09-24 13:06:33 -0700195}
196
Ady Abraham899dcdb2021-06-15 16:56:21 -0700197TEST_F(SchedulerTest, calculateMaxAcquiredBufferCount) {
Dominik Laskowski6eab42d2021-09-13 14:34:13 -0700198 EXPECT_EQ(1, mFlinger.calculateMaxAcquiredBufferCount(60_Hz, 30ms));
199 EXPECT_EQ(2, mFlinger.calculateMaxAcquiredBufferCount(90_Hz, 30ms));
200 EXPECT_EQ(3, mFlinger.calculateMaxAcquiredBufferCount(120_Hz, 30ms));
Ady Abraham564f9de2021-02-03 18:34:33 -0800201
Dominik Laskowski6eab42d2021-09-13 14:34:13 -0700202 EXPECT_EQ(2, mFlinger.calculateMaxAcquiredBufferCount(60_Hz, 40ms));
Ady Abraham564f9de2021-02-03 18:34:33 -0800203
Dominik Laskowski6eab42d2021-09-13 14:34:13 -0700204 EXPECT_EQ(1, mFlinger.calculateMaxAcquiredBufferCount(60_Hz, 10ms));
Lloyd Piquea1456c12023-05-17 12:11:15 -0700205
Lloyd Pique30db6402023-06-26 18:56:51 +0000206 const auto savedMinAcquiredBuffers = mFlinger.mutableMinAcquiredBuffers();
207 mFlinger.mutableMinAcquiredBuffers() = 2;
Lloyd Piquea1456c12023-05-17 12:11:15 -0700208 EXPECT_EQ(2, mFlinger.calculateMaxAcquiredBufferCount(60_Hz, 10ms));
Lloyd Pique30db6402023-06-26 18:56:51 +0000209 mFlinger.mutableMinAcquiredBuffers() = savedMinAcquiredBuffers;
Ady Abraham564f9de2021-02-03 18:34:33 -0800210}
211
Marin Shalamanov4c7831e2021-06-08 20:44:06 +0200212MATCHER(Is120Hz, "") {
Ady Abrahamace3d052022-11-17 16:25:05 -0800213 return isApproxEqual(arg.front().mode.fps, 120_Hz);
Marin Shalamanov4c7831e2021-06-08 20:44:06 +0200214}
215
216TEST_F(SchedulerTest, chooseRefreshRateForContentSelectsMaxRefreshRate) {
Dominik Laskowski596a2562022-10-28 11:26:12 -0400217 mScheduler->registerDisplay(kDisplayId1,
218 std::make_shared<RefreshRateSelector>(kDisplay1Modes,
219 kDisplay1Mode60->getId()));
Marin Shalamanov4c7831e2021-06-08 20:44:06 +0200220
Dominik Laskowski0c41ffa2021-12-24 16:45:12 -0800221 const sp<MockLayer> layer = sp<MockLayer>::make(mFlinger.flinger());
222 EXPECT_CALL(*layer, isVisible()).WillOnce(Return(true));
Marin Shalamanov4c7831e2021-06-08 20:44:06 +0200223
Vishnu Nair47b7bb42023-09-29 16:27:33 -0700224 mScheduler->recordLayerHistory(layer->getSequence(), layer->getLayerProps(), 0, systemTime(),
Vishnu Nairef68d6d2023-02-28 06:18:27 +0000225 LayerHistory::LayerUpdateType::Buffer);
Marin Shalamanov4c7831e2021-06-08 20:44:06 +0200226
Rachel Lee6a9731d2022-06-06 17:08:14 -0700227 constexpr hal::PowerMode kPowerModeOn = hal::PowerMode::ON;
Leon Scroggins III67388622023-02-06 20:36:20 -0500228 FTL_FAKE_GUARD(kMainThreadContext, mScheduler->setDisplayPowerMode(kDisplayId1, kPowerModeOn));
Marin Shalamanov4c7831e2021-06-08 20:44:06 +0200229
230 constexpr uint32_t kDisplayArea = 999'999;
Ady Abrahamed3290f2021-05-17 15:12:14 -0700231 mScheduler->onActiveDisplayAreaChanged(kDisplayArea);
Marin Shalamanov4c7831e2021-06-08 20:44:06 +0200232
ramindani69b58e82022-09-26 16:48:36 -0700233 EXPECT_CALL(mSchedulerCallback, requestDisplayModes(Is120Hz())).Times(1);
Ady Abraham822ecbd2023-07-07 16:16:09 -0700234 mScheduler->chooseRefreshRateForContent(/*LayerHierarchy*/ nullptr,
235 /*updateAttachedChoreographer*/ false);
Dominik Laskowski0c41ffa2021-12-24 16:45:12 -0800236
237 // No-op if layer requirements have not changed.
ramindani69b58e82022-09-26 16:48:36 -0700238 EXPECT_CALL(mSchedulerCallback, requestDisplayModes(_)).Times(0);
Ady Abraham822ecbd2023-07-07 16:16:09 -0700239 mScheduler->chooseRefreshRateForContent(/*LayerHierarchy*/ nullptr,
240 /*updateAttachedChoreographer*/ false);
Marin Shalamanov4c7831e2021-06-08 20:44:06 +0200241}
242
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400243TEST_F(SchedulerTest, chooseDisplayModesSingleDisplay) {
Dominik Laskowskib5a094b2022-10-27 12:00:12 -0400244 mScheduler->registerDisplay(kDisplayId1,
245 std::make_shared<RefreshRateSelector>(kDisplay1Modes,
246 kDisplay1Mode60->getId()));
ramindani69b58e82022-09-26 16:48:36 -0700247
Dominik Laskowskid82e0f02022-10-26 15:23:04 -0400248 std::vector<RefreshRateSelector::LayerRequirement> layers =
249 std::vector<RefreshRateSelector::LayerRequirement>({{.weight = 1.f}, {.weight = 1.f}});
ramindani69b58e82022-09-26 16:48:36 -0700250 mScheduler->setContentRequirements(layers);
251 GlobalSignals globalSignals = {.idle = true};
252 mScheduler->setTouchStateAndIdleTimerPolicy(globalSignals);
253
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400254 using DisplayModeChoice = TestableScheduler::DisplayModeChoice;
255
256 auto modeChoices = mScheduler->chooseDisplayModes();
257 ASSERT_EQ(1u, modeChoices.size());
258
259 auto choice = modeChoices.get(kDisplayId1);
260 ASSERT_TRUE(choice);
Ady Abrahamace3d052022-11-17 16:25:05 -0800261 EXPECT_EQ(choice->get(), DisplayModeChoice({60_Hz, kDisplay1Mode60}, globalSignals));
ramindani69b58e82022-09-26 16:48:36 -0700262
263 globalSignals = {.idle = false};
264 mScheduler->setTouchStateAndIdleTimerPolicy(globalSignals);
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400265
266 modeChoices = mScheduler->chooseDisplayModes();
267 ASSERT_EQ(1u, modeChoices.size());
268
269 choice = modeChoices.get(kDisplayId1);
270 ASSERT_TRUE(choice);
Ady Abrahamace3d052022-11-17 16:25:05 -0800271 EXPECT_EQ(choice->get(), DisplayModeChoice({120_Hz, kDisplay1Mode120}, globalSignals));
ramindani69b58e82022-09-26 16:48:36 -0700272
273 globalSignals = {.touch = true};
274 mScheduler->replaceTouchTimer(10);
275 mScheduler->setTouchStateAndIdleTimerPolicy(globalSignals);
ramindani69b58e82022-09-26 16:48:36 -0700276
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400277 modeChoices = mScheduler->chooseDisplayModes();
278 ASSERT_EQ(1u, modeChoices.size());
279
280 choice = modeChoices.get(kDisplayId1);
281 ASSERT_TRUE(choice);
Ady Abrahamace3d052022-11-17 16:25:05 -0800282 EXPECT_EQ(choice->get(), DisplayModeChoice({120_Hz, kDisplay1Mode120}, globalSignals));
ramindani69b58e82022-09-26 16:48:36 -0700283}
284
Rachel Lee6ed96c92024-02-07 14:37:38 -0800285TEST_F(SchedulerTest, chooseDisplayModesSingleDisplayHighHintTouchSignal) {
286 mScheduler->registerDisplay(kDisplayId1,
287 std::make_shared<RefreshRateSelector>(kDisplay1Modes,
288 kDisplay1Mode60->getId()));
289
290 using DisplayModeChoice = TestableScheduler::DisplayModeChoice;
291
292 std::vector<RefreshRateSelector::LayerRequirement> layers =
293 std::vector<RefreshRateSelector::LayerRequirement>({{.weight = 1.f}, {.weight = 1.f}});
294 auto& lr1 = layers[0];
295 auto& lr2 = layers[1];
296
297 // Scenario that is similar to game. Expects no touch boost.
298 lr1.vote = RefreshRateSelector::LayerVoteType::ExplicitCategory;
299 lr1.frameRateCategory = FrameRateCategory::HighHint;
300 lr1.name = "ExplicitCategory HighHint";
301 lr2.vote = RefreshRateSelector::LayerVoteType::ExplicitDefault;
302 lr2.desiredRefreshRate = 30_Hz;
303 lr2.name = "30Hz ExplicitDefault";
304 mScheduler->setContentRequirements(layers);
305 auto modeChoices = mScheduler->chooseDisplayModes();
306 ASSERT_EQ(1u, modeChoices.size());
307 auto choice = modeChoices.get(kDisplayId1);
308 ASSERT_TRUE(choice);
309 EXPECT_EQ(choice->get(), DisplayModeChoice({60_Hz, kDisplay1Mode60}, {.touch = false}));
310
311 // Scenario that is similar to video playback and interaction. Expects touch boost.
312 lr1.vote = RefreshRateSelector::LayerVoteType::ExplicitCategory;
313 lr1.frameRateCategory = FrameRateCategory::HighHint;
314 lr1.name = "ExplicitCategory HighHint";
315 lr2.vote = RefreshRateSelector::LayerVoteType::ExplicitExactOrMultiple;
316 lr2.desiredRefreshRate = 30_Hz;
317 lr2.name = "30Hz ExplicitExactOrMultiple";
318 mScheduler->setContentRequirements(layers);
319 modeChoices = mScheduler->chooseDisplayModes();
320 ASSERT_EQ(1u, modeChoices.size());
321 choice = modeChoices.get(kDisplayId1);
322 ASSERT_TRUE(choice);
323 EXPECT_EQ(choice->get(), DisplayModeChoice({120_Hz, kDisplay1Mode120}, {.touch = true}));
324
325 // Scenario with explicit category and HighHint. Expects touch boost.
326 lr1.vote = RefreshRateSelector::LayerVoteType::ExplicitCategory;
327 lr1.frameRateCategory = FrameRateCategory::HighHint;
328 lr1.name = "ExplicitCategory HighHint";
329 lr2.vote = RefreshRateSelector::LayerVoteType::ExplicitCategory;
330 lr2.frameRateCategory = FrameRateCategory::Low;
331 lr2.name = "ExplicitCategory Low";
332 mScheduler->setContentRequirements(layers);
333 modeChoices = mScheduler->chooseDisplayModes();
334 ASSERT_EQ(1u, modeChoices.size());
335 choice = modeChoices.get(kDisplayId1);
336 ASSERT_TRUE(choice);
337 EXPECT_EQ(choice->get(), DisplayModeChoice({120_Hz, kDisplay1Mode120}, {.touch = true}));
338}
339
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400340TEST_F(SchedulerTest, chooseDisplayModesMultipleDisplays) {
Dominik Laskowskib5a094b2022-10-27 12:00:12 -0400341 mScheduler->registerDisplay(kDisplayId1,
342 std::make_shared<RefreshRateSelector>(kDisplay1Modes,
343 kDisplay1Mode60->getId()));
344 mScheduler->registerDisplay(kDisplayId2,
345 std::make_shared<RefreshRateSelector>(kDisplay2Modes,
346 kDisplay2Mode60->getId()));
ramindani69b58e82022-09-26 16:48:36 -0700347
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400348 using DisplayModeChoice = TestableScheduler::DisplayModeChoice;
349 TestableScheduler::DisplayModeChoiceMap expectedChoices;
ramindani69b58e82022-09-26 16:48:36 -0700350
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400351 {
352 const GlobalSignals globalSignals = {.idle = true};
353 expectedChoices =
354 ftl::init::map<const PhysicalDisplayId&,
Ady Abrahamace3d052022-11-17 16:25:05 -0800355 DisplayModeChoice>(kDisplayId1,
356 FrameRateMode{60_Hz, kDisplay1Mode60},
357 globalSignals)(kDisplayId2,
358 FrameRateMode{60_Hz,
359 kDisplay2Mode60},
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400360 globalSignals);
361
Dominik Laskowskid82e0f02022-10-26 15:23:04 -0400362 std::vector<RefreshRateSelector::LayerRequirement> layers = {{.weight = 1.f},
363 {.weight = 1.f}};
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400364 mScheduler->setContentRequirements(layers);
365 mScheduler->setTouchStateAndIdleTimerPolicy(globalSignals);
366
367 const auto actualChoices = mScheduler->chooseDisplayModes();
368 EXPECT_EQ(expectedChoices, actualChoices);
ramindani69b58e82022-09-26 16:48:36 -0700369 }
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400370 {
371 const GlobalSignals globalSignals = {.idle = false};
372 expectedChoices =
373 ftl::init::map<const PhysicalDisplayId&,
Ady Abrahamace3d052022-11-17 16:25:05 -0800374 DisplayModeChoice>(kDisplayId1,
375 FrameRateMode{120_Hz, kDisplay1Mode120},
376 globalSignals)(kDisplayId2,
377 FrameRateMode{120_Hz,
378 kDisplay2Mode120},
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400379 globalSignals);
ramindani69b58e82022-09-26 16:48:36 -0700380
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400381 mScheduler->setTouchStateAndIdleTimerPolicy(globalSignals);
ramindani69b58e82022-09-26 16:48:36 -0700382
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400383 const auto actualChoices = mScheduler->chooseDisplayModes();
384 EXPECT_EQ(expectedChoices, actualChoices);
ramindani69b58e82022-09-26 16:48:36 -0700385 }
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400386 {
387 const GlobalSignals globalSignals = {.touch = true};
388 mScheduler->replaceTouchTimer(10);
389 mScheduler->setTouchStateAndIdleTimerPolicy(globalSignals);
ramindani69b58e82022-09-26 16:48:36 -0700390
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400391 expectedChoices =
392 ftl::init::map<const PhysicalDisplayId&,
Ady Abrahamace3d052022-11-17 16:25:05 -0800393 DisplayModeChoice>(kDisplayId1,
394 FrameRateMode{120_Hz, kDisplay1Mode120},
395 globalSignals)(kDisplayId2,
396 FrameRateMode{120_Hz,
397 kDisplay2Mode120},
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400398 globalSignals);
399
400 const auto actualChoices = mScheduler->chooseDisplayModes();
401 EXPECT_EQ(expectedChoices, actualChoices);
ramindani69b58e82022-09-26 16:48:36 -0700402 }
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400403 {
ramindani22f2ead2023-04-21 10:27:11 -0700404 // The kDisplayId3 does not support 120Hz, The pacesetter display rate is chosen to be 120
405 // Hz. In this case only the display kDisplayId3 choose 60Hz as it does not support 120Hz.
Dominik Laskowskib5a094b2022-10-27 12:00:12 -0400406 mScheduler
407 ->registerDisplay(kDisplayId3,
408 std::make_shared<RefreshRateSelector>(kDisplay3Modes,
409 kDisplay3Mode60->getId()));
Dominik Laskowski327d6092022-10-11 18:05:08 -0400410
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400411 const GlobalSignals globalSignals = {.touch = true};
412 mScheduler->replaceTouchTimer(10);
413 mScheduler->setTouchStateAndIdleTimerPolicy(globalSignals);
ramindani7c487282022-10-10 16:17:51 -0700414
Ady Abrahamace3d052022-11-17 16:25:05 -0800415 expectedChoices = ftl::init::map<
416 const PhysicalDisplayId&,
ramindani22f2ead2023-04-21 10:27:11 -0700417 DisplayModeChoice>(kDisplayId1, FrameRateMode{120_Hz, kDisplay1Mode120},
418 globalSignals)(kDisplayId2,
419 FrameRateMode{120_Hz, kDisplay2Mode120},
420 globalSignals)(kDisplayId3,
421 FrameRateMode{60_Hz,
422 kDisplay3Mode60},
423 globalSignals);
424
425 const auto actualChoices = mScheduler->chooseDisplayModes();
426 EXPECT_EQ(expectedChoices, actualChoices);
427 }
428 {
429 // We should choose 60Hz despite the touch signal as pacesetter only supports 60Hz
430 mScheduler->setPacesetterDisplay(kDisplayId3);
431 const GlobalSignals globalSignals = {.touch = true};
432 mScheduler->replaceTouchTimer(10);
433 mScheduler->setTouchStateAndIdleTimerPolicy(globalSignals);
434
435 expectedChoices = ftl::init::map<
436 const PhysicalDisplayId&,
Ady Abrahamace3d052022-11-17 16:25:05 -0800437 DisplayModeChoice>(kDisplayId1, FrameRateMode{60_Hz, kDisplay1Mode60},
438 globalSignals)(kDisplayId2,
439 FrameRateMode{60_Hz, kDisplay2Mode60},
440 globalSignals)(kDisplayId3,
441 FrameRateMode{60_Hz,
442 kDisplay3Mode60},
443 globalSignals);
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400444
445 const auto actualChoices = mScheduler->chooseDisplayModes();
446 EXPECT_EQ(expectedChoices, actualChoices);
ramindani7c487282022-10-10 16:17:51 -0700447 }
ramindani69b58e82022-09-26 16:48:36 -0700448}
449
Dominik Laskowski50e2e4d2023-10-04 10:58:28 -0400450TEST_F(SchedulerTest, onFrameSignalMultipleDisplays) {
451 mScheduler->registerDisplay(kDisplayId1,
452 std::make_shared<RefreshRateSelector>(kDisplay1Modes,
453 kDisplay1Mode60->getId()));
454 mScheduler->registerDisplay(kDisplayId2,
455 std::make_shared<RefreshRateSelector>(kDisplay2Modes,
456 kDisplay2Mode60->getId()));
457
458 using VsyncIds = std::vector<std::pair<PhysicalDisplayId, VsyncId>>;
459
460 struct Compositor final : ICompositor {
Dominik Laskowskifb4b7372023-11-22 09:56:54 -0500461 explicit Compositor(TestableScheduler& scheduler) : scheduler(scheduler) {}
462
463 TestableScheduler& scheduler;
464
465 struct {
466 PhysicalDisplayId commit;
467 PhysicalDisplayId composite;
468 } pacesetterIds;
469
470 struct {
471 VsyncIds commit;
472 VsyncIds composite;
473 } vsyncIds;
474
Dominik Laskowski50e2e4d2023-10-04 10:58:28 -0400475 bool committed = true;
Dominik Laskowskifb4b7372023-11-22 09:56:54 -0500476 bool changePacesetter = false;
Dominik Laskowski50e2e4d2023-10-04 10:58:28 -0400477
478 void configure() override {}
479
Dominik Laskowskifb4b7372023-11-22 09:56:54 -0500480 bool commit(PhysicalDisplayId pacesetterId,
481 const scheduler::FrameTargets& targets) override {
482 pacesetterIds.commit = pacesetterId;
483
484 vsyncIds.commit.clear();
485 vsyncIds.composite.clear();
Dominik Laskowski50e2e4d2023-10-04 10:58:28 -0400486
487 for (const auto& [id, target] : targets) {
Dominik Laskowskifb4b7372023-11-22 09:56:54 -0500488 vsyncIds.commit.emplace_back(id, target->vsyncId());
489 }
490
491 if (changePacesetter) {
492 scheduler.setPacesetterDisplay(kDisplayId2);
Dominik Laskowski50e2e4d2023-10-04 10:58:28 -0400493 }
494
495 return committed;
496 }
497
Dominik Laskowskifb4b7372023-11-22 09:56:54 -0500498 CompositeResultsPerDisplay composite(PhysicalDisplayId pacesetterId,
499 const scheduler::FrameTargeters& targeters) override {
500 pacesetterIds.composite = pacesetterId;
501
Dominik Laskowski50e2e4d2023-10-04 10:58:28 -0400502 CompositeResultsPerDisplay results;
503
Dominik Laskowskifb4b7372023-11-22 09:56:54 -0500504 for (const auto& [id, targeter] : targeters) {
505 vsyncIds.composite.emplace_back(id, targeter->target().vsyncId());
Dominik Laskowski50e2e4d2023-10-04 10:58:28 -0400506 results.try_emplace(id,
507 CompositeResult{.compositionCoverage =
508 CompositionCoverage::Hwc});
509 }
510
511 return results;
512 }
513
514 void sample() override {}
ramindaniae645822024-01-11 10:57:29 -0800515 void sendNotifyExpectedPresentHint(PhysicalDisplayId) override {}
Dominik Laskowskifb4b7372023-11-22 09:56:54 -0500516 } compositor(*mScheduler);
Dominik Laskowski50e2e4d2023-10-04 10:58:28 -0400517
518 mScheduler->doFrameSignal(compositor, VsyncId(42));
519
Dominik Laskowskifb4b7372023-11-22 09:56:54 -0500520 const auto makeVsyncIds = [](VsyncId vsyncId, bool swap = false) -> VsyncIds {
521 if (swap) {
522 return {{kDisplayId2, vsyncId}, {kDisplayId1, vsyncId}};
523 } else {
524 return {{kDisplayId1, vsyncId}, {kDisplayId2, vsyncId}};
525 }
Dominik Laskowski50e2e4d2023-10-04 10:58:28 -0400526 };
527
Dominik Laskowskifb4b7372023-11-22 09:56:54 -0500528 EXPECT_EQ(kDisplayId1, compositor.pacesetterIds.commit);
529 EXPECT_EQ(kDisplayId1, compositor.pacesetterIds.composite);
530 EXPECT_EQ(makeVsyncIds(VsyncId(42)), compositor.vsyncIds.commit);
531 EXPECT_EQ(makeVsyncIds(VsyncId(42)), compositor.vsyncIds.composite);
Dominik Laskowski50e2e4d2023-10-04 10:58:28 -0400532
Dominik Laskowskifb4b7372023-11-22 09:56:54 -0500533 // FrameTargets should be updated despite the skipped commit.
Dominik Laskowski50e2e4d2023-10-04 10:58:28 -0400534 compositor.committed = false;
535 mScheduler->doFrameSignal(compositor, VsyncId(43));
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(43)), compositor.vsyncIds.commit);
540 EXPECT_TRUE(compositor.vsyncIds.composite.empty());
541
542 // The pacesetter may change during commit.
543 compositor.committed = true;
544 compositor.changePacesetter = true;
545 mScheduler->doFrameSignal(compositor, VsyncId(44));
546
547 EXPECT_EQ(kDisplayId1, compositor.pacesetterIds.commit);
548 EXPECT_EQ(kDisplayId2, compositor.pacesetterIds.composite);
549 EXPECT_EQ(makeVsyncIds(VsyncId(44)), compositor.vsyncIds.commit);
550 EXPECT_EQ(makeVsyncIds(VsyncId(44), true), compositor.vsyncIds.composite);
Dominik Laskowski50e2e4d2023-10-04 10:58:28 -0400551}
552
ramindani0491e642023-11-16 17:42:14 -0800553TEST_F(SchedulerTest, nextFrameIntervalTest) {
554 SET_FLAG_FOR_TEST(flags::vrr_config, true);
555
556 static constexpr size_t kHistorySize = 10;
557 static constexpr size_t kMinimumSamplesForPrediction = 6;
558 static constexpr size_t kOutlierTolerancePercent = 25;
559 const auto refreshRate = Fps::fromPeriodNsecs(500);
560 auto frameRate = Fps::fromPeriodNsecs(1000);
561
562 const ftl::NonNull<DisplayModePtr> kMode = ftl::as_non_null(
563 createVrrDisplayMode(DisplayModeId(0), refreshRate,
564 hal::VrrConfig{.minFrameIntervalNs = static_cast<int32_t>(
565 frameRate.getPeriodNsecs())}));
566 std::shared_ptr<VSyncPredictor> vrrTracker =
Ady Abraham20024aa2024-03-05 01:32:49 +0000567 std::make_shared<VSyncPredictor>(std::make_unique<SystemClock>(), kMode, kHistorySize,
568 kMinimumSamplesForPrediction,
ramindaniae645822024-01-11 10:57:29 -0800569 kOutlierTolerancePercent);
ramindani0491e642023-11-16 17:42:14 -0800570 std::shared_ptr<RefreshRateSelector> vrrSelectorPtr =
571 std::make_shared<RefreshRateSelector>(makeModes(kMode), kMode->getId());
572 TestableScheduler scheduler{std::make_unique<android::mock::VsyncController>(),
573 vrrTracker,
574 vrrSelectorPtr,
Leon Scroggins III823d4ca2023-12-12 16:57:34 -0500575 mFlinger.getFactory(),
576 mFlinger.getTimeStats(),
ramindaniae645822024-01-11 10:57:29 -0800577 mSchedulerCallback};
ramindani0491e642023-11-16 17:42:14 -0800578
579 scheduler.registerDisplay(kMode->getPhysicalDisplayId(), vrrSelectorPtr, vrrTracker);
580 vrrSelectorPtr->setActiveMode(kMode->getId(), frameRate);
581 scheduler.setRenderRate(kMode->getPhysicalDisplayId(), frameRate);
582 vrrTracker->addVsyncTimestamp(0);
Ady Abraham20024aa2024-03-05 01:32:49 +0000583 // Set 1000 as vsync seq #0
584 vrrTracker->nextAnticipatedVSyncTimeFrom(700);
ramindani0491e642023-11-16 17:42:14 -0800585
ramindani0491e642023-11-16 17:42:14 -0800586 EXPECT_EQ(Fps::fromPeriodNsecs(1000),
587 scheduler.getNextFrameInterval(kMode->getPhysicalDisplayId(),
Ady Abraham4335afd2023-12-18 19:10:47 -0800588 TimePoint::fromNs(1000)));
ramindani0491e642023-11-16 17:42:14 -0800589 EXPECT_EQ(Fps::fromPeriodNsecs(1000),
590 scheduler.getNextFrameInterval(kMode->getPhysicalDisplayId(),
Ady Abraham4335afd2023-12-18 19:10:47 -0800591 TimePoint::fromNs(2000)));
ramindani0491e642023-11-16 17:42:14 -0800592
Ady Abraham4335afd2023-12-18 19:10:47 -0800593 // Not crossing the min frame period
Ady Abraham20024aa2024-03-05 01:32:49 +0000594 EXPECT_EQ(Fps::fromPeriodNsecs(1000),
Ady Abraham4335afd2023-12-18 19:10:47 -0800595 scheduler.getNextFrameInterval(kMode->getPhysicalDisplayId(),
596 TimePoint::fromNs(2500)));
ramindani0491e642023-11-16 17:42:14 -0800597 // Change render rate
598 frameRate = Fps::fromPeriodNsecs(2000);
599 vrrSelectorPtr->setActiveMode(kMode->getId(), frameRate);
600 scheduler.setRenderRate(kMode->getPhysicalDisplayId(), frameRate);
601
Ady Abraham20024aa2024-03-05 01:32:49 +0000602 // Set 2000 as vsync seq #0
603 vrrTracker->nextAnticipatedVSyncTimeFrom(1700);
604
ramindani0491e642023-11-16 17:42:14 -0800605 EXPECT_EQ(Fps::fromPeriodNsecs(2000),
606 scheduler.getNextFrameInterval(kMode->getPhysicalDisplayId(),
Ady Abraham4335afd2023-12-18 19:10:47 -0800607 TimePoint::fromNs(2000)));
ramindani0491e642023-11-16 17:42:14 -0800608 EXPECT_EQ(Fps::fromPeriodNsecs(2000),
609 scheduler.getNextFrameInterval(kMode->getPhysicalDisplayId(),
Ady Abraham4335afd2023-12-18 19:10:47 -0800610 TimePoint::fromNs(4000)));
ramindani0491e642023-11-16 17:42:14 -0800611}
612
Leon Scroggins III792ea802023-11-27 17:32:51 -0500613TEST_F(SchedulerTest, resyncAllToHardwareVsync) FTL_FAKE_GUARD(kMainThreadContext) {
614 // resyncAllToHardwareVsync will result in requesting hardware VSYNC on both displays, since
615 // they are both on.
616 EXPECT_CALL(mScheduler->mockRequestHardwareVsync, Call(kDisplayId1, true)).Times(1);
617 EXPECT_CALL(mScheduler->mockRequestHardwareVsync, Call(kDisplayId2, true)).Times(1);
618
619 mScheduler->registerDisplay(kDisplayId2,
620 std::make_shared<RefreshRateSelector>(kDisplay2Modes,
621 kDisplay2Mode60->getId()));
622 mScheduler->setDisplayPowerMode(kDisplayId1, hal::PowerMode::ON);
623 mScheduler->setDisplayPowerMode(kDisplayId2, hal::PowerMode::ON);
624
625 static constexpr bool kDisallow = true;
626 mScheduler->disableHardwareVsync(kDisplayId1, kDisallow);
627 mScheduler->disableHardwareVsync(kDisplayId2, kDisallow);
628
629 static constexpr bool kAllowToEnable = true;
630 mScheduler->resyncAllToHardwareVsync(kAllowToEnable);
631}
632
633TEST_F(SchedulerTest, resyncAllDoNotAllow) FTL_FAKE_GUARD(kMainThreadContext) {
634 // Without setting allowToEnable to true, resyncAllToHardwareVsync does not
635 // result in requesting hardware VSYNC.
636 EXPECT_CALL(mScheduler->mockRequestHardwareVsync, Call(kDisplayId1, _)).Times(0);
637
638 mScheduler->setDisplayPowerMode(kDisplayId1, hal::PowerMode::ON);
639
640 static constexpr bool kDisallow = true;
641 mScheduler->disableHardwareVsync(kDisplayId1, kDisallow);
642
643 static constexpr bool kAllowToEnable = false;
644 mScheduler->resyncAllToHardwareVsync(kAllowToEnable);
645}
646
647TEST_F(SchedulerTest, resyncAllSkipsOffDisplays) FTL_FAKE_GUARD(kMainThreadContext) {
648 SET_FLAG_FOR_TEST(flags::multithreaded_present, true);
649
650 // resyncAllToHardwareVsync will result in requesting hardware VSYNC on display 1, which is on,
651 // but not on display 2, which is off.
652 EXPECT_CALL(mScheduler->mockRequestHardwareVsync, Call(kDisplayId1, true)).Times(1);
653 EXPECT_CALL(mScheduler->mockRequestHardwareVsync, Call(kDisplayId2, _)).Times(0);
654
655 mScheduler->setDisplayPowerMode(kDisplayId1, hal::PowerMode::ON);
656
657 mScheduler->registerDisplay(kDisplayId2,
658 std::make_shared<RefreshRateSelector>(kDisplay2Modes,
659 kDisplay2Mode60->getId()));
660 ASSERT_EQ(hal::PowerMode::OFF, mScheduler->getDisplayPowerMode(kDisplayId2));
661
662 static constexpr bool kDisallow = true;
663 mScheduler->disableHardwareVsync(kDisplayId1, kDisallow);
664 mScheduler->disableHardwareVsync(kDisplayId2, kDisallow);
665
666 static constexpr bool kAllowToEnable = true;
667 mScheduler->resyncAllToHardwareVsync(kAllowToEnable);
668}
669
670TEST_F(SchedulerTest, resyncAllLegacyAppliesToOffDisplays) FTL_FAKE_GUARD(kMainThreadContext) {
671 SET_FLAG_FOR_TEST(flags::multithreaded_present, false);
672
673 // In the legacy code, prior to the flag, resync applied to OFF displays.
674 EXPECT_CALL(mScheduler->mockRequestHardwareVsync, Call(kDisplayId1, true)).Times(1);
675 EXPECT_CALL(mScheduler->mockRequestHardwareVsync, Call(kDisplayId2, true)).Times(1);
676
677 mScheduler->setDisplayPowerMode(kDisplayId1, hal::PowerMode::ON);
678
679 mScheduler->registerDisplay(kDisplayId2,
680 std::make_shared<RefreshRateSelector>(kDisplay2Modes,
681 kDisplay2Mode60->getId()));
682 ASSERT_EQ(hal::PowerMode::OFF, mScheduler->getDisplayPowerMode(kDisplayId2));
683
684 static constexpr bool kDisallow = true;
685 mScheduler->disableHardwareVsync(kDisplayId1, kDisallow);
686 mScheduler->disableHardwareVsync(kDisplayId2, kDisallow);
687
688 static constexpr bool kAllowToEnable = true;
689 mScheduler->resyncAllToHardwareVsync(kAllowToEnable);
690}
691
Ady Abraham822ecbd2023-07-07 16:16:09 -0700692class AttachedChoreographerTest : public SchedulerTest {
693protected:
694 void frameRateTestScenario(Fps layerFps, int8_t frameRateCompatibility, Fps displayFps,
695 Fps expectedChoreographerFps);
696};
697
698TEST_F(AttachedChoreographerTest, registerSingle) {
699 EXPECT_TRUE(mScheduler->mutableAttachedChoreographers().empty());
700
701 const sp<MockLayer> layer = sp<MockLayer>::make(mFlinger.flinger());
702
703 EXPECT_CALL(mSchedulerCallback, onChoreographerAttached);
704 const sp<IDisplayEventConnection> connection =
Dominik Laskowski4babfc42024-02-16 12:28:40 -0500705 mScheduler->createDisplayEventConnection(Cycle::Render, {}, layer->getHandle());
Ady Abraham822ecbd2023-07-07 16:16:09 -0700706
707 EXPECT_EQ(1u, mScheduler->mutableAttachedChoreographers().size());
708 ASSERT_EQ(1u, mScheduler->mutableAttachedChoreographers().count(layer->getSequence()));
709 EXPECT_EQ(1u,
710 mScheduler->mutableAttachedChoreographers()[layer->getSequence()].connections.size());
711 EXPECT_FALSE(
712 mScheduler->mutableAttachedChoreographers()[layer->getSequence()].frameRate.isValid());
713}
714
715TEST_F(AttachedChoreographerTest, registerMultipleOnSameLayer) {
716 EXPECT_TRUE(mScheduler->mutableAttachedChoreographers().empty());
717
718 const sp<MockLayer> layer = sp<MockLayer>::make(mFlinger.flinger());
719 const auto handle = layer->getHandle();
720
721 EXPECT_CALL(mSchedulerCallback, onChoreographerAttached).Times(2);
722
723 EXPECT_CALL(*mEventThread, registerDisplayEventConnection(_))
724 .WillOnce(Return(0))
725 .WillOnce(Return(0));
726
727 const auto mockConnection1 = sp<MockEventThreadConnection>::make(mEventThread);
728 const auto mockConnection2 = sp<MockEventThreadConnection>::make(mEventThread);
729 EXPECT_CALL(*mEventThread, createEventConnection(_, _))
730 .WillOnce(Return(mockConnection1))
731 .WillOnce(Return(mockConnection2));
732
733 const sp<IDisplayEventConnection> connection1 =
Dominik Laskowski4babfc42024-02-16 12:28:40 -0500734 mScheduler->createDisplayEventConnection(Cycle::Render, {}, handle);
Ady Abraham822ecbd2023-07-07 16:16:09 -0700735 const sp<IDisplayEventConnection> connection2 =
Dominik Laskowski4babfc42024-02-16 12:28:40 -0500736 mScheduler->createDisplayEventConnection(Cycle::Render, {}, handle);
Ady Abraham822ecbd2023-07-07 16:16:09 -0700737
738 EXPECT_EQ(1u, mScheduler->mutableAttachedChoreographers().size());
739 ASSERT_EQ(1u, mScheduler->mutableAttachedChoreographers().count(layer->getSequence()));
740 EXPECT_EQ(2u,
741 mScheduler->mutableAttachedChoreographers()[layer->getSequence()].connections.size());
742 EXPECT_FALSE(
743 mScheduler->mutableAttachedChoreographers()[layer->getSequence()].frameRate.isValid());
744}
745
746TEST_F(AttachedChoreographerTest, registerMultipleOnDifferentLayers) {
747 EXPECT_TRUE(mScheduler->mutableAttachedChoreographers().empty());
748
749 const sp<MockLayer> layer1 = sp<MockLayer>::make(mFlinger.flinger());
750 const sp<MockLayer> layer2 = sp<MockLayer>::make(mFlinger.flinger());
751
752 EXPECT_CALL(mSchedulerCallback, onChoreographerAttached).Times(2);
753 const sp<IDisplayEventConnection> connection1 =
Dominik Laskowski4babfc42024-02-16 12:28:40 -0500754 mScheduler->createDisplayEventConnection(Cycle::Render, {}, layer1->getHandle());
Ady Abraham822ecbd2023-07-07 16:16:09 -0700755 const sp<IDisplayEventConnection> connection2 =
Dominik Laskowski4babfc42024-02-16 12:28:40 -0500756 mScheduler->createDisplayEventConnection(Cycle::Render, {}, layer2->getHandle());
Ady Abraham822ecbd2023-07-07 16:16:09 -0700757
758 EXPECT_EQ(2u, mScheduler->mutableAttachedChoreographers().size());
759
760 ASSERT_EQ(1u, mScheduler->mutableAttachedChoreographers().count(layer1->getSequence()));
761 EXPECT_EQ(1u,
762 mScheduler->mutableAttachedChoreographers()[layer1->getSequence()]
763 .connections.size());
764 EXPECT_FALSE(
765 mScheduler->mutableAttachedChoreographers()[layer1->getSequence()].frameRate.isValid());
766
767 ASSERT_EQ(1u, mScheduler->mutableAttachedChoreographers().count(layer2->getSequence()));
768 EXPECT_EQ(1u,
769 mScheduler->mutableAttachedChoreographers()[layer2->getSequence()]
770 .connections.size());
771 EXPECT_FALSE(
772 mScheduler->mutableAttachedChoreographers()[layer2->getSequence()].frameRate.isValid());
773}
774
775TEST_F(AttachedChoreographerTest, removedWhenConnectionIsGone) {
776 EXPECT_TRUE(mScheduler->mutableAttachedChoreographers().empty());
777
778 const sp<MockLayer> layer = sp<MockLayer>::make(mFlinger.flinger());
779
780 EXPECT_CALL(mSchedulerCallback, onChoreographerAttached);
781
782 sp<IDisplayEventConnection> connection =
Dominik Laskowski4babfc42024-02-16 12:28:40 -0500783 mScheduler->createDisplayEventConnection(Cycle::Render, {}, layer->getHandle());
Ady Abraham822ecbd2023-07-07 16:16:09 -0700784
785 ASSERT_EQ(1u, mScheduler->mutableAttachedChoreographers().count(layer->getSequence()));
786 EXPECT_EQ(1u,
787 mScheduler->mutableAttachedChoreographers()[layer->getSequence()].connections.size());
788
789 // The connection is used all over this test, so it is quite hard to release it from here.
790 // Instead, we just do a small shortcut.
791 {
792 EXPECT_CALL(*mEventThread, registerDisplayEventConnection(_)).WillOnce(Return(0));
793 sp<MockEventThreadConnection> mockConnection =
794 sp<MockEventThreadConnection>::make(mEventThread);
795 mScheduler->mutableAttachedChoreographers()[layer->getSequence()].connections.clear();
796 mScheduler->mutableAttachedChoreographers()[layer->getSequence()].connections.emplace(
797 mockConnection);
798 }
799
800 RequestedLayerState layerState(LayerCreationArgs(layer->getSequence()));
801 LayerHierarchy hierarchy(&layerState);
802 mScheduler->updateAttachedChoreographers(hierarchy, 60_Hz);
803 EXPECT_TRUE(mScheduler->mutableAttachedChoreographers().empty());
804}
805
806TEST_F(AttachedChoreographerTest, removedWhenLayerIsGone) {
807 EXPECT_TRUE(mScheduler->mutableAttachedChoreographers().empty());
808
809 sp<MockLayer> layer = sp<MockLayer>::make(mFlinger.flinger());
810
811 EXPECT_CALL(mSchedulerCallback, onChoreographerAttached);
812 const sp<IDisplayEventConnection> connection =
Dominik Laskowski4babfc42024-02-16 12:28:40 -0500813 mScheduler->createDisplayEventConnection(Cycle::Render, {}, layer->getHandle());
Ady Abraham822ecbd2023-07-07 16:16:09 -0700814
815 layer.clear();
816 mFlinger.mutableLayersPendingRemoval().clear();
817 EXPECT_TRUE(mScheduler->mutableAttachedChoreographers().empty());
818}
819
820void AttachedChoreographerTest::frameRateTestScenario(Fps layerFps, int8_t frameRateCompatibility,
821 Fps displayFps,
822 Fps expectedChoreographerFps) {
823 const sp<MockLayer> layer = sp<MockLayer>::make(mFlinger.flinger());
824
825 EXPECT_CALL(mSchedulerCallback, onChoreographerAttached);
826 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 RequestedLayerState layerState(LayerCreationArgs(layer->getSequence()));
830 LayerHierarchy hierarchy(&layerState);
831
832 layerState.frameRate = layerFps.getValue();
833 layerState.frameRateCompatibility = frameRateCompatibility;
834
835 mScheduler->updateAttachedChoreographers(hierarchy, displayFps);
836
837 ASSERT_EQ(1u, mScheduler->mutableAttachedChoreographers().count(layer->getSequence()));
838 EXPECT_EQ(expectedChoreographerFps,
839 mScheduler->mutableAttachedChoreographers()[layer->getSequence()].frameRate);
840 EXPECT_EQ(expectedChoreographerFps, mEventThreadConnection->frameRate);
841}
842
843TEST_F(AttachedChoreographerTest, setsFrameRateDefault) {
844 Fps layerFps = 30_Hz;
845 int8_t frameRateCompatibility = ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT;
846 Fps displayFps = 60_Hz;
847 Fps expectedChoreographerFps = 30_Hz;
848
849 frameRateTestScenario(layerFps, frameRateCompatibility, displayFps, expectedChoreographerFps);
850
851 layerFps = Fps::fromValue(32.7f);
852 frameRateTestScenario(layerFps, frameRateCompatibility, displayFps, expectedChoreographerFps);
853}
854
855TEST_F(AttachedChoreographerTest, setsFrameRateExact) {
856 Fps layerFps = 30_Hz;
857 int8_t frameRateCompatibility = ANATIVEWINDOW_FRAME_RATE_EXACT;
858 Fps displayFps = 60_Hz;
859 Fps expectedChoreographerFps = 30_Hz;
860
861 frameRateTestScenario(layerFps, frameRateCompatibility, displayFps, expectedChoreographerFps);
862
863 layerFps = Fps::fromValue(32.7f);
864 expectedChoreographerFps = {};
865 frameRateTestScenario(layerFps, frameRateCompatibility, displayFps, expectedChoreographerFps);
866}
867
868TEST_F(AttachedChoreographerTest, setsFrameRateExactOrMultiple) {
869 Fps layerFps = 30_Hz;
870 int8_t frameRateCompatibility = ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_FIXED_SOURCE;
871 Fps displayFps = 60_Hz;
872 Fps expectedChoreographerFps = 30_Hz;
873
874 frameRateTestScenario(layerFps, frameRateCompatibility, displayFps, expectedChoreographerFps);
875
876 layerFps = Fps::fromValue(32.7f);
877 expectedChoreographerFps = {};
878 frameRateTestScenario(layerFps, frameRateCompatibility, displayFps, expectedChoreographerFps);
879}
880
881TEST_F(AttachedChoreographerTest, setsFrameRateParent) {
882 const sp<MockLayer> layer = sp<MockLayer>::make(mFlinger.flinger());
883 const sp<MockLayer> parent = sp<MockLayer>::make(mFlinger.flinger());
884
885 EXPECT_CALL(mSchedulerCallback, onChoreographerAttached);
886 sp<IDisplayEventConnection> connection =
Dominik Laskowski4babfc42024-02-16 12:28:40 -0500887 mScheduler->createDisplayEventConnection(Cycle::Render, {}, parent->getHandle());
Ady Abraham822ecbd2023-07-07 16:16:09 -0700888
889 RequestedLayerState parentState(LayerCreationArgs(parent->getSequence()));
890 LayerHierarchy parentHierarchy(&parentState);
891
892 RequestedLayerState layerState(LayerCreationArgs(layer->getSequence()));
893 LayerHierarchy hierarchy(&layerState);
894 parentHierarchy.mChildren.push_back(
895 std::make_pair(&hierarchy, LayerHierarchy::Variant::Attached));
896
897 layerState.frameRate = (30_Hz).getValue();
898 layerState.frameRateCompatibility = ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT;
899
900 mScheduler->updateAttachedChoreographers(parentHierarchy, 120_Hz);
901
902 ASSERT_EQ(1u, mScheduler->mutableAttachedChoreographers().count(parent->getSequence()));
903
904 EXPECT_EQ(30_Hz, mScheduler->mutableAttachedChoreographers()[parent->getSequence()].frameRate);
905}
906
907TEST_F(AttachedChoreographerTest, setsFrameRateParent2Children) {
908 const sp<MockLayer> layer1 = sp<MockLayer>::make(mFlinger.flinger());
909 const sp<MockLayer> layer2 = sp<MockLayer>::make(mFlinger.flinger());
910 const sp<MockLayer> parent = sp<MockLayer>::make(mFlinger.flinger());
911
912 EXPECT_CALL(mSchedulerCallback, onChoreographerAttached);
913 sp<IDisplayEventConnection> connection =
Dominik Laskowski4babfc42024-02-16 12:28:40 -0500914 mScheduler->createDisplayEventConnection(Cycle::Render, {}, parent->getHandle());
Ady Abraham822ecbd2023-07-07 16:16:09 -0700915
916 RequestedLayerState parentState(LayerCreationArgs(parent->getSequence()));
917 LayerHierarchy parentHierarchy(&parentState);
918
919 RequestedLayerState layer1State(LayerCreationArgs(layer1->getSequence()));
920 LayerHierarchy layer1Hierarchy(&layer1State);
921 parentHierarchy.mChildren.push_back(
922 std::make_pair(&layer1Hierarchy, LayerHierarchy::Variant::Attached));
923
924 RequestedLayerState layer2State(LayerCreationArgs(layer1->getSequence()));
925 LayerHierarchy layer2Hierarchy(&layer2State);
926 parentHierarchy.mChildren.push_back(
927 std::make_pair(&layer2Hierarchy, LayerHierarchy::Variant::Attached));
928
929 layer1State.frameRate = (30_Hz).getValue();
930 layer1State.frameRateCompatibility = ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT;
931
932 layer2State.frameRate = (20_Hz).getValue();
933 layer2State.frameRateCompatibility = ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT;
934
935 mScheduler->updateAttachedChoreographers(parentHierarchy, 120_Hz);
936
937 ASSERT_EQ(1u, mScheduler->mutableAttachedChoreographers().count(parent->getSequence()));
938
939 EXPECT_EQ(60_Hz, mScheduler->mutableAttachedChoreographers()[parent->getSequence()].frameRate);
940}
941
942TEST_F(AttachedChoreographerTest, setsFrameRateParentConflictingChildren) {
943 const sp<MockLayer> layer1 = sp<MockLayer>::make(mFlinger.flinger());
944 const sp<MockLayer> layer2 = sp<MockLayer>::make(mFlinger.flinger());
945 const sp<MockLayer> parent = sp<MockLayer>::make(mFlinger.flinger());
946
947 EXPECT_CALL(mSchedulerCallback, onChoreographerAttached);
948 sp<IDisplayEventConnection> connection =
Dominik Laskowski4babfc42024-02-16 12:28:40 -0500949 mScheduler->createDisplayEventConnection(Cycle::Render, {}, parent->getHandle());
Ady Abraham822ecbd2023-07-07 16:16:09 -0700950
951 RequestedLayerState parentState(LayerCreationArgs(parent->getSequence()));
952 LayerHierarchy parentHierarchy(&parentState);
953
954 RequestedLayerState layer1State(LayerCreationArgs(layer1->getSequence()));
955 LayerHierarchy layer1Hierarchy(&layer1State);
956 parentHierarchy.mChildren.push_back(
957 std::make_pair(&layer1Hierarchy, LayerHierarchy::Variant::Attached));
958
959 RequestedLayerState layer2State(LayerCreationArgs(layer1->getSequence()));
960 LayerHierarchy layer2Hierarchy(&layer2State);
961 parentHierarchy.mChildren.push_back(
962 std::make_pair(&layer2Hierarchy, LayerHierarchy::Variant::Attached));
963
964 layer1State.frameRate = (30_Hz).getValue();
965 layer1State.frameRateCompatibility = ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT;
966
967 layer2State.frameRate = (25_Hz).getValue();
968 layer2State.frameRateCompatibility = ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT;
969
970 mScheduler->updateAttachedChoreographers(parentHierarchy, 120_Hz);
971
972 ASSERT_EQ(1u, mScheduler->mutableAttachedChoreographers().count(parent->getSequence()));
973
974 EXPECT_EQ(Fps(), mScheduler->mutableAttachedChoreographers()[parent->getSequence()].frameRate);
975}
976
977TEST_F(AttachedChoreographerTest, setsFrameRateChild) {
978 const sp<MockLayer> layer = sp<MockLayer>::make(mFlinger.flinger());
979 const sp<MockLayer> parent = sp<MockLayer>::make(mFlinger.flinger());
980
981 EXPECT_CALL(mSchedulerCallback, onChoreographerAttached);
982 sp<IDisplayEventConnection> connection =
Dominik Laskowski4babfc42024-02-16 12:28:40 -0500983 mScheduler->createDisplayEventConnection(Cycle::Render, {}, layer->getHandle());
Ady Abraham822ecbd2023-07-07 16:16:09 -0700984
985 RequestedLayerState parentState(LayerCreationArgs(parent->getSequence()));
986 LayerHierarchy parentHierarchy(&parentState);
987
988 RequestedLayerState layerState(LayerCreationArgs(layer->getSequence()));
989 LayerHierarchy hierarchy(&layerState);
990 parentHierarchy.mChildren.push_back(
991 std::make_pair(&hierarchy, LayerHierarchy::Variant::Attached));
992
993 parentState.frameRate = (30_Hz).getValue();
994 parentState.frameRateCompatibility = ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT;
995
996 mScheduler->updateAttachedChoreographers(parentHierarchy, 120_Hz);
997
998 ASSERT_EQ(1u, mScheduler->mutableAttachedChoreographers().count(layer->getSequence()));
999
1000 EXPECT_EQ(30_Hz, mScheduler->mutableAttachedChoreographers()[layer->getSequence()].frameRate);
1001}
1002
1003TEST_F(AttachedChoreographerTest, setsFrameRateChildNotOverriddenByParent) {
1004 const sp<MockLayer> layer = sp<MockLayer>::make(mFlinger.flinger());
1005 const sp<MockLayer> parent = sp<MockLayer>::make(mFlinger.flinger());
1006
1007 EXPECT_CALL(mSchedulerCallback, onChoreographerAttached);
1008 sp<IDisplayEventConnection> connection =
Dominik Laskowski4babfc42024-02-16 12:28:40 -05001009 mScheduler->createDisplayEventConnection(Cycle::Render, {}, layer->getHandle());
Ady Abraham822ecbd2023-07-07 16:16:09 -07001010
1011 RequestedLayerState parentState(LayerCreationArgs(parent->getSequence()));
1012 LayerHierarchy parentHierarchy(&parentState);
1013
1014 RequestedLayerState layerState(LayerCreationArgs(layer->getSequence()));
1015 LayerHierarchy hierarchy(&layerState);
1016 parentHierarchy.mChildren.push_back(
1017 std::make_pair(&hierarchy, LayerHierarchy::Variant::Attached));
1018
1019 parentState.frameRate = (30_Hz).getValue();
1020 parentState.frameRateCompatibility = ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT;
1021
1022 layerState.frameRate = (60_Hz).getValue();
1023 layerState.frameRateCompatibility = ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT;
1024
1025 mScheduler->updateAttachedChoreographers(parentHierarchy, 120_Hz);
1026
1027 ASSERT_EQ(1u, mScheduler->mutableAttachedChoreographers().count(layer->getSequence()));
1028
1029 EXPECT_EQ(60_Hz, mScheduler->mutableAttachedChoreographers()[layer->getSequence()].frameRate);
1030}
1031
Dominik Laskowski068173d2021-08-11 17:22:59 -07001032} // namespace android::scheduler