blob: 10e2220ece54e1a9ad45283bf9cd1cc4873cc58e [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"
Dominik Laskowski98041832019-08-01 18:35:59 -070028#include "TestableScheduler.h"
Dominik Laskowski983f2b52020-06-25 16:54:06 -070029#include "TestableSurfaceFlinger.h"
Dominik Laskowskib0054a22022-03-03 09:03:06 -080030#include "mock/DisplayHardware/MockDisplayMode.h"
Ana Krulec0c8cd522018-08-31 12:27:28 -070031#include "mock/MockEventThread.h"
Dominik Laskowski983f2b52020-06-25 16:54:06 -070032#include "mock/MockLayer.h"
Dominik Laskowski8b01cc02020-07-14 19:02:41 -070033#include "mock/MockSchedulerCallback.h"
Ana Krulec0c8cd522018-08-31 12:27:28 -070034
Ady Abraham822ecbd2023-07-07 16:16:09 -070035#include <FrontEnd/LayerHierarchy.h>
36
ramindani0491e642023-11-16 17:42:14 -080037#include <com_android_graphics_surfaceflinger_flags.h>
Ady Abraham822ecbd2023-07-07 16:16:09 -070038#include "FpsOps.h"
39
ramindani0491e642023-11-16 17:42:14 -080040using namespace com::android::graphics::surfaceflinger;
41
Dominik Laskowski068173d2021-08-11 17:22:59 -070042namespace android::scheduler {
43
Dominik Laskowskib0054a22022-03-03 09:03:06 -080044using android::mock::createDisplayMode;
ramindani0491e642023-11-16 17:42:14 -080045using android::mock::createVrrDisplayMode;
Dominik Laskowskib0054a22022-03-03 09:03:06 -080046
Ana Krulec0c8cd522018-08-31 12:27:28 -070047using testing::_;
48using testing::Return;
49
Dominik Laskowski8b01cc02020-07-14 19:02:41 -070050namespace {
Ana Krulec0c8cd522018-08-31 12:27:28 -070051
Dominik Laskowski068173d2021-08-11 17:22:59 -070052using MockEventThread = android::mock::EventThread;
53using MockLayer = android::mock::MockLayer;
54
Ady Abraham822ecbd2023-07-07 16:16:09 -070055using LayerHierarchy = surfaceflinger::frontend::LayerHierarchy;
56using LayerHierarchyBuilder = surfaceflinger::frontend::LayerHierarchyBuilder;
57using RequestedLayerState = surfaceflinger::frontend::RequestedLayerState;
58
Ana Krulec0c8cd522018-08-31 12:27:28 -070059class SchedulerTest : public testing::Test {
60protected:
Ana Krulec85c39af2018-12-26 17:29:57 -080061 class MockEventThreadConnection : public android::EventThreadConnection {
Ana Krulec0c8cd522018-08-31 12:27:28 -070062 public:
Ana Krulec85c39af2018-12-26 17:29:57 -080063 explicit MockEventThreadConnection(EventThread* eventThread)
Ady Abrahamf2851612023-09-25 17:19:00 -070064 : EventThreadConnection(eventThread, /*callingUid*/ static_cast<uid_t>(0)) {}
Ana Krulec0c8cd522018-08-31 12:27:28 -070065 ~MockEventThreadConnection() = default;
66
Huihong Luo6fac5232021-11-22 16:05:23 -080067 MOCK_METHOD1(stealReceiveChannel, binder::Status(gui::BitTube* outChannel));
68 MOCK_METHOD1(setVsyncRate, binder::Status(int count));
69 MOCK_METHOD0(requestNextVsync, binder::Status());
Ana Krulec0c8cd522018-08-31 12:27:28 -070070 };
71
Ana Krulec0c8cd522018-08-31 12:27:28 -070072 SchedulerTest();
Ana Krulec0c8cd522018-08-31 12:27:28 -070073
Dominik Laskowski530d6bd2022-10-10 16:55:54 -040074 static constexpr PhysicalDisplayId kDisplayId1 = PhysicalDisplayId::fromPort(255u);
Ady Abrahamace3d052022-11-17 16:25:05 -080075 static inline const ftl::NonNull<DisplayModePtr> kDisplay1Mode60 =
76 ftl::as_non_null(createDisplayMode(kDisplayId1, DisplayModeId(0), 60_Hz));
77 static inline const ftl::NonNull<DisplayModePtr> kDisplay1Mode120 =
78 ftl::as_non_null(createDisplayMode(kDisplayId1, DisplayModeId(1), 120_Hz));
Dominik Laskowski530d6bd2022-10-10 16:55:54 -040079 static inline const DisplayModes kDisplay1Modes = makeModes(kDisplay1Mode60, kDisplay1Mode120);
80
81 static constexpr PhysicalDisplayId kDisplayId2 = PhysicalDisplayId::fromPort(254u);
Ady Abrahamace3d052022-11-17 16:25:05 -080082 static inline const ftl::NonNull<DisplayModePtr> kDisplay2Mode60 =
83 ftl::as_non_null(createDisplayMode(kDisplayId2, DisplayModeId(0), 60_Hz));
84 static inline const ftl::NonNull<DisplayModePtr> kDisplay2Mode120 =
85 ftl::as_non_null(createDisplayMode(kDisplayId2, DisplayModeId(1), 120_Hz));
Dominik Laskowski530d6bd2022-10-10 16:55:54 -040086 static inline const DisplayModes kDisplay2Modes = makeModes(kDisplay2Mode60, kDisplay2Mode120);
87
88 static constexpr PhysicalDisplayId kDisplayId3 = PhysicalDisplayId::fromPort(253u);
Ady Abrahamace3d052022-11-17 16:25:05 -080089 static inline const ftl::NonNull<DisplayModePtr> kDisplay3Mode60 =
90 ftl::as_non_null(createDisplayMode(kDisplayId3, DisplayModeId(0), 60_Hz));
Dominik Laskowski530d6bd2022-10-10 16:55:54 -040091 static inline const DisplayModes kDisplay3Modes = makeModes(kDisplay3Mode60);
Marin Shalamanov2cde1002021-06-08 19:50:10 +020092
Dominik Laskowskid82e0f02022-10-26 15:23:04 -040093 std::shared_ptr<RefreshRateSelector> mSelector =
94 std::make_shared<RefreshRateSelector>(makeModes(kDisplay1Mode60),
95 kDisplay1Mode60->getId());
Dominik Laskowski983f2b52020-06-25 16:54:06 -070096
Dominik Laskowski8b01cc02020-07-14 19:02:41 -070097 mock::SchedulerCallback mSchedulerCallback;
Leon Scroggins III823d4ca2023-12-12 16:57:34 -050098 TestableSurfaceFlinger mFlinger;
ramindaniae645822024-01-11 10:57:29 -080099 TestableScheduler* mScheduler = new TestableScheduler{mSelector, mFlinger, mSchedulerCallback};
Vishnu Naira0292282023-12-16 14:32:00 -0800100 surfaceflinger::frontend::LayerHierarchyBuilder mLayerHierarchyBuilder;
Dominik Laskowski98041832019-08-01 18:35:59 -0700101
Dominik Laskowski068173d2021-08-11 17:22:59 -0700102 MockEventThread* mEventThread;
Ana Krulec0c8cd522018-08-31 12:27:28 -0700103 sp<MockEventThreadConnection> mEventThreadConnection;
Ana Krulec0c8cd522018-08-31 12:27:28 -0700104};
105
106SchedulerTest::SchedulerTest() {
Dominik Laskowski068173d2021-08-11 17:22:59 -0700107 auto eventThread = std::make_unique<MockEventThread>();
Ana Krulec0c8cd522018-08-31 12:27:28 -0700108 mEventThread = eventThread.get();
Ana Krulec85c39af2018-12-26 17:29:57 -0800109 EXPECT_CALL(*mEventThread, registerDisplayEventConnection(_)).WillOnce(Return(0));
110
Ady Abrahamd11bade2022-08-01 16:18:03 -0700111 mEventThreadConnection = sp<MockEventThreadConnection>::make(mEventThread);
Ana Krulec0c8cd522018-08-31 12:27:28 -0700112
113 // createConnection call to scheduler makes a createEventConnection call to EventThread. Make
114 // sure that call gets executed and returns an EventThread::Connection object.
Ady Abraham0f4a1b12019-06-04 16:04:04 -0700115 EXPECT_CALL(*mEventThread, createEventConnection(_, _))
Ana Krulec0c8cd522018-08-31 12:27:28 -0700116 .WillRepeatedly(Return(mEventThreadConnection));
117
Dominik Laskowski4babfc42024-02-16 12:28:40 -0500118 mScheduler->setEventThread(Cycle::Render, std::move(eventThread));
Ady Abrahama0a16272021-03-03 15:23:35 -0800119
120 mFlinger.resetScheduler(mScheduler);
Ana Krulec0c8cd522018-08-31 12:27:28 -0700121}
122
Dominik Laskowski8b01cc02020-07-14 19:02:41 -0700123} // namespace
Ana Krulec0c8cd522018-08-31 12:27:28 -0700124
Dominik Laskowski66295432023-03-14 12:25:36 -0400125TEST_F(SchedulerTest, registerDisplay) FTL_FAKE_GUARD(kMainThreadContext) {
Dominik Laskowski008bec02023-03-14 12:04:58 -0400126 // Hardware VSYNC should not change if the display is already registered.
Dominik Laskowski66295432023-03-14 12:25:36 -0400127 EXPECT_CALL(mSchedulerCallback, requestHardwareVsync(kDisplayId1, false)).Times(0);
Dominik Laskowski008bec02023-03-14 12:04:58 -0400128 mScheduler->registerDisplay(kDisplayId1,
129 std::make_shared<RefreshRateSelector>(kDisplay1Modes,
130 kDisplay1Mode60->getId()));
131
Dominik Laskowski66295432023-03-14 12:25:36 -0400132 // TODO(b/241285191): Restore once VsyncSchedule::getPendingHardwareVsyncState is called by
133 // Scheduler::setDisplayPowerMode rather than SF::setPowerModeInternal.
134#if 0
Dominik Laskowski008bec02023-03-14 12:04:58 -0400135 // Hardware VSYNC should be disabled for newly registered displays.
Dominik Laskowski66295432023-03-14 12:25:36 -0400136 EXPECT_CALL(mSchedulerCallback, requestHardwareVsync(kDisplayId2, false)).Times(1);
137 EXPECT_CALL(mSchedulerCallback, requestHardwareVsync(kDisplayId3, false)).Times(1);
138#endif
Dominik Laskowski008bec02023-03-14 12:04:58 -0400139
140 mScheduler->registerDisplay(kDisplayId2,
141 std::make_shared<RefreshRateSelector>(kDisplay2Modes,
142 kDisplay2Mode60->getId()));
143 mScheduler->registerDisplay(kDisplayId3,
144 std::make_shared<RefreshRateSelector>(kDisplay3Modes,
145 kDisplay3Mode60->getId()));
Dominik Laskowski66295432023-03-14 12:25:36 -0400146
147 EXPECT_FALSE(mScheduler->getVsyncSchedule(kDisplayId1)->getPendingHardwareVsyncState());
148 EXPECT_FALSE(mScheduler->getVsyncSchedule(kDisplayId2)->getPendingHardwareVsyncState());
149 EXPECT_FALSE(mScheduler->getVsyncSchedule(kDisplayId3)->getPendingHardwareVsyncState());
Dominik Laskowski008bec02023-03-14 12:04:58 -0400150}
151
Marin Shalamanov2cde1002021-06-08 19:50:10 +0200152TEST_F(SchedulerTest, chooseRefreshRateForContentIsNoopWhenModeSwitchingIsNotSupported) {
153 // The layer is registered at creation time and deregistered at destruction time.
Dominik Laskowski068173d2021-08-11 17:22:59 -0700154 sp<MockLayer> layer = sp<MockLayer>::make(mFlinger.flinger());
Dominik Laskowski983f2b52020-06-25 16:54:06 -0700155
Marin Shalamanov2cde1002021-06-08 19:50:10 +0200156 // recordLayerHistory should be a noop
Dominik Laskowski9c93d602021-10-07 19:38:26 -0700157 ASSERT_EQ(0u, mScheduler->getNumActiveLayers());
Vishnu Nair47b7bb42023-09-29 16:27:33 -0700158 mScheduler->recordLayerHistory(layer->getSequence(), layer->getLayerProps(), 0, 0,
Vishnu Nairef68d6d2023-02-28 06:18:27 +0000159 LayerHistory::LayerUpdateType::Buffer);
Dominik Laskowski9c93d602021-10-07 19:38:26 -0700160 ASSERT_EQ(0u, mScheduler->getNumActiveLayers());
Dominik Laskowski983f2b52020-06-25 16:54:06 -0700161
Rachel Lee6a9731d2022-06-06 17:08:14 -0700162 constexpr hal::PowerMode kPowerModeOn = hal::PowerMode::ON;
Leon Scroggins III67388622023-02-06 20:36:20 -0500163 FTL_FAKE_GUARD(kMainThreadContext, mScheduler->setDisplayPowerMode(kDisplayId1, kPowerModeOn));
Dominik Laskowski983f2b52020-06-25 16:54:06 -0700164
165 constexpr uint32_t kDisplayArea = 999'999;
Ady Abrahamed3290f2021-05-17 15:12:14 -0700166 mScheduler->onActiveDisplayAreaChanged(kDisplayArea);
Dominik Laskowski983f2b52020-06-25 16:54:06 -0700167
ramindani69b58e82022-09-26 16:48:36 -0700168 EXPECT_CALL(mSchedulerCallback, requestDisplayModes(_)).Times(0);
Ady Abraham822ecbd2023-07-07 16:16:09 -0700169 mScheduler->chooseRefreshRateForContent(/*LayerHierarchy*/ nullptr,
170 /*updateAttachedChoreographer*/ false);
Dominik Laskowski983f2b52020-06-25 16:54:06 -0700171}
172
Marin Shalamanov2cde1002021-06-08 19:50:10 +0200173TEST_F(SchedulerTest, updateDisplayModes) {
Dominik Laskowski9c93d602021-10-07 19:38:26 -0700174 ASSERT_EQ(0u, mScheduler->layerHistorySize());
Dominik Laskowski068173d2021-08-11 17:22:59 -0700175 sp<MockLayer> layer = sp<MockLayer>::make(mFlinger.flinger());
Dominik Laskowski9c93d602021-10-07 19:38:26 -0700176 ASSERT_EQ(1u, mScheduler->layerHistorySize());
Marin Shalamanov2cde1002021-06-08 19:50:10 +0200177
Dominik Laskowski596a2562022-10-28 11:26:12 -0400178 // Replace `mSelector` with a new `RefreshRateSelector` that has different display modes.
179 mScheduler->registerDisplay(kDisplayId1,
180 std::make_shared<RefreshRateSelector>(kDisplay1Modes,
181 kDisplay1Mode60->getId()));
Marin Shalamanov2cde1002021-06-08 19:50:10 +0200182
Dominik Laskowski9c93d602021-10-07 19:38:26 -0700183 ASSERT_EQ(0u, mScheduler->getNumActiveLayers());
Vishnu Nair47b7bb42023-09-29 16:27:33 -0700184 mScheduler->recordLayerHistory(layer->getSequence(), layer->getLayerProps(), 0, 0,
Vishnu Nairef68d6d2023-02-28 06:18:27 +0000185 LayerHistory::LayerUpdateType::Buffer);
Dominik Laskowski9c93d602021-10-07 19:38:26 -0700186 ASSERT_EQ(1u, mScheduler->getNumActiveLayers());
Marin Shalamanov2cde1002021-06-08 19:50:10 +0200187}
188
Dominik Laskowski068173d2021-08-11 17:22:59 -0700189TEST_F(SchedulerTest, dispatchCachedReportedMode) {
190 mScheduler->clearCachedReportedMode();
191
Ady Abraham690f4612021-07-01 23:24:03 -0700192 EXPECT_CALL(*mEventThread, onModeChanged(_)).Times(0);
Dominik Laskowski068173d2021-08-11 17:22:59 -0700193 EXPECT_NO_FATAL_FAILURE(mScheduler->dispatchCachedReportedMode());
Ana Krulec6ddd2612020-09-24 13:06:33 -0700194}
195
Ady Abraham899dcdb2021-06-15 16:56:21 -0700196TEST_F(SchedulerTest, calculateMaxAcquiredBufferCount) {
Dominik Laskowski6eab42d2021-09-13 14:34:13 -0700197 EXPECT_EQ(1, mFlinger.calculateMaxAcquiredBufferCount(60_Hz, 30ms));
198 EXPECT_EQ(2, mFlinger.calculateMaxAcquiredBufferCount(90_Hz, 30ms));
199 EXPECT_EQ(3, mFlinger.calculateMaxAcquiredBufferCount(120_Hz, 30ms));
Ady Abraham564f9de2021-02-03 18:34:33 -0800200
Dominik Laskowski6eab42d2021-09-13 14:34:13 -0700201 EXPECT_EQ(2, mFlinger.calculateMaxAcquiredBufferCount(60_Hz, 40ms));
Ady Abraham564f9de2021-02-03 18:34:33 -0800202
Dominik Laskowski6eab42d2021-09-13 14:34:13 -0700203 EXPECT_EQ(1, mFlinger.calculateMaxAcquiredBufferCount(60_Hz, 10ms));
Lloyd Piquea1456c12023-05-17 12:11:15 -0700204
Lloyd Pique30db6402023-06-26 18:56:51 +0000205 const auto savedMinAcquiredBuffers = mFlinger.mutableMinAcquiredBuffers();
206 mFlinger.mutableMinAcquiredBuffers() = 2;
Lloyd Piquea1456c12023-05-17 12:11:15 -0700207 EXPECT_EQ(2, mFlinger.calculateMaxAcquiredBufferCount(60_Hz, 10ms));
Lloyd Pique30db6402023-06-26 18:56:51 +0000208 mFlinger.mutableMinAcquiredBuffers() = savedMinAcquiredBuffers;
Ady Abraham564f9de2021-02-03 18:34:33 -0800209}
210
Marin Shalamanov4c7831e2021-06-08 20:44:06 +0200211MATCHER(Is120Hz, "") {
Ady Abrahamace3d052022-11-17 16:25:05 -0800212 return isApproxEqual(arg.front().mode.fps, 120_Hz);
Marin Shalamanov4c7831e2021-06-08 20:44:06 +0200213}
214
215TEST_F(SchedulerTest, chooseRefreshRateForContentSelectsMaxRefreshRate) {
Dominik Laskowski596a2562022-10-28 11:26:12 -0400216 mScheduler->registerDisplay(kDisplayId1,
217 std::make_shared<RefreshRateSelector>(kDisplay1Modes,
218 kDisplay1Mode60->getId()));
Marin Shalamanov4c7831e2021-06-08 20:44:06 +0200219
Dominik Laskowski0c41ffa2021-12-24 16:45:12 -0800220 const sp<MockLayer> layer = sp<MockLayer>::make(mFlinger.flinger());
221 EXPECT_CALL(*layer, isVisible()).WillOnce(Return(true));
Marin Shalamanov4c7831e2021-06-08 20:44:06 +0200222
Vishnu Nair47b7bb42023-09-29 16:27:33 -0700223 mScheduler->recordLayerHistory(layer->getSequence(), layer->getLayerProps(), 0, systemTime(),
Vishnu Nairef68d6d2023-02-28 06:18:27 +0000224 LayerHistory::LayerUpdateType::Buffer);
Marin Shalamanov4c7831e2021-06-08 20:44:06 +0200225
Rachel Lee6a9731d2022-06-06 17:08:14 -0700226 constexpr hal::PowerMode kPowerModeOn = hal::PowerMode::ON;
Leon Scroggins III67388622023-02-06 20:36:20 -0500227 FTL_FAKE_GUARD(kMainThreadContext, mScheduler->setDisplayPowerMode(kDisplayId1, kPowerModeOn));
Marin Shalamanov4c7831e2021-06-08 20:44:06 +0200228
229 constexpr uint32_t kDisplayArea = 999'999;
Ady Abrahamed3290f2021-05-17 15:12:14 -0700230 mScheduler->onActiveDisplayAreaChanged(kDisplayArea);
Marin Shalamanov4c7831e2021-06-08 20:44:06 +0200231
ramindani69b58e82022-09-26 16:48:36 -0700232 EXPECT_CALL(mSchedulerCallback, requestDisplayModes(Is120Hz())).Times(1);
Ady Abraham822ecbd2023-07-07 16:16:09 -0700233 mScheduler->chooseRefreshRateForContent(/*LayerHierarchy*/ nullptr,
234 /*updateAttachedChoreographer*/ false);
Dominik Laskowski0c41ffa2021-12-24 16:45:12 -0800235
236 // No-op if layer requirements have not changed.
ramindani69b58e82022-09-26 16:48:36 -0700237 EXPECT_CALL(mSchedulerCallback, requestDisplayModes(_)).Times(0);
Ady Abraham822ecbd2023-07-07 16:16:09 -0700238 mScheduler->chooseRefreshRateForContent(/*LayerHierarchy*/ nullptr,
239 /*updateAttachedChoreographer*/ false);
Marin Shalamanov4c7831e2021-06-08 20:44:06 +0200240}
241
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400242TEST_F(SchedulerTest, chooseDisplayModesSingleDisplay) {
Dominik Laskowskib5a094b2022-10-27 12:00:12 -0400243 mScheduler->registerDisplay(kDisplayId1,
244 std::make_shared<RefreshRateSelector>(kDisplay1Modes,
245 kDisplay1Mode60->getId()));
ramindani69b58e82022-09-26 16:48:36 -0700246
Dominik Laskowskid82e0f02022-10-26 15:23:04 -0400247 std::vector<RefreshRateSelector::LayerRequirement> layers =
248 std::vector<RefreshRateSelector::LayerRequirement>({{.weight = 1.f}, {.weight = 1.f}});
ramindani69b58e82022-09-26 16:48:36 -0700249 mScheduler->setContentRequirements(layers);
250 GlobalSignals globalSignals = {.idle = true};
251 mScheduler->setTouchStateAndIdleTimerPolicy(globalSignals);
252
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400253 using DisplayModeChoice = TestableScheduler::DisplayModeChoice;
254
255 auto modeChoices = mScheduler->chooseDisplayModes();
256 ASSERT_EQ(1u, modeChoices.size());
257
258 auto choice = modeChoices.get(kDisplayId1);
259 ASSERT_TRUE(choice);
Ady Abrahamace3d052022-11-17 16:25:05 -0800260 EXPECT_EQ(choice->get(), DisplayModeChoice({60_Hz, kDisplay1Mode60}, globalSignals));
ramindani69b58e82022-09-26 16:48:36 -0700261
262 globalSignals = {.idle = false};
263 mScheduler->setTouchStateAndIdleTimerPolicy(globalSignals);
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400264
265 modeChoices = mScheduler->chooseDisplayModes();
266 ASSERT_EQ(1u, modeChoices.size());
267
268 choice = modeChoices.get(kDisplayId1);
269 ASSERT_TRUE(choice);
Ady Abrahamace3d052022-11-17 16:25:05 -0800270 EXPECT_EQ(choice->get(), DisplayModeChoice({120_Hz, kDisplay1Mode120}, globalSignals));
ramindani69b58e82022-09-26 16:48:36 -0700271
272 globalSignals = {.touch = true};
273 mScheduler->replaceTouchTimer(10);
274 mScheduler->setTouchStateAndIdleTimerPolicy(globalSignals);
ramindani69b58e82022-09-26 16:48:36 -0700275
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400276 modeChoices = mScheduler->chooseDisplayModes();
277 ASSERT_EQ(1u, modeChoices.size());
278
279 choice = modeChoices.get(kDisplayId1);
280 ASSERT_TRUE(choice);
Ady Abrahamace3d052022-11-17 16:25:05 -0800281 EXPECT_EQ(choice->get(), DisplayModeChoice({120_Hz, kDisplay1Mode120}, globalSignals));
ramindani69b58e82022-09-26 16:48:36 -0700282}
283
Rachel Lee6ed96c92024-02-07 14:37:38 -0800284TEST_F(SchedulerTest, chooseDisplayModesSingleDisplayHighHintTouchSignal) {
285 mScheduler->registerDisplay(kDisplayId1,
286 std::make_shared<RefreshRateSelector>(kDisplay1Modes,
287 kDisplay1Mode60->getId()));
288
289 using DisplayModeChoice = TestableScheduler::DisplayModeChoice;
290
291 std::vector<RefreshRateSelector::LayerRequirement> layers =
292 std::vector<RefreshRateSelector::LayerRequirement>({{.weight = 1.f}, {.weight = 1.f}});
293 auto& lr1 = layers[0];
294 auto& lr2 = layers[1];
295
296 // Scenario that is similar to game. Expects no touch boost.
297 lr1.vote = RefreshRateSelector::LayerVoteType::ExplicitCategory;
298 lr1.frameRateCategory = FrameRateCategory::HighHint;
299 lr1.name = "ExplicitCategory HighHint";
300 lr2.vote = RefreshRateSelector::LayerVoteType::ExplicitDefault;
301 lr2.desiredRefreshRate = 30_Hz;
302 lr2.name = "30Hz ExplicitDefault";
303 mScheduler->setContentRequirements(layers);
304 auto modeChoices = mScheduler->chooseDisplayModes();
305 ASSERT_EQ(1u, modeChoices.size());
306 auto choice = modeChoices.get(kDisplayId1);
307 ASSERT_TRUE(choice);
308 EXPECT_EQ(choice->get(), DisplayModeChoice({60_Hz, kDisplay1Mode60}, {.touch = false}));
309
310 // Scenario that is similar to video playback and interaction. Expects touch boost.
311 lr1.vote = RefreshRateSelector::LayerVoteType::ExplicitCategory;
312 lr1.frameRateCategory = FrameRateCategory::HighHint;
313 lr1.name = "ExplicitCategory HighHint";
314 lr2.vote = RefreshRateSelector::LayerVoteType::ExplicitExactOrMultiple;
315 lr2.desiredRefreshRate = 30_Hz;
316 lr2.name = "30Hz ExplicitExactOrMultiple";
317 mScheduler->setContentRequirements(layers);
318 modeChoices = mScheduler->chooseDisplayModes();
319 ASSERT_EQ(1u, modeChoices.size());
320 choice = modeChoices.get(kDisplayId1);
321 ASSERT_TRUE(choice);
322 EXPECT_EQ(choice->get(), DisplayModeChoice({120_Hz, kDisplay1Mode120}, {.touch = true}));
323
324 // Scenario with explicit category and HighHint. Expects touch boost.
325 lr1.vote = RefreshRateSelector::LayerVoteType::ExplicitCategory;
326 lr1.frameRateCategory = FrameRateCategory::HighHint;
327 lr1.name = "ExplicitCategory HighHint";
328 lr2.vote = RefreshRateSelector::LayerVoteType::ExplicitCategory;
329 lr2.frameRateCategory = FrameRateCategory::Low;
330 lr2.name = "ExplicitCategory Low";
331 mScheduler->setContentRequirements(layers);
332 modeChoices = mScheduler->chooseDisplayModes();
333 ASSERT_EQ(1u, modeChoices.size());
334 choice = modeChoices.get(kDisplayId1);
335 ASSERT_TRUE(choice);
336 EXPECT_EQ(choice->get(), DisplayModeChoice({120_Hz, kDisplay1Mode120}, {.touch = true}));
337}
338
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400339TEST_F(SchedulerTest, chooseDisplayModesMultipleDisplays) {
Dominik Laskowskib5a094b2022-10-27 12:00:12 -0400340 mScheduler->registerDisplay(kDisplayId1,
341 std::make_shared<RefreshRateSelector>(kDisplay1Modes,
342 kDisplay1Mode60->getId()));
343 mScheduler->registerDisplay(kDisplayId2,
344 std::make_shared<RefreshRateSelector>(kDisplay2Modes,
345 kDisplay2Mode60->getId()));
ramindani69b58e82022-09-26 16:48:36 -0700346
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400347 using DisplayModeChoice = TestableScheduler::DisplayModeChoice;
348 TestableScheduler::DisplayModeChoiceMap expectedChoices;
ramindani69b58e82022-09-26 16:48:36 -0700349
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400350 {
351 const GlobalSignals globalSignals = {.idle = true};
352 expectedChoices =
353 ftl::init::map<const PhysicalDisplayId&,
Ady Abrahamace3d052022-11-17 16:25:05 -0800354 DisplayModeChoice>(kDisplayId1,
355 FrameRateMode{60_Hz, kDisplay1Mode60},
356 globalSignals)(kDisplayId2,
357 FrameRateMode{60_Hz,
358 kDisplay2Mode60},
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400359 globalSignals);
360
Dominik Laskowskid82e0f02022-10-26 15:23:04 -0400361 std::vector<RefreshRateSelector::LayerRequirement> layers = {{.weight = 1.f},
362 {.weight = 1.f}};
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400363 mScheduler->setContentRequirements(layers);
364 mScheduler->setTouchStateAndIdleTimerPolicy(globalSignals);
365
366 const auto actualChoices = mScheduler->chooseDisplayModes();
367 EXPECT_EQ(expectedChoices, actualChoices);
ramindani69b58e82022-09-26 16:48:36 -0700368 }
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400369 {
370 const GlobalSignals globalSignals = {.idle = false};
371 expectedChoices =
372 ftl::init::map<const PhysicalDisplayId&,
Ady Abrahamace3d052022-11-17 16:25:05 -0800373 DisplayModeChoice>(kDisplayId1,
374 FrameRateMode{120_Hz, kDisplay1Mode120},
375 globalSignals)(kDisplayId2,
376 FrameRateMode{120_Hz,
377 kDisplay2Mode120},
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400378 globalSignals);
ramindani69b58e82022-09-26 16:48:36 -0700379
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400380 mScheduler->setTouchStateAndIdleTimerPolicy(globalSignals);
ramindani69b58e82022-09-26 16:48:36 -0700381
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400382 const auto actualChoices = mScheduler->chooseDisplayModes();
383 EXPECT_EQ(expectedChoices, actualChoices);
ramindani69b58e82022-09-26 16:48:36 -0700384 }
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400385 {
386 const GlobalSignals globalSignals = {.touch = true};
387 mScheduler->replaceTouchTimer(10);
388 mScheduler->setTouchStateAndIdleTimerPolicy(globalSignals);
ramindani69b58e82022-09-26 16:48:36 -0700389
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400390 expectedChoices =
391 ftl::init::map<const PhysicalDisplayId&,
Ady Abrahamace3d052022-11-17 16:25:05 -0800392 DisplayModeChoice>(kDisplayId1,
393 FrameRateMode{120_Hz, kDisplay1Mode120},
394 globalSignals)(kDisplayId2,
395 FrameRateMode{120_Hz,
396 kDisplay2Mode120},
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400397 globalSignals);
398
399 const auto actualChoices = mScheduler->chooseDisplayModes();
400 EXPECT_EQ(expectedChoices, actualChoices);
ramindani69b58e82022-09-26 16:48:36 -0700401 }
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400402 {
ramindani22f2ead2023-04-21 10:27:11 -0700403 // The kDisplayId3 does not support 120Hz, The pacesetter display rate is chosen to be 120
404 // Hz. In this case only the display kDisplayId3 choose 60Hz as it does not support 120Hz.
Dominik Laskowskib5a094b2022-10-27 12:00:12 -0400405 mScheduler
406 ->registerDisplay(kDisplayId3,
407 std::make_shared<RefreshRateSelector>(kDisplay3Modes,
408 kDisplay3Mode60->getId()));
Dominik Laskowski327d6092022-10-11 18:05:08 -0400409
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400410 const GlobalSignals globalSignals = {.touch = true};
411 mScheduler->replaceTouchTimer(10);
412 mScheduler->setTouchStateAndIdleTimerPolicy(globalSignals);
ramindani7c487282022-10-10 16:17:51 -0700413
Ady Abrahamace3d052022-11-17 16:25:05 -0800414 expectedChoices = ftl::init::map<
415 const PhysicalDisplayId&,
ramindani22f2ead2023-04-21 10:27:11 -0700416 DisplayModeChoice>(kDisplayId1, FrameRateMode{120_Hz, kDisplay1Mode120},
417 globalSignals)(kDisplayId2,
418 FrameRateMode{120_Hz, kDisplay2Mode120},
419 globalSignals)(kDisplayId3,
420 FrameRateMode{60_Hz,
421 kDisplay3Mode60},
422 globalSignals);
423
424 const auto actualChoices = mScheduler->chooseDisplayModes();
425 EXPECT_EQ(expectedChoices, actualChoices);
426 }
427 {
428 // We should choose 60Hz despite the touch signal as pacesetter only supports 60Hz
429 mScheduler->setPacesetterDisplay(kDisplayId3);
430 const GlobalSignals globalSignals = {.touch = true};
431 mScheduler->replaceTouchTimer(10);
432 mScheduler->setTouchStateAndIdleTimerPolicy(globalSignals);
433
434 expectedChoices = ftl::init::map<
435 const PhysicalDisplayId&,
Ady Abrahamace3d052022-11-17 16:25:05 -0800436 DisplayModeChoice>(kDisplayId1, FrameRateMode{60_Hz, kDisplay1Mode60},
437 globalSignals)(kDisplayId2,
438 FrameRateMode{60_Hz, kDisplay2Mode60},
439 globalSignals)(kDisplayId3,
440 FrameRateMode{60_Hz,
441 kDisplay3Mode60},
442 globalSignals);
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400443
444 const auto actualChoices = mScheduler->chooseDisplayModes();
445 EXPECT_EQ(expectedChoices, actualChoices);
ramindani7c487282022-10-10 16:17:51 -0700446 }
ramindani69b58e82022-09-26 16:48:36 -0700447}
448
Dominik Laskowski50e2e4d2023-10-04 10:58:28 -0400449TEST_F(SchedulerTest, onFrameSignalMultipleDisplays) {
450 mScheduler->registerDisplay(kDisplayId1,
451 std::make_shared<RefreshRateSelector>(kDisplay1Modes,
452 kDisplay1Mode60->getId()));
453 mScheduler->registerDisplay(kDisplayId2,
454 std::make_shared<RefreshRateSelector>(kDisplay2Modes,
455 kDisplay2Mode60->getId()));
456
457 using VsyncIds = std::vector<std::pair<PhysicalDisplayId, VsyncId>>;
458
459 struct Compositor final : ICompositor {
Dominik Laskowskifb4b7372023-11-22 09:56:54 -0500460 explicit Compositor(TestableScheduler& scheduler) : scheduler(scheduler) {}
461
462 TestableScheduler& scheduler;
463
464 struct {
465 PhysicalDisplayId commit;
466 PhysicalDisplayId composite;
467 } pacesetterIds;
468
469 struct {
470 VsyncIds commit;
471 VsyncIds composite;
472 } vsyncIds;
473
Dominik Laskowski50e2e4d2023-10-04 10:58:28 -0400474 bool committed = true;
Dominik Laskowskifb4b7372023-11-22 09:56:54 -0500475 bool changePacesetter = false;
Dominik Laskowski50e2e4d2023-10-04 10:58:28 -0400476
477 void configure() override {}
478
Dominik Laskowskifb4b7372023-11-22 09:56:54 -0500479 bool commit(PhysicalDisplayId pacesetterId,
480 const scheduler::FrameTargets& targets) override {
481 pacesetterIds.commit = pacesetterId;
482
483 vsyncIds.commit.clear();
484 vsyncIds.composite.clear();
Dominik Laskowski50e2e4d2023-10-04 10:58:28 -0400485
486 for (const auto& [id, target] : targets) {
Dominik Laskowskifb4b7372023-11-22 09:56:54 -0500487 vsyncIds.commit.emplace_back(id, target->vsyncId());
488 }
489
490 if (changePacesetter) {
491 scheduler.setPacesetterDisplay(kDisplayId2);
Dominik Laskowski50e2e4d2023-10-04 10:58:28 -0400492 }
493
494 return committed;
495 }
496
Dominik Laskowskifb4b7372023-11-22 09:56:54 -0500497 CompositeResultsPerDisplay composite(PhysicalDisplayId pacesetterId,
498 const scheduler::FrameTargeters& targeters) override {
499 pacesetterIds.composite = pacesetterId;
500
Dominik Laskowski50e2e4d2023-10-04 10:58:28 -0400501 CompositeResultsPerDisplay results;
502
Dominik Laskowskifb4b7372023-11-22 09:56:54 -0500503 for (const auto& [id, targeter] : targeters) {
504 vsyncIds.composite.emplace_back(id, targeter->target().vsyncId());
Dominik Laskowski50e2e4d2023-10-04 10:58:28 -0400505 results.try_emplace(id,
506 CompositeResult{.compositionCoverage =
507 CompositionCoverage::Hwc});
508 }
509
510 return results;
511 }
512
513 void sample() override {}
ramindaniae645822024-01-11 10:57:29 -0800514 void sendNotifyExpectedPresentHint(PhysicalDisplayId) override {}
Dominik Laskowskifb4b7372023-11-22 09:56:54 -0500515 } compositor(*mScheduler);
Dominik Laskowski50e2e4d2023-10-04 10:58:28 -0400516
517 mScheduler->doFrameSignal(compositor, VsyncId(42));
518
Dominik Laskowskifb4b7372023-11-22 09:56:54 -0500519 const auto makeVsyncIds = [](VsyncId vsyncId, bool swap = false) -> VsyncIds {
520 if (swap) {
521 return {{kDisplayId2, vsyncId}, {kDisplayId1, vsyncId}};
522 } else {
523 return {{kDisplayId1, vsyncId}, {kDisplayId2, vsyncId}};
524 }
Dominik Laskowski50e2e4d2023-10-04 10:58:28 -0400525 };
526
Dominik Laskowskifb4b7372023-11-22 09:56:54 -0500527 EXPECT_EQ(kDisplayId1, compositor.pacesetterIds.commit);
528 EXPECT_EQ(kDisplayId1, compositor.pacesetterIds.composite);
529 EXPECT_EQ(makeVsyncIds(VsyncId(42)), compositor.vsyncIds.commit);
530 EXPECT_EQ(makeVsyncIds(VsyncId(42)), compositor.vsyncIds.composite);
Dominik Laskowski50e2e4d2023-10-04 10:58:28 -0400531
Dominik Laskowskifb4b7372023-11-22 09:56:54 -0500532 // FrameTargets should be updated despite the skipped commit.
Dominik Laskowski50e2e4d2023-10-04 10:58:28 -0400533 compositor.committed = false;
534 mScheduler->doFrameSignal(compositor, VsyncId(43));
535
Dominik Laskowskifb4b7372023-11-22 09:56:54 -0500536 EXPECT_EQ(kDisplayId1, compositor.pacesetterIds.commit);
537 EXPECT_EQ(kDisplayId1, compositor.pacesetterIds.composite);
538 EXPECT_EQ(makeVsyncIds(VsyncId(43)), compositor.vsyncIds.commit);
539 EXPECT_TRUE(compositor.vsyncIds.composite.empty());
540
541 // The pacesetter may change during commit.
542 compositor.committed = true;
543 compositor.changePacesetter = true;
544 mScheduler->doFrameSignal(compositor, VsyncId(44));
545
546 EXPECT_EQ(kDisplayId1, compositor.pacesetterIds.commit);
547 EXPECT_EQ(kDisplayId2, compositor.pacesetterIds.composite);
548 EXPECT_EQ(makeVsyncIds(VsyncId(44)), compositor.vsyncIds.commit);
549 EXPECT_EQ(makeVsyncIds(VsyncId(44), true), compositor.vsyncIds.composite);
Dominik Laskowski50e2e4d2023-10-04 10:58:28 -0400550}
551
ramindani0491e642023-11-16 17:42:14 -0800552TEST_F(SchedulerTest, nextFrameIntervalTest) {
553 SET_FLAG_FOR_TEST(flags::vrr_config, true);
554
555 static constexpr size_t kHistorySize = 10;
556 static constexpr size_t kMinimumSamplesForPrediction = 6;
557 static constexpr size_t kOutlierTolerancePercent = 25;
558 const auto refreshRate = Fps::fromPeriodNsecs(500);
559 auto frameRate = Fps::fromPeriodNsecs(1000);
560
561 const ftl::NonNull<DisplayModePtr> kMode = ftl::as_non_null(
562 createVrrDisplayMode(DisplayModeId(0), refreshRate,
563 hal::VrrConfig{.minFrameIntervalNs = static_cast<int32_t>(
564 frameRate.getPeriodNsecs())}));
565 std::shared_ptr<VSyncPredictor> vrrTracker =
Ady Abraham9633f8e2024-03-04 19:38:12 +0000566 std::make_shared<VSyncPredictor>(kMode, kHistorySize, kMinimumSamplesForPrediction,
ramindaniae645822024-01-11 10:57:29 -0800567 kOutlierTolerancePercent);
ramindani0491e642023-11-16 17:42:14 -0800568 std::shared_ptr<RefreshRateSelector> vrrSelectorPtr =
569 std::make_shared<RefreshRateSelector>(makeModes(kMode), kMode->getId());
570 TestableScheduler scheduler{std::make_unique<android::mock::VsyncController>(),
571 vrrTracker,
572 vrrSelectorPtr,
Leon Scroggins III823d4ca2023-12-12 16:57:34 -0500573 mFlinger.getFactory(),
574 mFlinger.getTimeStats(),
ramindaniae645822024-01-11 10:57:29 -0800575 mSchedulerCallback};
ramindani0491e642023-11-16 17:42:14 -0800576
577 scheduler.registerDisplay(kMode->getPhysicalDisplayId(), vrrSelectorPtr, vrrTracker);
578 vrrSelectorPtr->setActiveMode(kMode->getId(), frameRate);
579 scheduler.setRenderRate(kMode->getPhysicalDisplayId(), frameRate);
580 vrrTracker->addVsyncTimestamp(0);
581
ramindani0491e642023-11-16 17:42:14 -0800582 EXPECT_EQ(Fps::fromPeriodNsecs(1000),
583 scheduler.getNextFrameInterval(kMode->getPhysicalDisplayId(),
Ady Abraham4335afd2023-12-18 19:10:47 -0800584 TimePoint::fromNs(1000)));
ramindani0491e642023-11-16 17:42:14 -0800585 EXPECT_EQ(Fps::fromPeriodNsecs(1000),
586 scheduler.getNextFrameInterval(kMode->getPhysicalDisplayId(),
Ady Abraham4335afd2023-12-18 19:10:47 -0800587 TimePoint::fromNs(2000)));
ramindani0491e642023-11-16 17:42:14 -0800588
Ady Abraham4335afd2023-12-18 19:10:47 -0800589 // Not crossing the min frame period
Ady Abraham9633f8e2024-03-04 19:38:12 +0000590 EXPECT_EQ(Fps::fromPeriodNsecs(1500),
Ady Abraham4335afd2023-12-18 19:10:47 -0800591 scheduler.getNextFrameInterval(kMode->getPhysicalDisplayId(),
592 TimePoint::fromNs(2500)));
ramindani0491e642023-11-16 17:42:14 -0800593 // Change render rate
594 frameRate = Fps::fromPeriodNsecs(2000);
595 vrrSelectorPtr->setActiveMode(kMode->getId(), frameRate);
596 scheduler.setRenderRate(kMode->getPhysicalDisplayId(), frameRate);
597
598 EXPECT_EQ(Fps::fromPeriodNsecs(2000),
599 scheduler.getNextFrameInterval(kMode->getPhysicalDisplayId(),
Ady Abraham4335afd2023-12-18 19:10:47 -0800600 TimePoint::fromNs(2000)));
ramindani0491e642023-11-16 17:42:14 -0800601 EXPECT_EQ(Fps::fromPeriodNsecs(2000),
602 scheduler.getNextFrameInterval(kMode->getPhysicalDisplayId(),
Ady Abraham4335afd2023-12-18 19:10:47 -0800603 TimePoint::fromNs(4000)));
ramindani0491e642023-11-16 17:42:14 -0800604}
605
Leon Scroggins III792ea802023-11-27 17:32:51 -0500606TEST_F(SchedulerTest, resyncAllToHardwareVsync) FTL_FAKE_GUARD(kMainThreadContext) {
607 // resyncAllToHardwareVsync will result in requesting hardware VSYNC on both displays, since
608 // they are both on.
609 EXPECT_CALL(mScheduler->mockRequestHardwareVsync, Call(kDisplayId1, true)).Times(1);
610 EXPECT_CALL(mScheduler->mockRequestHardwareVsync, Call(kDisplayId2, true)).Times(1);
611
612 mScheduler->registerDisplay(kDisplayId2,
613 std::make_shared<RefreshRateSelector>(kDisplay2Modes,
614 kDisplay2Mode60->getId()));
615 mScheduler->setDisplayPowerMode(kDisplayId1, hal::PowerMode::ON);
616 mScheduler->setDisplayPowerMode(kDisplayId2, hal::PowerMode::ON);
617
618 static constexpr bool kDisallow = true;
619 mScheduler->disableHardwareVsync(kDisplayId1, kDisallow);
620 mScheduler->disableHardwareVsync(kDisplayId2, kDisallow);
621
622 static constexpr bool kAllowToEnable = true;
623 mScheduler->resyncAllToHardwareVsync(kAllowToEnable);
624}
625
626TEST_F(SchedulerTest, resyncAllDoNotAllow) FTL_FAKE_GUARD(kMainThreadContext) {
627 // Without setting allowToEnable to true, resyncAllToHardwareVsync does not
628 // result in requesting hardware VSYNC.
629 EXPECT_CALL(mScheduler->mockRequestHardwareVsync, Call(kDisplayId1, _)).Times(0);
630
631 mScheduler->setDisplayPowerMode(kDisplayId1, hal::PowerMode::ON);
632
633 static constexpr bool kDisallow = true;
634 mScheduler->disableHardwareVsync(kDisplayId1, kDisallow);
635
636 static constexpr bool kAllowToEnable = false;
637 mScheduler->resyncAllToHardwareVsync(kAllowToEnable);
638}
639
640TEST_F(SchedulerTest, resyncAllSkipsOffDisplays) FTL_FAKE_GUARD(kMainThreadContext) {
641 SET_FLAG_FOR_TEST(flags::multithreaded_present, true);
642
643 // resyncAllToHardwareVsync will result in requesting hardware VSYNC on display 1, which is on,
644 // but not on display 2, which is off.
645 EXPECT_CALL(mScheduler->mockRequestHardwareVsync, Call(kDisplayId1, true)).Times(1);
646 EXPECT_CALL(mScheduler->mockRequestHardwareVsync, Call(kDisplayId2, _)).Times(0);
647
648 mScheduler->setDisplayPowerMode(kDisplayId1, hal::PowerMode::ON);
649
650 mScheduler->registerDisplay(kDisplayId2,
651 std::make_shared<RefreshRateSelector>(kDisplay2Modes,
652 kDisplay2Mode60->getId()));
653 ASSERT_EQ(hal::PowerMode::OFF, mScheduler->getDisplayPowerMode(kDisplayId2));
654
655 static constexpr bool kDisallow = true;
656 mScheduler->disableHardwareVsync(kDisplayId1, kDisallow);
657 mScheduler->disableHardwareVsync(kDisplayId2, kDisallow);
658
659 static constexpr bool kAllowToEnable = true;
660 mScheduler->resyncAllToHardwareVsync(kAllowToEnable);
661}
662
663TEST_F(SchedulerTest, resyncAllLegacyAppliesToOffDisplays) FTL_FAKE_GUARD(kMainThreadContext) {
664 SET_FLAG_FOR_TEST(flags::multithreaded_present, false);
665
666 // In the legacy code, prior to the flag, resync applied to OFF displays.
667 EXPECT_CALL(mScheduler->mockRequestHardwareVsync, Call(kDisplayId1, true)).Times(1);
668 EXPECT_CALL(mScheduler->mockRequestHardwareVsync, Call(kDisplayId2, true)).Times(1);
669
670 mScheduler->setDisplayPowerMode(kDisplayId1, hal::PowerMode::ON);
671
672 mScheduler->registerDisplay(kDisplayId2,
673 std::make_shared<RefreshRateSelector>(kDisplay2Modes,
674 kDisplay2Mode60->getId()));
675 ASSERT_EQ(hal::PowerMode::OFF, mScheduler->getDisplayPowerMode(kDisplayId2));
676
677 static constexpr bool kDisallow = true;
678 mScheduler->disableHardwareVsync(kDisplayId1, kDisallow);
679 mScheduler->disableHardwareVsync(kDisplayId2, kDisallow);
680
681 static constexpr bool kAllowToEnable = true;
682 mScheduler->resyncAllToHardwareVsync(kAllowToEnable);
683}
684
Ady Abraham822ecbd2023-07-07 16:16:09 -0700685class AttachedChoreographerTest : public SchedulerTest {
686protected:
687 void frameRateTestScenario(Fps layerFps, int8_t frameRateCompatibility, Fps displayFps,
688 Fps expectedChoreographerFps);
689};
690
691TEST_F(AttachedChoreographerTest, registerSingle) {
692 EXPECT_TRUE(mScheduler->mutableAttachedChoreographers().empty());
693
694 const sp<MockLayer> layer = sp<MockLayer>::make(mFlinger.flinger());
695
696 EXPECT_CALL(mSchedulerCallback, onChoreographerAttached);
697 const sp<IDisplayEventConnection> connection =
Dominik Laskowski4babfc42024-02-16 12:28:40 -0500698 mScheduler->createDisplayEventConnection(Cycle::Render, {}, layer->getHandle());
Ady Abraham822ecbd2023-07-07 16:16:09 -0700699
700 EXPECT_EQ(1u, mScheduler->mutableAttachedChoreographers().size());
701 ASSERT_EQ(1u, mScheduler->mutableAttachedChoreographers().count(layer->getSequence()));
702 EXPECT_EQ(1u,
703 mScheduler->mutableAttachedChoreographers()[layer->getSequence()].connections.size());
704 EXPECT_FALSE(
705 mScheduler->mutableAttachedChoreographers()[layer->getSequence()].frameRate.isValid());
706}
707
708TEST_F(AttachedChoreographerTest, registerMultipleOnSameLayer) {
709 EXPECT_TRUE(mScheduler->mutableAttachedChoreographers().empty());
710
711 const sp<MockLayer> layer = sp<MockLayer>::make(mFlinger.flinger());
712 const auto handle = layer->getHandle();
713
714 EXPECT_CALL(mSchedulerCallback, onChoreographerAttached).Times(2);
715
716 EXPECT_CALL(*mEventThread, registerDisplayEventConnection(_))
717 .WillOnce(Return(0))
718 .WillOnce(Return(0));
719
720 const auto mockConnection1 = sp<MockEventThreadConnection>::make(mEventThread);
721 const auto mockConnection2 = sp<MockEventThreadConnection>::make(mEventThread);
722 EXPECT_CALL(*mEventThread, createEventConnection(_, _))
723 .WillOnce(Return(mockConnection1))
724 .WillOnce(Return(mockConnection2));
725
726 const sp<IDisplayEventConnection> connection1 =
Dominik Laskowski4babfc42024-02-16 12:28:40 -0500727 mScheduler->createDisplayEventConnection(Cycle::Render, {}, handle);
Ady Abraham822ecbd2023-07-07 16:16:09 -0700728 const sp<IDisplayEventConnection> connection2 =
Dominik Laskowski4babfc42024-02-16 12:28:40 -0500729 mScheduler->createDisplayEventConnection(Cycle::Render, {}, handle);
Ady Abraham822ecbd2023-07-07 16:16:09 -0700730
731 EXPECT_EQ(1u, mScheduler->mutableAttachedChoreographers().size());
732 ASSERT_EQ(1u, mScheduler->mutableAttachedChoreographers().count(layer->getSequence()));
733 EXPECT_EQ(2u,
734 mScheduler->mutableAttachedChoreographers()[layer->getSequence()].connections.size());
735 EXPECT_FALSE(
736 mScheduler->mutableAttachedChoreographers()[layer->getSequence()].frameRate.isValid());
737}
738
739TEST_F(AttachedChoreographerTest, registerMultipleOnDifferentLayers) {
740 EXPECT_TRUE(mScheduler->mutableAttachedChoreographers().empty());
741
742 const sp<MockLayer> layer1 = sp<MockLayer>::make(mFlinger.flinger());
743 const sp<MockLayer> layer2 = sp<MockLayer>::make(mFlinger.flinger());
744
745 EXPECT_CALL(mSchedulerCallback, onChoreographerAttached).Times(2);
746 const sp<IDisplayEventConnection> connection1 =
Dominik Laskowski4babfc42024-02-16 12:28:40 -0500747 mScheduler->createDisplayEventConnection(Cycle::Render, {}, layer1->getHandle());
Ady Abraham822ecbd2023-07-07 16:16:09 -0700748 const sp<IDisplayEventConnection> connection2 =
Dominik Laskowski4babfc42024-02-16 12:28:40 -0500749 mScheduler->createDisplayEventConnection(Cycle::Render, {}, layer2->getHandle());
Ady Abraham822ecbd2023-07-07 16:16:09 -0700750
751 EXPECT_EQ(2u, mScheduler->mutableAttachedChoreographers().size());
752
753 ASSERT_EQ(1u, mScheduler->mutableAttachedChoreographers().count(layer1->getSequence()));
754 EXPECT_EQ(1u,
755 mScheduler->mutableAttachedChoreographers()[layer1->getSequence()]
756 .connections.size());
757 EXPECT_FALSE(
758 mScheduler->mutableAttachedChoreographers()[layer1->getSequence()].frameRate.isValid());
759
760 ASSERT_EQ(1u, mScheduler->mutableAttachedChoreographers().count(layer2->getSequence()));
761 EXPECT_EQ(1u,
762 mScheduler->mutableAttachedChoreographers()[layer2->getSequence()]
763 .connections.size());
764 EXPECT_FALSE(
765 mScheduler->mutableAttachedChoreographers()[layer2->getSequence()].frameRate.isValid());
766}
767
768TEST_F(AttachedChoreographerTest, removedWhenConnectionIsGone) {
769 EXPECT_TRUE(mScheduler->mutableAttachedChoreographers().empty());
770
771 const sp<MockLayer> layer = sp<MockLayer>::make(mFlinger.flinger());
772
773 EXPECT_CALL(mSchedulerCallback, onChoreographerAttached);
774
775 sp<IDisplayEventConnection> connection =
Dominik Laskowski4babfc42024-02-16 12:28:40 -0500776 mScheduler->createDisplayEventConnection(Cycle::Render, {}, layer->getHandle());
Ady Abraham822ecbd2023-07-07 16:16:09 -0700777
778 ASSERT_EQ(1u, mScheduler->mutableAttachedChoreographers().count(layer->getSequence()));
779 EXPECT_EQ(1u,
780 mScheduler->mutableAttachedChoreographers()[layer->getSequence()].connections.size());
781
782 // The connection is used all over this test, so it is quite hard to release it from here.
783 // Instead, we just do a small shortcut.
784 {
785 EXPECT_CALL(*mEventThread, registerDisplayEventConnection(_)).WillOnce(Return(0));
786 sp<MockEventThreadConnection> mockConnection =
787 sp<MockEventThreadConnection>::make(mEventThread);
788 mScheduler->mutableAttachedChoreographers()[layer->getSequence()].connections.clear();
789 mScheduler->mutableAttachedChoreographers()[layer->getSequence()].connections.emplace(
790 mockConnection);
791 }
792
793 RequestedLayerState layerState(LayerCreationArgs(layer->getSequence()));
794 LayerHierarchy hierarchy(&layerState);
795 mScheduler->updateAttachedChoreographers(hierarchy, 60_Hz);
796 EXPECT_TRUE(mScheduler->mutableAttachedChoreographers().empty());
797}
798
799TEST_F(AttachedChoreographerTest, removedWhenLayerIsGone) {
800 EXPECT_TRUE(mScheduler->mutableAttachedChoreographers().empty());
801
802 sp<MockLayer> layer = sp<MockLayer>::make(mFlinger.flinger());
803
804 EXPECT_CALL(mSchedulerCallback, onChoreographerAttached);
805 const sp<IDisplayEventConnection> connection =
Dominik Laskowski4babfc42024-02-16 12:28:40 -0500806 mScheduler->createDisplayEventConnection(Cycle::Render, {}, layer->getHandle());
Ady Abraham822ecbd2023-07-07 16:16:09 -0700807
808 layer.clear();
809 mFlinger.mutableLayersPendingRemoval().clear();
810 EXPECT_TRUE(mScheduler->mutableAttachedChoreographers().empty());
811}
812
813void AttachedChoreographerTest::frameRateTestScenario(Fps layerFps, int8_t frameRateCompatibility,
814 Fps displayFps,
815 Fps expectedChoreographerFps) {
816 const sp<MockLayer> layer = sp<MockLayer>::make(mFlinger.flinger());
817
818 EXPECT_CALL(mSchedulerCallback, onChoreographerAttached);
819 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 RequestedLayerState layerState(LayerCreationArgs(layer->getSequence()));
823 LayerHierarchy hierarchy(&layerState);
824
825 layerState.frameRate = layerFps.getValue();
826 layerState.frameRateCompatibility = frameRateCompatibility;
827
828 mScheduler->updateAttachedChoreographers(hierarchy, displayFps);
829
830 ASSERT_EQ(1u, mScheduler->mutableAttachedChoreographers().count(layer->getSequence()));
831 EXPECT_EQ(expectedChoreographerFps,
832 mScheduler->mutableAttachedChoreographers()[layer->getSequence()].frameRate);
833 EXPECT_EQ(expectedChoreographerFps, mEventThreadConnection->frameRate);
834}
835
836TEST_F(AttachedChoreographerTest, setsFrameRateDefault) {
837 Fps layerFps = 30_Hz;
838 int8_t frameRateCompatibility = ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT;
839 Fps displayFps = 60_Hz;
840 Fps expectedChoreographerFps = 30_Hz;
841
842 frameRateTestScenario(layerFps, frameRateCompatibility, displayFps, expectedChoreographerFps);
843
844 layerFps = Fps::fromValue(32.7f);
845 frameRateTestScenario(layerFps, frameRateCompatibility, displayFps, expectedChoreographerFps);
846}
847
848TEST_F(AttachedChoreographerTest, setsFrameRateExact) {
849 Fps layerFps = 30_Hz;
850 int8_t frameRateCompatibility = ANATIVEWINDOW_FRAME_RATE_EXACT;
851 Fps displayFps = 60_Hz;
852 Fps expectedChoreographerFps = 30_Hz;
853
854 frameRateTestScenario(layerFps, frameRateCompatibility, displayFps, expectedChoreographerFps);
855
856 layerFps = Fps::fromValue(32.7f);
857 expectedChoreographerFps = {};
858 frameRateTestScenario(layerFps, frameRateCompatibility, displayFps, expectedChoreographerFps);
859}
860
861TEST_F(AttachedChoreographerTest, setsFrameRateExactOrMultiple) {
862 Fps layerFps = 30_Hz;
863 int8_t frameRateCompatibility = ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_FIXED_SOURCE;
864 Fps displayFps = 60_Hz;
865 Fps expectedChoreographerFps = 30_Hz;
866
867 frameRateTestScenario(layerFps, frameRateCompatibility, displayFps, expectedChoreographerFps);
868
869 layerFps = Fps::fromValue(32.7f);
870 expectedChoreographerFps = {};
871 frameRateTestScenario(layerFps, frameRateCompatibility, displayFps, expectedChoreographerFps);
872}
873
874TEST_F(AttachedChoreographerTest, setsFrameRateParent) {
875 const sp<MockLayer> layer = sp<MockLayer>::make(mFlinger.flinger());
876 const sp<MockLayer> parent = sp<MockLayer>::make(mFlinger.flinger());
877
878 EXPECT_CALL(mSchedulerCallback, onChoreographerAttached);
879 sp<IDisplayEventConnection> connection =
Dominik Laskowski4babfc42024-02-16 12:28:40 -0500880 mScheduler->createDisplayEventConnection(Cycle::Render, {}, parent->getHandle());
Ady Abraham822ecbd2023-07-07 16:16:09 -0700881
882 RequestedLayerState parentState(LayerCreationArgs(parent->getSequence()));
883 LayerHierarchy parentHierarchy(&parentState);
884
885 RequestedLayerState layerState(LayerCreationArgs(layer->getSequence()));
886 LayerHierarchy hierarchy(&layerState);
887 parentHierarchy.mChildren.push_back(
888 std::make_pair(&hierarchy, LayerHierarchy::Variant::Attached));
889
890 layerState.frameRate = (30_Hz).getValue();
891 layerState.frameRateCompatibility = ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT;
892
893 mScheduler->updateAttachedChoreographers(parentHierarchy, 120_Hz);
894
895 ASSERT_EQ(1u, mScheduler->mutableAttachedChoreographers().count(parent->getSequence()));
896
897 EXPECT_EQ(30_Hz, mScheduler->mutableAttachedChoreographers()[parent->getSequence()].frameRate);
898}
899
900TEST_F(AttachedChoreographerTest, setsFrameRateParent2Children) {
901 const sp<MockLayer> layer1 = sp<MockLayer>::make(mFlinger.flinger());
902 const sp<MockLayer> layer2 = sp<MockLayer>::make(mFlinger.flinger());
903 const sp<MockLayer> parent = sp<MockLayer>::make(mFlinger.flinger());
904
905 EXPECT_CALL(mSchedulerCallback, onChoreographerAttached);
906 sp<IDisplayEventConnection> connection =
Dominik Laskowski4babfc42024-02-16 12:28:40 -0500907 mScheduler->createDisplayEventConnection(Cycle::Render, {}, parent->getHandle());
Ady Abraham822ecbd2023-07-07 16:16:09 -0700908
909 RequestedLayerState parentState(LayerCreationArgs(parent->getSequence()));
910 LayerHierarchy parentHierarchy(&parentState);
911
912 RequestedLayerState layer1State(LayerCreationArgs(layer1->getSequence()));
913 LayerHierarchy layer1Hierarchy(&layer1State);
914 parentHierarchy.mChildren.push_back(
915 std::make_pair(&layer1Hierarchy, LayerHierarchy::Variant::Attached));
916
917 RequestedLayerState layer2State(LayerCreationArgs(layer1->getSequence()));
918 LayerHierarchy layer2Hierarchy(&layer2State);
919 parentHierarchy.mChildren.push_back(
920 std::make_pair(&layer2Hierarchy, LayerHierarchy::Variant::Attached));
921
922 layer1State.frameRate = (30_Hz).getValue();
923 layer1State.frameRateCompatibility = ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT;
924
925 layer2State.frameRate = (20_Hz).getValue();
926 layer2State.frameRateCompatibility = ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT;
927
928 mScheduler->updateAttachedChoreographers(parentHierarchy, 120_Hz);
929
930 ASSERT_EQ(1u, mScheduler->mutableAttachedChoreographers().count(parent->getSequence()));
931
932 EXPECT_EQ(60_Hz, mScheduler->mutableAttachedChoreographers()[parent->getSequence()].frameRate);
933}
934
935TEST_F(AttachedChoreographerTest, setsFrameRateParentConflictingChildren) {
936 const sp<MockLayer> layer1 = sp<MockLayer>::make(mFlinger.flinger());
937 const sp<MockLayer> layer2 = sp<MockLayer>::make(mFlinger.flinger());
938 const sp<MockLayer> parent = sp<MockLayer>::make(mFlinger.flinger());
939
940 EXPECT_CALL(mSchedulerCallback, onChoreographerAttached);
941 sp<IDisplayEventConnection> connection =
Dominik Laskowski4babfc42024-02-16 12:28:40 -0500942 mScheduler->createDisplayEventConnection(Cycle::Render, {}, parent->getHandle());
Ady Abraham822ecbd2023-07-07 16:16:09 -0700943
944 RequestedLayerState parentState(LayerCreationArgs(parent->getSequence()));
945 LayerHierarchy parentHierarchy(&parentState);
946
947 RequestedLayerState layer1State(LayerCreationArgs(layer1->getSequence()));
948 LayerHierarchy layer1Hierarchy(&layer1State);
949 parentHierarchy.mChildren.push_back(
950 std::make_pair(&layer1Hierarchy, LayerHierarchy::Variant::Attached));
951
952 RequestedLayerState layer2State(LayerCreationArgs(layer1->getSequence()));
953 LayerHierarchy layer2Hierarchy(&layer2State);
954 parentHierarchy.mChildren.push_back(
955 std::make_pair(&layer2Hierarchy, LayerHierarchy::Variant::Attached));
956
957 layer1State.frameRate = (30_Hz).getValue();
958 layer1State.frameRateCompatibility = ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT;
959
960 layer2State.frameRate = (25_Hz).getValue();
961 layer2State.frameRateCompatibility = ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT;
962
963 mScheduler->updateAttachedChoreographers(parentHierarchy, 120_Hz);
964
965 ASSERT_EQ(1u, mScheduler->mutableAttachedChoreographers().count(parent->getSequence()));
966
967 EXPECT_EQ(Fps(), mScheduler->mutableAttachedChoreographers()[parent->getSequence()].frameRate);
968}
969
970TEST_F(AttachedChoreographerTest, setsFrameRateChild) {
971 const sp<MockLayer> layer = sp<MockLayer>::make(mFlinger.flinger());
972 const sp<MockLayer> parent = sp<MockLayer>::make(mFlinger.flinger());
973
974 EXPECT_CALL(mSchedulerCallback, onChoreographerAttached);
975 sp<IDisplayEventConnection> connection =
Dominik Laskowski4babfc42024-02-16 12:28:40 -0500976 mScheduler->createDisplayEventConnection(Cycle::Render, {}, layer->getHandle());
Ady Abraham822ecbd2023-07-07 16:16:09 -0700977
978 RequestedLayerState parentState(LayerCreationArgs(parent->getSequence()));
979 LayerHierarchy parentHierarchy(&parentState);
980
981 RequestedLayerState layerState(LayerCreationArgs(layer->getSequence()));
982 LayerHierarchy hierarchy(&layerState);
983 parentHierarchy.mChildren.push_back(
984 std::make_pair(&hierarchy, LayerHierarchy::Variant::Attached));
985
986 parentState.frameRate = (30_Hz).getValue();
987 parentState.frameRateCompatibility = ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT;
988
989 mScheduler->updateAttachedChoreographers(parentHierarchy, 120_Hz);
990
991 ASSERT_EQ(1u, mScheduler->mutableAttachedChoreographers().count(layer->getSequence()));
992
993 EXPECT_EQ(30_Hz, mScheduler->mutableAttachedChoreographers()[layer->getSequence()].frameRate);
994}
995
996TEST_F(AttachedChoreographerTest, setsFrameRateChildNotOverriddenByParent) {
997 const sp<MockLayer> layer = sp<MockLayer>::make(mFlinger.flinger());
998 const sp<MockLayer> parent = sp<MockLayer>::make(mFlinger.flinger());
999
1000 EXPECT_CALL(mSchedulerCallback, onChoreographerAttached);
1001 sp<IDisplayEventConnection> connection =
Dominik Laskowski4babfc42024-02-16 12:28:40 -05001002 mScheduler->createDisplayEventConnection(Cycle::Render, {}, layer->getHandle());
Ady Abraham822ecbd2023-07-07 16:16:09 -07001003
1004 RequestedLayerState parentState(LayerCreationArgs(parent->getSequence()));
1005 LayerHierarchy parentHierarchy(&parentState);
1006
1007 RequestedLayerState layerState(LayerCreationArgs(layer->getSequence()));
1008 LayerHierarchy hierarchy(&layerState);
1009 parentHierarchy.mChildren.push_back(
1010 std::make_pair(&hierarchy, LayerHierarchy::Variant::Attached));
1011
1012 parentState.frameRate = (30_Hz).getValue();
1013 parentState.frameRateCompatibility = ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT;
1014
1015 layerState.frameRate = (60_Hz).getValue();
1016 layerState.frameRateCompatibility = ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT;
1017
1018 mScheduler->updateAttachedChoreographers(parentHierarchy, 120_Hz);
1019
1020 ASSERT_EQ(1u, mScheduler->mutableAttachedChoreographers().count(layer->getSequence()));
1021
1022 EXPECT_EQ(60_Hz, mScheduler->mutableAttachedChoreographers()[layer->getSequence()].frameRate);
1023}
1024
Dominik Laskowski068173d2021-08-11 17:22:59 -07001025} // namespace android::scheduler