blob: e6f46655fc55cfd5f27f0f014429c37f9bb425a3 [file] [log] [blame]
Ana Krulec98b5b242018-08-10 15:03:23 -07001/*
2 * Copyright 2018 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
Dominik Laskowski98041832019-08-01 18:35:59 -070017#undef LOG_TAG
18#define LOG_TAG "Scheduler"
Ana Krulec7ab56032018-11-02 20:51:06 +010019#define ATRACE_TAG ATRACE_TAG_GRAPHICS
20
Ana Krulec98b5b242018-08-10 15:03:23 -070021#include "Scheduler.h"
22
Dominik Laskowski8b01cc02020-07-14 19:02:41 -070023#include <android-base/properties.h>
Dominik Laskowski49cea512019-11-12 14:13:23 -080024#include <android-base/stringprintf.h>
Ana Krulece588e312018-09-18 12:32:24 -070025#include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h>
26#include <android/hardware/configstore/1.1/ISurfaceFlingerConfigs.h>
Ana Krulece588e312018-09-18 12:32:24 -070027#include <configstore/Utils.h>
Dominik Laskowski03cfce82022-11-02 12:13:29 -040028#include <ftl/enum.h>
ramindania556d072022-06-14 23:25:11 +000029#include <ftl/fake_guard.h>
Dominik Laskowski01602522022-10-07 19:02:28 -040030#include <ftl/small_map.h>
chaviw3277faf2021-05-19 16:45:23 -050031#include <gui/WindowInfo.h>
Ana Krulecfefd6ae2019-02-13 17:53:08 -080032#include <system/window.h>
Ana Krulec3084c052018-11-21 20:27:17 +010033#include <utils/Timers.h>
Ana Krulec7ab56032018-11-02 20:51:06 +010034#include <utils/Trace.h>
Ana Krulec98b5b242018-08-10 15:03:23 -070035
Adithya Srinivasan5f683cf2020-09-15 14:21:04 -070036#include <FrameTimeline/FrameTimeline.h>
Dominik Laskowski63f12792023-01-21 16:58:22 -050037#include <scheduler/interface/ICompositor.h>
38
Dominik Laskowskif7a09ed2019-10-07 13:54:18 -070039#include <algorithm>
40#include <cinttypes>
41#include <cstdint>
42#include <functional>
43#include <memory>
44#include <numeric>
45
46#include "../Layer.h"
Dominik Laskowski01602522022-10-07 19:02:28 -040047#include "Display/DisplayMap.h"
Ana Krulec98b5b242018-08-10 15:03:23 -070048#include "EventThread.h"
Andy Yu2ae6b6b2021-11-18 14:51:06 -080049#include "FrameRateOverrideMappings.h"
Ana Krulecf2c006d2019-06-21 15:37:07 -070050#include "OneShotTimer.h"
Sundong Ahnd5e08f62018-12-12 20:27:28 +090051#include "SurfaceFlingerProperties.h"
Kevin DuBois00287382019-11-19 15:11:55 -080052#include "VSyncPredictor.h"
53#include "VSyncReactor.h"
Ana Krulec98b5b242018-08-10 15:03:23 -070054
Dominik Laskowski98041832019-08-01 18:35:59 -070055#define RETURN_IF_INVALID_HANDLE(handle, ...) \
56 do { \
57 if (mConnections.count(handle) == 0) { \
58 ALOGE("Invalid connection handle %" PRIuPTR, handle.id); \
59 return __VA_ARGS__; \
60 } \
61 } while (false)
62
Dominik Laskowski068173d2021-08-11 17:22:59 -070063namespace android::scheduler {
Dominik Laskowski8b01cc02020-07-14 19:02:41 -070064
Dominik Laskowski1c99a002023-01-20 17:10:36 -050065Scheduler::Scheduler(ICompositor& compositor, ISchedulerCallback& callback, FeatureFlags features,
66 sp<VsyncModulator> modulatorPtr)
67 : impl::MessageQueue(compositor),
68 mFeatures(features),
69 mVsyncModulator(std::move(modulatorPtr)),
70 mSchedulerCallback(callback) {}
Dominik Laskowski8b01cc02020-07-14 19:02:41 -070071
Dominik Laskowski83bd7712022-01-07 14:30:53 -080072Scheduler::~Scheduler() {
Ady Abraham011f8ba2022-11-22 15:09:07 -080073 // MessageQueue depends on VsyncSchedule, so first destroy it.
74 // Otherwise, MessageQueue will get destroyed after Scheduler's dtor,
75 // which will cause a use-after-free issue.
76 Impl::destroyVsync();
77
Dominik Laskowski83bd7712022-01-07 14:30:53 -080078 // Stop timers and wait for their threads to exit.
79 mDisplayPowerTimer.reset();
80 mTouchTimer.reset();
81
Dominik Laskowskid82e0f02022-10-26 15:23:04 -040082 // Stop idle timer and clear callbacks, as the RefreshRateSelector may outlive the Scheduler.
Dominik Laskowski596a2562022-10-28 11:26:12 -040083 demoteLeaderDisplay();
Dominik Laskowski83bd7712022-01-07 14:30:53 -080084}
85
Dominik Laskowski9c93d602021-10-07 19:38:26 -070086void Scheduler::startTimers() {
Dominik Laskowski98041832019-08-01 18:35:59 -070087 using namespace sysprop;
Dominik Laskowski068173d2021-08-11 17:22:59 -070088 using namespace std::string_literals;
Ady Abraham8532d012019-05-08 14:50:56 -070089
Dominik Laskowski98041832019-08-01 18:35:59 -070090 if (const int64_t millis = set_touch_timer_ms(0); millis > 0) {
Ady Abraham8532d012019-05-08 14:50:56 -070091 // Touch events are coming to SF every 100ms, so the timer needs to be higher than that
Dominik Laskowski98041832019-08-01 18:35:59 -070092 mTouchTimer.emplace(
Ady Abrahamdb3dfee2020-11-17 17:07:12 -080093 "TouchTimer", std::chrono::milliseconds(millis),
Dominik Laskowskidd252cd2019-07-26 09:10:16 -070094 [this] { touchTimerCallback(TimerState::Reset); },
95 [this] { touchTimerCallback(TimerState::Expired); });
Ady Abraham8532d012019-05-08 14:50:56 -070096 mTouchTimer->start();
97 }
Ady Abraham6fe2c172019-07-12 12:37:57 -070098
Dominik Laskowski98041832019-08-01 18:35:59 -070099 if (const int64_t millis = set_display_power_timer_ms(0); millis > 0) {
100 mDisplayPowerTimer.emplace(
Ady Abrahamdb3dfee2020-11-17 17:07:12 -0800101 "DisplayPowerTimer", std::chrono::milliseconds(millis),
Dominik Laskowskidd252cd2019-07-26 09:10:16 -0700102 [this] { displayPowerTimerCallback(TimerState::Reset); },
103 [this] { displayPowerTimerCallback(TimerState::Expired); });
Ady Abraham6fe2c172019-07-12 12:37:57 -0700104 mDisplayPowerTimer->start();
105 }
Ana Krulece588e312018-09-18 12:32:24 -0700106}
107
Dominik Laskowski596a2562022-10-28 11:26:12 -0400108void Scheduler::setLeaderDisplay(std::optional<PhysicalDisplayId> leaderIdOpt) {
109 demoteLeaderDisplay();
Dominik Laskowski59db9562022-10-27 16:18:53 -0400110
Dominik Laskowski596a2562022-10-28 11:26:12 -0400111 std::scoped_lock lock(mDisplayLock);
112 promoteLeaderDisplay(leaderIdOpt);
Lloyd Pique1f9f1a42019-01-31 13:04:00 -0800113}
Ana Krulec0c8cd522018-08-31 12:27:28 -0700114
Dominik Laskowskib5a094b2022-10-27 12:00:12 -0400115void Scheduler::registerDisplay(PhysicalDisplayId displayId, RefreshRateSelectorPtr selectorPtr) {
Leon Scroggins III31d41412022-11-18 16:42:53 -0500116 registerDisplayInternal(displayId, std::move(selectorPtr),
117 std::make_shared<VsyncSchedule>(displayId, mFeatures));
118}
119
120void Scheduler::registerDisplayInternal(PhysicalDisplayId displayId,
121 RefreshRateSelectorPtr selectorPtr,
122 std::shared_ptr<VsyncSchedule> vsyncSchedule) {
Dominik Laskowski596a2562022-10-28 11:26:12 -0400123 demoteLeaderDisplay();
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400124
Dominik Laskowski596a2562022-10-28 11:26:12 -0400125 std::scoped_lock lock(mDisplayLock);
Dominik Laskowskib5a094b2022-10-27 12:00:12 -0400126 mRefreshRateSelectors.emplace_or_replace(displayId, std::move(selectorPtr));
Leon Scroggins III31d41412022-11-18 16:42:53 -0500127 mVsyncSchedules.emplace_or_replace(displayId, std::move(vsyncSchedule));
Dominik Laskowski596a2562022-10-28 11:26:12 -0400128
129 promoteLeaderDisplay();
Dominik Laskowski01602522022-10-07 19:02:28 -0400130}
131
132void Scheduler::unregisterDisplay(PhysicalDisplayId displayId) {
Dominik Laskowski596a2562022-10-28 11:26:12 -0400133 demoteLeaderDisplay();
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400134
Dominik Laskowski596a2562022-10-28 11:26:12 -0400135 std::scoped_lock lock(mDisplayLock);
Dominik Laskowskib5a094b2022-10-27 12:00:12 -0400136 mRefreshRateSelectors.erase(displayId);
Leon Scroggins III31d41412022-11-18 16:42:53 -0500137 mVsyncSchedules.erase(displayId);
Dominik Laskowski596a2562022-10-28 11:26:12 -0400138
Leon Scroggins IIIda21f422023-01-30 20:17:56 -0500139 // Do not allow removing the final display. Code in the scheduler expects
140 // there to be at least one display. (This may be relaxed in the future with
141 // headless virtual display.)
142 LOG_ALWAYS_FATAL_IF(mRefreshRateSelectors.empty(), "Cannot unregister all displays!");
143
Dominik Laskowski596a2562022-10-28 11:26:12 -0400144 promoteLeaderDisplay();
Dominik Laskowski01602522022-10-07 19:02:28 -0400145}
146
Dominik Laskowski756b7892021-08-04 12:53:59 -0700147void Scheduler::run() {
148 while (true) {
149 waitMessage();
150 }
151}
152
Dominik Laskowski08fbd852022-07-14 08:53:42 -0700153void Scheduler::onFrameSignal(ICompositor& compositor, VsyncId vsyncId,
154 TimePoint expectedVsyncTime) {
155 const TimePoint frameTime = SchedulerClock::now();
156
157 if (!compositor.commit(frameTime, vsyncId, expectedVsyncTime)) {
158 return;
159 }
160
161 compositor.composite(frameTime, vsyncId);
162 compositor.sample();
163}
164
Leon Scroggins III31d41412022-11-18 16:42:53 -0500165std::optional<Fps> Scheduler::getFrameRateOverride(uid_t uid) const {
166 std::scoped_lock lock(mDisplayLock);
167 return getFrameRateOverrideLocked(uid);
Dominik Laskowski983f2b52020-06-25 16:54:06 -0700168}
169
Leon Scroggins III31d41412022-11-18 16:42:53 -0500170std::optional<Fps> Scheduler::getFrameRateOverrideLocked(uid_t uid) const {
Andy Yu2ae6b6b2021-11-18 14:51:06 -0800171 const bool supportsFrameRateOverrideByContent =
Leon Scroggins III31d41412022-11-18 16:42:53 -0500172 leaderSelectorPtrLocked()->supportsAppFrameRateOverrideByContent();
Andy Yu2ae6b6b2021-11-18 14:51:06 -0800173 return mFrameRateOverrideMappings
174 .getFrameRateOverrideForUid(uid, supportsFrameRateOverrideByContent);
Ady Abraham62a0be22020-12-08 16:54:10 -0800175}
176
Leon Scroggins III31d41412022-11-18 16:42:53 -0500177bool Scheduler::isVsyncTargetForUid(TimePoint expectedVsyncTime, uid_t uid) const {
Ady Abraham62a0be22020-12-08 16:54:10 -0800178 const auto frameRate = getFrameRateOverride(uid);
179 if (!frameRate.has_value()) {
180 return true;
181 }
182
Leon Scroggins III31d41412022-11-18 16:42:53 -0500183 return isVsyncInPhase(expectedVsyncTime, *frameRate);
Ady Abraham0bb6a472020-10-12 10:22:13 -0700184}
185
Leon Scroggins III31d41412022-11-18 16:42:53 -0500186bool Scheduler::isVsyncInPhase(TimePoint expectedVsyncTime, Fps frameRate) const {
187 return getVsyncSchedule()->getTracker().isVSyncInPhase(expectedVsyncTime.ns(), frameRate);
Huihong Luo1768cb02022-10-11 11:10:34 -0700188}
189
Leon Scroggins III31d41412022-11-18 16:42:53 -0500190Fps Scheduler::getLeaderRenderFrameRate(uid_t uid) const {
191 std::scoped_lock lock(mDisplayLock);
192 ftl::FakeGuard guard(kMainThreadContext);
193 auto vsyncSchedule = getVsyncScheduleLocked();
Ady Abraham64c2fc02020-12-29 12:07:50 -0800194
Leon Scroggins III31d41412022-11-18 16:42:53 -0500195 const Fps refreshRate = leaderSelectorPtrLocked()->getActiveMode().fps;
196 const nsecs_t currentPeriod = vsyncSchedule->period().ns() ?: refreshRate.getPeriodNsecs();
Dominik Laskowskib0054a22022-03-03 09:03:06 -0800197
Leon Scroggins III31d41412022-11-18 16:42:53 -0500198 const auto frameRate = getFrameRateOverrideLocked(uid);
199 if (!frameRate.has_value()) {
200 return Fps::fromPeriodNsecs(currentPeriod);
201 }
Jorim Jaggic0086af2021-02-12 18:18:11 +0100202
Leon Scroggins III31d41412022-11-18 16:42:53 -0500203 const auto divisor = RefreshRateSelector::getFrameRateDivisor(refreshRate, *frameRate);
204 if (divisor <= 1) {
205 return Fps::fromPeriodNsecs(currentPeriod);
206 }
207 return Fps::fromPeriodNsecs(currentPeriod * divisor);
Jorim Jaggic0086af2021-02-12 18:18:11 +0100208}
209
Dominik Laskowski1c99a002023-01-20 17:10:36 -0500210ConnectionHandle Scheduler::createEventThread(Cycle cycle,
211 frametimeline::TokenManager* tokenManager,
212 std::chrono::nanoseconds workDuration,
213 std::chrono::nanoseconds readyDuration) {
214 auto eventThread = std::make_unique<impl::EventThread>(cycle == Cycle::Render ? "app" : "appSf",
Leon Scroggins III31d41412022-11-18 16:42:53 -0500215 getVsyncSchedule(), *this, tokenManager,
Dominik Laskowski1c99a002023-01-20 17:10:36 -0500216 workDuration, readyDuration);
217
218 auto& handle = cycle == Cycle::Render ? mAppConnectionHandle : mSfConnectionHandle;
219 handle = createConnection(std::move(eventThread));
220 return handle;
Dominik Laskowski98041832019-08-01 18:35:59 -0700221}
Ana Krulec98b5b242018-08-10 15:03:23 -0700222
Dominik Laskowski068173d2021-08-11 17:22:59 -0700223ConnectionHandle Scheduler::createConnection(std::unique_ptr<EventThread> eventThread) {
Dominik Laskowski98041832019-08-01 18:35:59 -0700224 const ConnectionHandle handle = ConnectionHandle{mNextConnectionHandleId++};
225 ALOGV("Creating a connection handle with ID %" PRIuPTR, handle.id);
Dominik Laskowskif654d572018-12-20 11:03:06 -0800226
Ady Abraham62f216c2020-10-13 19:07:23 -0700227 auto connection = createConnectionInternal(eventThread.get());
Dominik Laskowski98041832019-08-01 18:35:59 -0700228
Ana Krulec6ddd2612020-09-24 13:06:33 -0700229 std::lock_guard<std::mutex> lock(mConnectionsLock);
Dominik Laskowski98041832019-08-01 18:35:59 -0700230 mConnections.emplace(handle, Connection{connection, std::move(eventThread)});
231 return handle;
Ana Krulec98b5b242018-08-10 15:03:23 -0700232}
233
Ady Abraham0f4a1b12019-06-04 16:04:04 -0700234sp<EventThreadConnection> Scheduler::createConnectionInternal(
Huihong Luo1b0c49f2022-03-15 19:18:21 -0700235 EventThread* eventThread, EventRegistrationFlags eventRegistration) {
Ady Abraham62f216c2020-10-13 19:07:23 -0700236 return eventThread->createEventConnection([&] { resync(); }, eventRegistration);
Ana Krulec0c8cd522018-08-31 12:27:28 -0700237}
238
Ana Krulec98b5b242018-08-10 15:03:23 -0700239sp<IDisplayEventConnection> Scheduler::createDisplayEventConnection(
Huihong Luo1b0c49f2022-03-15 19:18:21 -0700240 ConnectionHandle handle, EventRegistrationFlags eventRegistration) {
Ana Krulec6ddd2612020-09-24 13:06:33 -0700241 std::lock_guard<std::mutex> lock(mConnectionsLock);
Dominik Laskowski98041832019-08-01 18:35:59 -0700242 RETURN_IF_INVALID_HANDLE(handle, nullptr);
Ady Abraham62f216c2020-10-13 19:07:23 -0700243 return createConnectionInternal(mConnections[handle].thread.get(), eventRegistration);
Ana Krulec98b5b242018-08-10 15:03:23 -0700244}
245
Dominik Laskowski98041832019-08-01 18:35:59 -0700246sp<EventThreadConnection> Scheduler::getEventConnection(ConnectionHandle handle) {
Ana Krulec6ddd2612020-09-24 13:06:33 -0700247 std::lock_guard<std::mutex> lock(mConnectionsLock);
Dominik Laskowski98041832019-08-01 18:35:59 -0700248 RETURN_IF_INVALID_HANDLE(handle, nullptr);
249 return mConnections[handle].connection;
Ana Krulec98b5b242018-08-10 15:03:23 -0700250}
251
Dominik Laskowski98041832019-08-01 18:35:59 -0700252void Scheduler::onHotplugReceived(ConnectionHandle handle, PhysicalDisplayId displayId,
253 bool connected) {
Ana Krulec6ddd2612020-09-24 13:06:33 -0700254 android::EventThread* thread;
255 {
256 std::lock_guard<std::mutex> lock(mConnectionsLock);
257 RETURN_IF_INVALID_HANDLE(handle);
258 thread = mConnections[handle].thread.get();
259 }
260
261 thread->onHotplugReceived(displayId, connected);
Ana Krulec98b5b242018-08-10 15:03:23 -0700262}
263
Dominik Laskowski98041832019-08-01 18:35:59 -0700264void Scheduler::onScreenAcquired(ConnectionHandle handle) {
Ana Krulec6ddd2612020-09-24 13:06:33 -0700265 android::EventThread* thread;
266 {
267 std::lock_guard<std::mutex> lock(mConnectionsLock);
268 RETURN_IF_INVALID_HANDLE(handle);
269 thread = mConnections[handle].thread.get();
270 }
271 thread->onScreenAcquired();
Ana Krulec98b5b242018-08-10 15:03:23 -0700272}
273
Dominik Laskowski98041832019-08-01 18:35:59 -0700274void Scheduler::onScreenReleased(ConnectionHandle handle) {
Ana Krulec6ddd2612020-09-24 13:06:33 -0700275 android::EventThread* thread;
276 {
277 std::lock_guard<std::mutex> lock(mConnectionsLock);
278 RETURN_IF_INVALID_HANDLE(handle);
279 thread = mConnections[handle].thread.get();
280 }
281 thread->onScreenReleased();
Ana Krulec98b5b242018-08-10 15:03:23 -0700282}
283
Ady Abraham62a0be22020-12-08 16:54:10 -0800284void Scheduler::onFrameRateOverridesChanged(ConnectionHandle handle, PhysicalDisplayId displayId) {
Andy Yud6a36202022-01-26 04:08:22 -0800285 const bool supportsFrameRateOverrideByContent =
Ady Abraham68636062022-11-16 17:07:25 -0800286 leaderSelectorPtr()->supportsAppFrameRateOverrideByContent();
Andy Yud6a36202022-01-26 04:08:22 -0800287
Andy Yu2ae6b6b2021-11-18 14:51:06 -0800288 std::vector<FrameRateOverride> overrides =
Andy Yud6a36202022-01-26 04:08:22 -0800289 mFrameRateOverrideMappings.getAllFrameRateOverrides(supportsFrameRateOverrideByContent);
Andy Yu2ae6b6b2021-11-18 14:51:06 -0800290
Ady Abraham62f216c2020-10-13 19:07:23 -0700291 android::EventThread* thread;
292 {
Ady Abraham62a0be22020-12-08 16:54:10 -0800293 std::lock_guard lock(mConnectionsLock);
Ady Abraham62f216c2020-10-13 19:07:23 -0700294 RETURN_IF_INVALID_HANDLE(handle);
295 thread = mConnections[handle].thread.get();
296 }
297 thread->onFrameRateOverridesChanged(displayId, std::move(overrides));
298}
299
Ady Abrahamace3d052022-11-17 16:25:05 -0800300void Scheduler::onPrimaryDisplayModeChanged(ConnectionHandle handle, const FrameRateMode& mode) {
Ady Abraham62a0be22020-12-08 16:54:10 -0800301 {
Dominik Laskowski068173d2021-08-11 17:22:59 -0700302 std::lock_guard<std::mutex> lock(mPolicyLock);
Marin Shalamanova7fe3042021-01-29 21:02:08 +0100303 // Cache the last reported modes for primary display.
Dominik Laskowski068173d2021-08-11 17:22:59 -0700304 mPolicy.cachedModeChangedParams = {handle, mode};
Ady Abraham5cc2e262021-03-25 13:09:17 -0700305
306 // Invalidate content based refresh rate selection so it could be calculated
307 // again for the new refresh rate.
Dominik Laskowski068173d2021-08-11 17:22:59 -0700308 mPolicy.contentRequirements.clear();
Ady Abraham62a0be22020-12-08 16:54:10 -0800309 }
Ady Abraham690f4612021-07-01 23:24:03 -0700310 onNonPrimaryDisplayModeChanged(handle, mode);
Ady Abrahamdfd62162020-06-10 16:11:56 -0700311}
312
Marin Shalamanova7fe3042021-01-29 21:02:08 +0100313void Scheduler::dispatchCachedReportedMode() {
Ana Krulec6ddd2612020-09-24 13:06:33 -0700314 // Check optional fields first.
Ady Abrahamace3d052022-11-17 16:25:05 -0800315 if (!mPolicy.modeOpt) {
Marin Shalamanova7fe3042021-01-29 21:02:08 +0100316 ALOGW("No mode ID found, not dispatching cached mode.");
Ana Krulec6ddd2612020-09-24 13:06:33 -0700317 return;
318 }
Dominik Laskowski068173d2021-08-11 17:22:59 -0700319 if (!mPolicy.cachedModeChangedParams) {
Marin Shalamanova7fe3042021-01-29 21:02:08 +0100320 ALOGW("No mode changed params found, not dispatching cached mode.");
Ana Krulec6ddd2612020-09-24 13:06:33 -0700321 return;
322 }
323
Ady Abrahamd1591702021-07-27 16:27:56 -0700324 // If the mode is not the current mode, this means that a
325 // mode change is in progress. In that case we shouldn't dispatch an event
326 // as it will be dispatched when the current mode changes.
Ady Abrahamace3d052022-11-17 16:25:05 -0800327 if (leaderSelectorPtr()->getActiveMode() != mPolicy.modeOpt) {
Ady Abrahamd1591702021-07-27 16:27:56 -0700328 return;
329 }
330
Marin Shalamanova7fe3042021-01-29 21:02:08 +0100331 // If there is no change from cached mode, there is no need to dispatch an event
Ady Abrahamace3d052022-11-17 16:25:05 -0800332 if (*mPolicy.modeOpt == mPolicy.cachedModeChangedParams->mode) {
Ady Abrahamdfd62162020-06-10 16:11:56 -0700333 return;
334 }
335
Ady Abrahamace3d052022-11-17 16:25:05 -0800336 mPolicy.cachedModeChangedParams->mode = *mPolicy.modeOpt;
Dominik Laskowski068173d2021-08-11 17:22:59 -0700337 onNonPrimaryDisplayModeChanged(mPolicy.cachedModeChangedParams->handle,
338 mPolicy.cachedModeChangedParams->mode);
Ady Abrahamdfd62162020-06-10 16:11:56 -0700339}
340
Ady Abrahamace3d052022-11-17 16:25:05 -0800341void Scheduler::onNonPrimaryDisplayModeChanged(ConnectionHandle handle, const FrameRateMode& mode) {
Ana Krulec6ddd2612020-09-24 13:06:33 -0700342 android::EventThread* thread;
343 {
344 std::lock_guard<std::mutex> lock(mConnectionsLock);
345 RETURN_IF_INVALID_HANDLE(handle);
346 thread = mConnections[handle].thread.get();
347 }
Ady Abraham67434eb2022-12-01 17:48:12 -0800348 thread->onModeChanged(mode);
Ady Abraham447052e2019-02-13 16:07:27 -0800349}
350
Alec Mouri717bcb62020-02-10 17:07:19 -0800351size_t Scheduler::getEventThreadConnectionCount(ConnectionHandle handle) {
Ana Krulec6ddd2612020-09-24 13:06:33 -0700352 std::lock_guard<std::mutex> lock(mConnectionsLock);
Alec Mouri717bcb62020-02-10 17:07:19 -0800353 RETURN_IF_INVALID_HANDLE(handle, 0);
354 return mConnections[handle].thread->getEventThreadConnectionCount();
355}
356
Dominik Laskowski98041832019-08-01 18:35:59 -0700357void Scheduler::dump(ConnectionHandle handle, std::string& result) const {
Ana Krulec6ddd2612020-09-24 13:06:33 -0700358 android::EventThread* thread;
359 {
360 std::lock_guard<std::mutex> lock(mConnectionsLock);
361 RETURN_IF_INVALID_HANDLE(handle);
362 thread = mConnections.at(handle).thread.get();
363 }
364 thread->dump(result);
Ana Krulec98b5b242018-08-10 15:03:23 -0700365}
366
Ady Abraham9c53ee72020-07-22 21:16:18 -0700367void Scheduler::setDuration(ConnectionHandle handle, std::chrono::nanoseconds workDuration,
368 std::chrono::nanoseconds readyDuration) {
Ana Krulec6ddd2612020-09-24 13:06:33 -0700369 android::EventThread* thread;
370 {
371 std::lock_guard<std::mutex> lock(mConnectionsLock);
372 RETURN_IF_INVALID_HANDLE(handle);
373 thread = mConnections[handle].thread.get();
374 }
375 thread->setDuration(workDuration, readyDuration);
Ana Krulec98b5b242018-08-10 15:03:23 -0700376}
Ana Krulece588e312018-09-18 12:32:24 -0700377
Dominik Laskowski1c99a002023-01-20 17:10:36 -0500378void Scheduler::setVsyncConfigSet(const VsyncConfigSet& configs, Period vsyncPeriod) {
379 setVsyncConfig(mVsyncModulator->setVsyncConfigSet(configs), vsyncPeriod);
380}
381
382void Scheduler::setVsyncConfig(const VsyncConfig& config, Period vsyncPeriod) {
383 setDuration(mAppConnectionHandle,
384 /* workDuration */ config.appWorkDuration,
385 /* readyDuration */ config.sfWorkDuration);
386 setDuration(mSfConnectionHandle,
387 /* workDuration */ vsyncPeriod,
388 /* readyDuration */ config.sfWorkDuration);
389 setDuration(config.sfWorkDuration);
390}
391
Leon Scroggins III31d41412022-11-18 16:42:53 -0500392void Scheduler::enableHardwareVsync(PhysicalDisplayId id) {
393 auto schedule = getVsyncSchedule(id);
394 schedule->enableHardwareVsync(mSchedulerCallback);
395}
396
397void Scheduler::disableHardwareVsync(PhysicalDisplayId id, bool disallow) {
398 auto schedule = getVsyncSchedule(id);
399 schedule->disableHardwareVsync(mSchedulerCallback, disallow);
400}
401
402void Scheduler::resyncAllToHardwareVsync(bool allowToEnable) {
403 std::scoped_lock lock(mDisplayLock);
404 ftl::FakeGuard guard(kMainThreadContext);
405
406 for (const auto& [id, _] : mRefreshRateSelectors) {
407 resyncToHardwareVsyncLocked(id, allowToEnable);
Ana Krulece588e312018-09-18 12:32:24 -0700408 }
409}
410
Leon Scroggins III31d41412022-11-18 16:42:53 -0500411void Scheduler::resyncToHardwareVsyncLocked(PhysicalDisplayId id, bool allowToEnable,
412 std::optional<Fps> refreshRate) {
413 if (!refreshRate) {
414 auto selectorPtr = mRefreshRateSelectors.get(id);
415 LOG_ALWAYS_FATAL_IF(!selectorPtr);
416 refreshRate = selectorPtr->get()->getActiveMode().modePtr->getFps();
Ana Krulece588e312018-09-18 12:32:24 -0700417 }
Leon Scroggins III31d41412022-11-18 16:42:53 -0500418 auto schedule = getVsyncScheduleLocked(id);
419 if (allowToEnable) {
420 schedule->allowHardwareVsync();
421 } else if (!schedule->isHardwareVsyncAllowed()) {
422 // Hardware vsync is not currently allowed, so abort the resync
423 // attempt for now.
424 return;
Ana Krulece588e312018-09-18 12:32:24 -0700425 }
Leon Scroggins III31d41412022-11-18 16:42:53 -0500426
427 setVsyncPeriod(schedule, refreshRate->getPeriodNsecs(), false /* force */);
Ana Krulece588e312018-09-18 12:32:24 -0700428}
429
Leon Scroggins III31d41412022-11-18 16:42:53 -0500430void Scheduler::setRenderRate(PhysicalDisplayId id, Fps renderFrameRate) {
431 std::scoped_lock lock(mDisplayLock);
432 ftl::FakeGuard guard(kMainThreadContext);
Ana Krulecc2870422019-01-29 19:00:58 -0800433
Leon Scroggins III31d41412022-11-18 16:42:53 -0500434 auto selectorPtr = mRefreshRateSelectors.get(id);
435 LOG_ALWAYS_FATAL_IF(!selectorPtr);
436 const auto mode = selectorPtr->get()->getActiveMode();
Ady Abrahamace3d052022-11-17 16:25:05 -0800437
438 using fps_approx_ops::operator!=;
439 LOG_ALWAYS_FATAL_IF(renderFrameRate != mode.fps,
Leon Scroggins III31d41412022-11-18 16:42:53 -0500440 "Mismatch in render frame rates. Selector: %s, Scheduler: %s, Display: "
441 "%" PRIu64,
442 to_string(mode.fps).c_str(), to_string(renderFrameRate).c_str(), id.value);
Ady Abrahamace3d052022-11-17 16:25:05 -0800443
444 ALOGV("%s %s (%s)", __func__, to_string(mode.fps).c_str(),
445 to_string(mode.modePtr->getFps()).c_str());
446
447 const auto divisor = RefreshRateSelector::getFrameRateDivisor(mode.modePtr->getFps(), mode.fps);
448 LOG_ALWAYS_FATAL_IF(divisor == 0, "%s <> %s -- not divisors", to_string(mode.fps).c_str(),
449 to_string(mode.fps).c_str());
450
Leon Scroggins III31d41412022-11-18 16:42:53 -0500451 getVsyncScheduleLocked(id)->getTracker().setDivisor(static_cast<unsigned>(divisor));
Ady Abrahamace3d052022-11-17 16:25:05 -0800452}
453
Steven Thomas2bbaabe2019-08-28 16:08:35 -0700454void Scheduler::resync() {
Long Ling457bef92019-09-11 14:43:11 -0700455 static constexpr nsecs_t kIgnoreDelay = ms2ns(750);
Ana Krulecc2870422019-01-29 19:00:58 -0800456
457 const nsecs_t now = systemTime();
Steven Thomas2bbaabe2019-08-28 16:08:35 -0700458 const nsecs_t last = mLastResyncTime.exchange(now);
Ana Krulecc2870422019-01-29 19:00:58 -0800459
460 if (now - last > kIgnoreDelay) {
Leon Scroggins III31d41412022-11-18 16:42:53 -0500461 resyncAllToHardwareVsync(false /* allowToEnable */);
Ana Krulecc2870422019-01-29 19:00:58 -0800462 }
463}
464
Leon Scroggins III31d41412022-11-18 16:42:53 -0500465void Scheduler::setVsyncPeriod(const std::shared_ptr<VsyncSchedule>& schedule, nsecs_t period,
466 bool force) {
467 ALOGD("Scheduler::setVsyncPeriod");
Dominik Laskowskib0054a22022-03-03 09:03:06 -0800468 if (period <= 0) return;
469
Leon Scroggins III31d41412022-11-18 16:42:53 -0500470 // TODO (b/266712910):The old code held mHWVsyncLock before calling
471 // startPeriodTransition. Move these into a new method on VsyncSchedule that
472 // encapsulates this behavior there and allows holding the lock the whole
473 // time.
474 schedule->getController().startPeriodTransition(period, force);
475 schedule->enableHardwareVsync(mSchedulerCallback);
Ana Krulece588e312018-09-18 12:32:24 -0700476}
477
Leon Scroggins III31d41412022-11-18 16:42:53 -0500478bool Scheduler::addResyncSample(PhysicalDisplayId id, nsecs_t timestamp,
479 std::optional<nsecs_t> hwcVsyncPeriod) {
480 bool periodFlushed = false;
481 auto schedule = getVsyncSchedule(id);
482 if (schedule->getController().addHwVsyncTimestamp(timestamp, hwcVsyncPeriod, &periodFlushed)) {
483 schedule->enableHardwareVsync(mSchedulerCallback);
484 } else {
485 schedule->disableHardwareVsync(mSchedulerCallback, false /* disallow */);
Ana Krulece588e312018-09-18 12:32:24 -0700486 }
487
Leon Scroggins III31d41412022-11-18 16:42:53 -0500488 return periodFlushed;
Ana Krulece588e312018-09-18 12:32:24 -0700489}
490
Leon Scroggins III31d41412022-11-18 16:42:53 -0500491void Scheduler::addPresentFence(PhysicalDisplayId id, std::shared_ptr<FenceTime> fence) {
492 auto schedule = getVsyncSchedule(id);
493 const bool needMoreSignals = schedule->getController().addPresentFence(std::move(fence));
494 if (needMoreSignals) {
495 schedule->enableHardwareVsync(mSchedulerCallback);
Ana Krulece588e312018-09-18 12:32:24 -0700496 } else {
Leon Scroggins III31d41412022-11-18 16:42:53 -0500497 schedule->disableHardwareVsync(mSchedulerCallback, false /* disallow */);
Ana Krulece588e312018-09-18 12:32:24 -0700498 }
499}
500
Dominik Laskowskif7a09ed2019-10-07 13:54:18 -0700501void Scheduler::registerLayer(Layer* layer) {
Marin Shalamanov4be385e2021-04-23 13:25:30 +0200502 // If the content detection feature is off, we still keep the layer history,
503 // since we use it for other features (like Frame Rate API), so layers
504 // still need to be registered.
Andy Labrada096227e2022-06-15 16:58:11 +0000505 mLayerHistory.registerLayer(layer, mFeatures.test(Feature::kContentDetection));
Ady Abraham09bd3922019-04-08 10:44:56 -0700506}
507
Ady Abrahambdda8f02021-04-01 16:06:11 -0700508void Scheduler::deregisterLayer(Layer* layer) {
Dominik Laskowski9c93d602021-10-07 19:38:26 -0700509 mLayerHistory.deregisterLayer(layer);
Ady Abrahambdda8f02021-04-01 16:06:11 -0700510}
511
Ady Abraham5def7332020-05-29 16:13:47 -0700512void Scheduler::recordLayerHistory(Layer* layer, nsecs_t presentTime,
513 LayerHistory::LayerUpdateType updateType) {
Dominik Laskowski596a2562022-10-28 11:26:12 -0400514 if (leaderSelectorPtr()->canSwitch()) {
515 mLayerHistory.record(layer, presentTime, systemTime(), updateType);
Dominik Laskowski49cea512019-11-12 14:13:23 -0800516 }
Ana Krulec3084c052018-11-21 20:27:17 +0100517}
518
Marin Shalamanova7fe3042021-01-29 21:02:08 +0100519void Scheduler::setModeChangePending(bool pending) {
Dominik Laskowski9c93d602021-10-07 19:38:26 -0700520 mLayerHistory.setModeChangePending(pending);
Ady Abraham32efd542020-05-19 17:49:26 -0700521}
522
Andy Labrada096227e2022-06-15 16:58:11 +0000523void Scheduler::setDefaultFrameRateCompatibility(Layer* layer) {
524 mLayerHistory.setDefaultFrameRateCompatibility(layer,
525 mFeatures.test(Feature::kContentDetection));
526}
527
Dominik Laskowski49cea512019-11-12 14:13:23 -0800528void Scheduler::chooseRefreshRateForContent() {
Dominik Laskowski596a2562022-10-28 11:26:12 -0400529 const auto selectorPtr = leaderSelectorPtr();
Dominik Laskowskid82e0f02022-10-26 15:23:04 -0400530 if (!selectorPtr->canSwitch()) return;
Dominik Laskowski49cea512019-11-12 14:13:23 -0800531
Ady Abraham8a82ba62020-01-17 12:43:17 -0800532 ATRACE_CALL();
533
Dominik Laskowskid82e0f02022-10-26 15:23:04 -0400534 LayerHistory::Summary summary = mLayerHistory.summarize(*selectorPtr, systemTime());
Dominik Laskowski0c41ffa2021-12-24 16:45:12 -0800535 applyPolicy(&Policy::contentRequirements, std::move(summary));
Ady Abrahama1a49af2019-02-07 14:36:55 -0800536}
537
Ana Krulecfb772822018-11-30 10:44:07 +0100538void Scheduler::resetIdleTimer() {
Dominik Laskowski596a2562022-10-28 11:26:12 -0400539 leaderSelectorPtr()->resetIdleTimer();
Ady Abrahama1a49af2019-02-07 14:36:55 -0800540}
541
Dominik Laskowski8da6b0e2021-05-12 15:34:13 -0700542void Scheduler::onTouchHint() {
Dominik Laskowski983f2b52020-06-25 16:54:06 -0700543 if (mTouchTimer) {
Ady Abraham8a82ba62020-01-17 12:43:17 -0800544 mTouchTimer->reset();
Dominik Laskowski596a2562022-10-28 11:26:12 -0400545 leaderSelectorPtr()->resetKernelIdleTimer();
Dominik Laskowski49cea512019-11-12 14:13:23 -0800546 }
Ady Abraham8532d012019-05-08 14:50:56 -0700547}
548
Leon Scroggins III31d41412022-11-18 16:42:53 -0500549void Scheduler::setDisplayPowerMode(PhysicalDisplayId id, hal::PowerMode powerMode) {
550 const bool isLeader = [this, id]() REQUIRES(kMainThreadContext) {
551 ftl::FakeGuard guard(mDisplayLock);
552 return id == mLeaderDisplayId;
553 }();
554 if (isLeader) {
555 // TODO (b/255657128): This needs to be handled per display.
Dominik Laskowski068173d2021-08-11 17:22:59 -0700556 std::lock_guard<std::mutex> lock(mPolicyLock);
Rachel Lee6a9731d2022-06-06 17:08:14 -0700557 mPolicy.displayPowerMode = powerMode;
Ady Abraham6fe2c172019-07-12 12:37:57 -0700558 }
Leon Scroggins III31d41412022-11-18 16:42:53 -0500559 {
560 std::scoped_lock lock(mDisplayLock);
561 auto vsyncSchedule = getVsyncScheduleLocked(id);
562 vsyncSchedule->getController().setDisplayPowerMode(powerMode);
563 }
564 if (!isLeader) return;
Ady Abraham6fe2c172019-07-12 12:37:57 -0700565
566 if (mDisplayPowerTimer) {
567 mDisplayPowerTimer->reset();
568 }
569
570 // Display Power event will boost the refresh rate to performance.
571 // Clear Layer History to get fresh FPS detection
Dominik Laskowski9c93d602021-10-07 19:38:26 -0700572 mLayerHistory.clear();
Ady Abraham6fe2c172019-07-12 12:37:57 -0700573}
574
Leon Scroggins III31d41412022-11-18 16:42:53 -0500575std::shared_ptr<const VsyncSchedule> Scheduler::getVsyncSchedule(
576 std::optional<PhysicalDisplayId> idOpt) const {
577 std::scoped_lock lock(mDisplayLock);
578 return getVsyncScheduleLocked(idOpt);
579}
580
581std::shared_ptr<const VsyncSchedule> Scheduler::getVsyncScheduleLocked(
582 std::optional<PhysicalDisplayId> idOpt) const {
583 ftl::FakeGuard guard(kMainThreadContext);
584 if (!idOpt) {
585 LOG_ALWAYS_FATAL_IF(!mLeaderDisplayId, "Missing a leader!");
586 idOpt = mLeaderDisplayId;
587 }
588 auto scheduleOpt = mVsyncSchedules.get(*idOpt);
589 LOG_ALWAYS_FATAL_IF(!scheduleOpt);
590 return std::const_pointer_cast<const VsyncSchedule>(scheduleOpt->get());
591}
592
Dominik Laskowski3a80a382019-07-25 11:16:07 -0700593void Scheduler::kernelIdleTimerCallback(TimerState state) {
594 ATRACE_INT("ExpiredKernelIdleTimer", static_cast<int>(state));
Ana Krulecfb772822018-11-30 10:44:07 +0100595
Ady Abraham2139f732019-11-13 18:56:40 -0800596 // TODO(145561154): cleanup the kernel idle timer implementation and the refresh rate
597 // magic number
Ady Abrahamace3d052022-11-17 16:25:05 -0800598 const Fps refreshRate = leaderSelectorPtr()->getActiveMode().modePtr->getFps();
Ady Abraham3efa3942021-06-24 19:01:25 -0700599
Dominik Laskowski6eab42d2021-09-13 14:34:13 -0700600 constexpr Fps FPS_THRESHOLD_FOR_KERNEL_TIMER = 65_Hz;
601 using namespace fps_approx_ops;
602
Dominik Laskowskib0054a22022-03-03 09:03:06 -0800603 if (state == TimerState::Reset && refreshRate > FPS_THRESHOLD_FOR_KERNEL_TIMER) {
Alec Mouri7f015182019-07-11 13:56:22 -0700604 // If we're not in performance mode then the kernel timer shouldn't do
605 // anything, as the refresh rate during DPU power collapse will be the
606 // same.
Leon Scroggins III31d41412022-11-18 16:42:53 -0500607 resyncAllToHardwareVsync(true /* allowToEnable */);
Dominik Laskowskib0054a22022-03-03 09:03:06 -0800608 } else if (state == TimerState::Expired && refreshRate <= FPS_THRESHOLD_FOR_KERNEL_TIMER) {
Dominik Laskowski3a80a382019-07-25 11:16:07 -0700609 // Disable HW VSYNC if the timer expired, as we don't need it enabled if
610 // we're not pushing frames, and if we're in PERFORMANCE mode then we'll
Ady Abraham8cb21882020-08-26 18:22:05 -0700611 // need to update the VsyncController model anyway.
Leon Scroggins III31d41412022-11-18 16:42:53 -0500612 std::scoped_lock lock(mDisplayLock);
613 ftl::FakeGuard guard(kMainThreadContext);
614 constexpr bool disallow = false;
615 for (auto& [_, schedule] : mVsyncSchedules) {
616 schedule->disableHardwareVsync(mSchedulerCallback, disallow);
617 }
Alec Mouridc28b372019-04-18 21:17:13 -0700618 }
Ady Abrahama09852a2020-02-20 14:23:42 -0800619
620 mSchedulerCallback.kernelTimerChanged(state == TimerState::Expired);
Alec Mouridc28b372019-04-18 21:17:13 -0700621}
622
Dominik Laskowski3a80a382019-07-25 11:16:07 -0700623void Scheduler::idleTimerCallback(TimerState state) {
Dominik Laskowski0c41ffa2021-12-24 16:45:12 -0800624 applyPolicy(&Policy::idleTimer, state);
Dominik Laskowski3a80a382019-07-25 11:16:07 -0700625 ATRACE_INT("ExpiredIdleTimer", static_cast<int>(state));
Ana Krulecfb772822018-11-30 10:44:07 +0100626}
627
Dominik Laskowski3a80a382019-07-25 11:16:07 -0700628void Scheduler::touchTimerCallback(TimerState state) {
Dominik Laskowskidd252cd2019-07-26 09:10:16 -0700629 const TouchState touch = state == TimerState::Reset ? TouchState::Active : TouchState::Inactive;
Dominik Laskowski983f2b52020-06-25 16:54:06 -0700630 // Touch event will boost the refresh rate to performance.
631 // Clear layer history to get fresh FPS detection.
632 // NOTE: Instead of checking all the layers, we should be checking the layer
633 // that is currently on top. b/142507166 will give us this capability.
Dominik Laskowski0c41ffa2021-12-24 16:45:12 -0800634 if (applyPolicy(&Policy::touch, touch).touch) {
Dominik Laskowski9c93d602021-10-07 19:38:26 -0700635 mLayerHistory.clear();
Ady Abraham1adbb722020-05-15 11:51:48 -0700636 }
Dominik Laskowski3a80a382019-07-25 11:16:07 -0700637 ATRACE_INT("TouchState", static_cast<int>(touch));
Ady Abraham8532d012019-05-08 14:50:56 -0700638}
639
Dominik Laskowski3a80a382019-07-25 11:16:07 -0700640void Scheduler::displayPowerTimerCallback(TimerState state) {
Dominik Laskowski0c41ffa2021-12-24 16:45:12 -0800641 applyPolicy(&Policy::displayPowerTimer, state);
Dominik Laskowski3a80a382019-07-25 11:16:07 -0700642 ATRACE_INT("ExpiredDisplayPowerTimer", static_cast<int>(state));
Alec Mouridc28b372019-04-18 21:17:13 -0700643}
644
Dominik Laskowski03cfce82022-11-02 12:13:29 -0400645void Scheduler::dump(utils::Dumper& dumper) const {
646 using namespace std::string_view_literals;
Ady Abraham4f960d12021-10-13 16:59:49 -0700647
648 {
Dominik Laskowski03cfce82022-11-02 12:13:29 -0400649 utils::Dumper::Section section(dumper, "Features"sv);
650
651 for (Feature feature : ftl::enum_range<Feature>()) {
652 if (const auto flagOpt = ftl::flag_name(feature)) {
653 dumper.dump(flagOpt->substr(1), mFeatures.test(feature));
654 }
655 }
656 }
657 {
658 utils::Dumper::Section section(dumper, "Policy"sv);
Dominik Laskowski596a2562022-10-28 11:26:12 -0400659 {
660 std::scoped_lock lock(mDisplayLock);
661 ftl::FakeGuard guard(kMainThreadContext);
662 dumper.dump("leaderDisplayId"sv, mLeaderDisplayId);
663 }
Dominik Laskowski03cfce82022-11-02 12:13:29 -0400664 dumper.dump("layerHistory"sv, mLayerHistory.dump());
665 dumper.dump("touchTimer"sv, mTouchTimer.transform(&OneShotTimer::interval));
666 dumper.dump("displayPowerTimer"sv, mDisplayPowerTimer.transform(&OneShotTimer::interval));
667 }
668
669 mFrameRateOverrideMappings.dump(dumper);
670 dumper.eol();
Ana Krulecb43429d2019-01-09 14:28:51 -0800671}
672
Dominik Laskowski068173d2021-08-11 17:22:59 -0700673void Scheduler::dumpVsync(std::string& out) const {
Leon Scroggins III31d41412022-11-18 16:42:53 -0500674 std::scoped_lock lock(mDisplayLock);
675 ftl::FakeGuard guard(kMainThreadContext);
676 if (mLeaderDisplayId) {
677 base::StringAppendF(&out, "VsyncSchedule for leader %s:\n",
678 to_string(*mLeaderDisplayId).c_str());
679 getVsyncScheduleLocked()->dump(out);
680 }
681 for (auto& [id, vsyncSchedule] : mVsyncSchedules) {
682 if (id == mLeaderDisplayId) {
683 continue;
684 }
685 base::StringAppendF(&out, "VsyncSchedule for follower %s:\n", to_string(id).c_str());
686 vsyncSchedule->dump(out);
687 }
Ady Abraham8735eac2020-08-12 16:35:04 -0700688}
689
Dominik Laskowskia8626ec2021-12-15 18:13:30 -0800690bool Scheduler::updateFrameRateOverrides(GlobalSignals consideredSignals, Fps displayRefreshRate) {
Dominik Laskowski596a2562022-10-28 11:26:12 -0400691 if (consideredSignals.idle) return false;
692
693 const auto frameRateOverrides =
694 leaderSelectorPtr()->getFrameRateOverrides(mPolicy.contentRequirements,
695 displayRefreshRate, consideredSignals);
696
697 // Note that RefreshRateSelector::supportsFrameRateOverrideByContent is checked when querying
698 // the FrameRateOverrideMappings rather than here.
699 return mFrameRateOverrideMappings.updateFrameRateOverridesByContent(frameRateOverrides);
700}
701
702void Scheduler::promoteLeaderDisplay(std::optional<PhysicalDisplayId> leaderIdOpt) {
703 // TODO(b/241286431): Choose the leader display.
704 mLeaderDisplayId = leaderIdOpt.value_or(mRefreshRateSelectors.begin()->first);
705 ALOGI("Display %s is the leader", to_string(*mLeaderDisplayId).c_str());
706
Leon Scroggins III31d41412022-11-18 16:42:53 -0500707 auto vsyncSchedule = getVsyncScheduleLocked(*mLeaderDisplayId);
Dominik Laskowski596a2562022-10-28 11:26:12 -0400708 if (const auto leaderPtr = leaderSelectorPtrLocked()) {
709 leaderPtr->setIdleTimerCallbacks(
710 {.platform = {.onReset = [this] { idleTimerCallback(TimerState::Reset); },
711 .onExpired = [this] { idleTimerCallback(TimerState::Expired); }},
712 .kernel = {.onReset = [this] { kernelIdleTimerCallback(TimerState::Reset); },
713 .onExpired =
714 [this] { kernelIdleTimerCallback(TimerState::Expired); }}});
715
716 leaderPtr->startIdleTimer();
Leon Scroggins III31d41412022-11-18 16:42:53 -0500717
718 const Fps refreshRate = leaderPtr->getActiveMode().modePtr->getFps();
719 setVsyncPeriod(vsyncSchedule, refreshRate.getPeriodNsecs(), true /* force */);
720 }
721
722 updateVsyncRegistration(vsyncSchedule->getDispatch());
723 {
724 std::lock_guard<std::mutex> lock(mConnectionsLock);
725 for (auto& [_, connection] : mConnections) {
726 connection.thread->onNewVsyncSchedule(vsyncSchedule);
727 }
Ady Abraham62a0be22020-12-08 16:54:10 -0800728 }
Dominik Laskowski596a2562022-10-28 11:26:12 -0400729}
730
731void Scheduler::demoteLeaderDisplay() {
732 // No need to lock for reads on kMainThreadContext.
733 if (const auto leaderPtr = FTL_FAKE_GUARD(mDisplayLock, leaderSelectorPtrLocked())) {
734 leaderPtr->stopIdleTimer();
735 leaderPtr->clearIdleTimerCallbacks();
736 }
737
738 // Clear state that depends on the leader's RefreshRateSelector.
739 std::scoped_lock lock(mPolicyLock);
740 mPolicy = {};
Ady Abraham62a0be22020-12-08 16:54:10 -0800741}
742
Dominik Laskowski0c41ffa2021-12-24 16:45:12 -0800743template <typename S, typename T>
744auto Scheduler::applyPolicy(S Policy::*statePtr, T&& newState) -> GlobalSignals {
Ady Abraham73c3df52023-01-12 18:09:31 -0800745 ATRACE_CALL();
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400746 std::vector<display::DisplayModeRequest> modeRequests;
Dominik Laskowskia8626ec2021-12-15 18:13:30 -0800747 GlobalSignals consideredSignals;
748
Ady Abraham62a0be22020-12-08 16:54:10 -0800749 bool refreshRateChanged = false;
750 bool frameRateOverridesChanged;
Dominik Laskowskia8626ec2021-12-15 18:13:30 -0800751
Ady Abraham8532d012019-05-08 14:50:56 -0700752 {
Dominik Laskowski596a2562022-10-28 11:26:12 -0400753 std::scoped_lock lock(mPolicyLock);
Dominik Laskowski0c41ffa2021-12-24 16:45:12 -0800754
755 auto& currentState = mPolicy.*statePtr;
756 if (currentState == newState) return {};
757 currentState = std::forward<T>(newState);
758
Dominik Laskowski596a2562022-10-28 11:26:12 -0400759 DisplayModeChoiceMap modeChoices;
Ady Abrahamace3d052022-11-17 16:25:05 -0800760 ftl::Optional<FrameRateMode> modeOpt;
Dominik Laskowski596a2562022-10-28 11:26:12 -0400761 {
762 std::scoped_lock lock(mDisplayLock);
763 ftl::FakeGuard guard(kMainThreadContext);
764
765 modeChoices = chooseDisplayModes();
766
767 // TODO(b/240743786): The leader display's mode must change for any DisplayModeRequest
768 // to go through. Fix this by tracking per-display Scheduler::Policy and timers.
Ady Abrahamace3d052022-11-17 16:25:05 -0800769 std::tie(modeOpt, consideredSignals) =
Dominik Laskowski596a2562022-10-28 11:26:12 -0400770 modeChoices.get(*mLeaderDisplayId)
771 .transform([](const DisplayModeChoice& choice) {
Ady Abrahamace3d052022-11-17 16:25:05 -0800772 return std::make_pair(choice.mode, choice.consideredSignals);
Dominik Laskowski596a2562022-10-28 11:26:12 -0400773 })
774 .value();
775 }
ramindani69b58e82022-09-26 16:48:36 -0700776
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400777 modeRequests.reserve(modeChoices.size());
778 for (auto& [id, choice] : modeChoices) {
779 modeRequests.emplace_back(
Ady Abrahamace3d052022-11-17 16:25:05 -0800780 display::DisplayModeRequest{.mode = std::move(choice.mode),
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400781 .emitEvent = !choice.consideredSignals.idle});
782 }
Dominik Laskowski0c41ffa2021-12-24 16:45:12 -0800783
Ady Abrahamace3d052022-11-17 16:25:05 -0800784 frameRateOverridesChanged = updateFrameRateOverrides(consideredSignals, modeOpt->fps);
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400785
Ady Abrahamace3d052022-11-17 16:25:05 -0800786 if (mPolicy.modeOpt != modeOpt) {
787 mPolicy.modeOpt = modeOpt;
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400788 refreshRateChanged = true;
789 } else {
Marin Shalamanova7fe3042021-01-29 21:02:08 +0100790 // We don't need to change the display mode, but we might need to send an event
Dominik Laskowski0c41ffa2021-12-24 16:45:12 -0800791 // about a mode change, since it was suppressed if previously considered idle.
Ady Abrahamdfd62162020-06-10 16:11:56 -0700792 if (!consideredSignals.idle) {
Marin Shalamanova7fe3042021-01-29 21:02:08 +0100793 dispatchCachedReportedMode();
Ady Abrahamdfd62162020-06-10 16:11:56 -0700794 }
Ady Abraham8532d012019-05-08 14:50:56 -0700795 }
Ady Abraham8532d012019-05-08 14:50:56 -0700796 }
Ady Abraham62a0be22020-12-08 16:54:10 -0800797 if (refreshRateChanged) {
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400798 mSchedulerCallback.requestDisplayModes(std::move(modeRequests));
Ady Abraham62a0be22020-12-08 16:54:10 -0800799 }
800 if (frameRateOverridesChanged) {
801 mSchedulerCallback.triggerOnFrameRateOverridesChanged();
802 }
Dominik Laskowski0c41ffa2021-12-24 16:45:12 -0800803 return consideredSignals;
Ady Abraham8532d012019-05-08 14:50:56 -0700804}
805
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400806auto Scheduler::chooseDisplayModes() const -> DisplayModeChoiceMap {
Ady Abraham4ccdcb42020-02-11 17:34:34 -0800807 ATRACE_CALL();
Ady Abraham09bd3922019-04-08 10:44:56 -0700808
Ady Abraham68636062022-11-16 17:07:25 -0800809 using RankedRefreshRates = RefreshRateSelector::RankedFrameRates;
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400810 display::PhysicalDisplayVector<RankedRefreshRates> perDisplayRanking;
Dominik Laskowski01602522022-10-07 19:02:28 -0400811
812 // Tallies the score of a refresh rate across `displayCount` displays.
813 struct RefreshRateTally {
814 explicit RefreshRateTally(float score) : score(score) {}
815
816 float score;
817 size_t displayCount = 1;
818 };
819
820 // Chosen to exceed a typical number of refresh rates across displays.
821 constexpr size_t kStaticCapacity = 8;
822 ftl::SmallMap<Fps, RefreshRateTally, kStaticCapacity, FpsApproxEqual> refreshRateTallies;
823
824 const auto globalSignals = makeGlobalSignals();
Dominik Laskowskia8626ec2021-12-15 18:13:30 -0800825
Dominik Laskowskib5a094b2022-10-27 12:00:12 -0400826 for (const auto& [id, selectorPtr] : mRefreshRateSelectors) {
Ady Abrahamace3d052022-11-17 16:25:05 -0800827 auto rankedFrameRates =
Ady Abraham68636062022-11-16 17:07:25 -0800828 selectorPtr->getRankedFrameRates(mPolicy.contentRequirements, globalSignals);
ramindani69b58e82022-09-26 16:48:36 -0700829
Ady Abrahamace3d052022-11-17 16:25:05 -0800830 for (const auto& [frameRateMode, score] : rankedFrameRates.ranking) {
831 const auto [it, inserted] = refreshRateTallies.try_emplace(frameRateMode.fps, score);
Dominik Laskowski01602522022-10-07 19:02:28 -0400832
833 if (!inserted) {
834 auto& tally = it->second;
835 tally.score += score;
836 tally.displayCount++;
837 }
838 }
839
Ady Abrahamace3d052022-11-17 16:25:05 -0800840 perDisplayRanking.push_back(std::move(rankedFrameRates));
Dominik Laskowski95df6a12022-10-07 18:11:07 -0400841 }
ramindani69b58e82022-09-26 16:48:36 -0700842
Dominik Laskowski01602522022-10-07 19:02:28 -0400843 auto maxScoreIt = refreshRateTallies.cbegin();
ramindani69b58e82022-09-26 16:48:36 -0700844
Dominik Laskowski01602522022-10-07 19:02:28 -0400845 // Find the first refresh rate common to all displays.
846 while (maxScoreIt != refreshRateTallies.cend() &&
Dominik Laskowskib5a094b2022-10-27 12:00:12 -0400847 maxScoreIt->second.displayCount != mRefreshRateSelectors.size()) {
Dominik Laskowski01602522022-10-07 19:02:28 -0400848 ++maxScoreIt;
849 }
850
851 if (maxScoreIt != refreshRateTallies.cend()) {
852 // Choose the highest refresh rate common to all displays, if any.
853 for (auto it = maxScoreIt + 1; it != refreshRateTallies.cend(); ++it) {
854 const auto [fps, tally] = *it;
855
Dominik Laskowskib5a094b2022-10-27 12:00:12 -0400856 if (tally.displayCount == mRefreshRateSelectors.size() &&
857 tally.score > maxScoreIt->second.score) {
Dominik Laskowski01602522022-10-07 19:02:28 -0400858 maxScoreIt = it;
859 }
ramindani7c487282022-10-10 16:17:51 -0700860 }
861 }
ramindani69b58e82022-09-26 16:48:36 -0700862
Dominik Laskowski01602522022-10-07 19:02:28 -0400863 const std::optional<Fps> chosenFps = maxScoreIt != refreshRateTallies.cend()
864 ? std::make_optional(maxScoreIt->first)
865 : std::nullopt;
866
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400867 DisplayModeChoiceMap modeChoices;
Dominik Laskowski01602522022-10-07 19:02:28 -0400868
ramindani69b58e82022-09-26 16:48:36 -0700869 using fps_approx_ops::operator==;
Dominik Laskowski01602522022-10-07 19:02:28 -0400870
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400871 for (auto& [ranking, signals] : perDisplayRanking) {
Dominik Laskowski01602522022-10-07 19:02:28 -0400872 if (!chosenFps) {
Ady Abraham68636062022-11-16 17:07:25 -0800873 const auto& [frameRateMode, _] = ranking.front();
Ady Abrahamace3d052022-11-17 16:25:05 -0800874 modeChoices.try_emplace(frameRateMode.modePtr->getPhysicalDisplayId(),
875 DisplayModeChoice{frameRateMode, signals});
Dominik Laskowski01602522022-10-07 19:02:28 -0400876 continue;
877 }
878
Ady Abraham68636062022-11-16 17:07:25 -0800879 for (auto& [frameRateMode, _] : ranking) {
Ady Abrahamace3d052022-11-17 16:25:05 -0800880 if (frameRateMode.fps == *chosenFps) {
881 modeChoices.try_emplace(frameRateMode.modePtr->getPhysicalDisplayId(),
882 DisplayModeChoice{frameRateMode, signals});
Dominik Laskowski01602522022-10-07 19:02:28 -0400883 break;
884 }
885 }
886 }
Dominik Laskowski530d6bd2022-10-10 16:55:54 -0400887 return modeChoices;
ramindani69b58e82022-09-26 16:48:36 -0700888}
889
Dominik Laskowski95df6a12022-10-07 18:11:07 -0400890GlobalSignals Scheduler::makeGlobalSignals() const {
ramindani38c84982022-08-29 18:02:57 +0000891 const bool powerOnImminent = mDisplayPowerTimer &&
892 (mPolicy.displayPowerMode != hal::PowerMode::ON ||
893 mPolicy.displayPowerTimer == TimerState::Reset);
Ady Abraham6fe2c172019-07-12 12:37:57 -0700894
Dominik Laskowski95df6a12022-10-07 18:11:07 -0400895 return {.touch = mTouchTimer && mPolicy.touch == TouchState::Active,
896 .idle = mPolicy.idleTimer == TimerState::Expired,
897 .powerOnImminent = powerOnImminent};
Ana Krulecfefd6ae2019-02-13 17:53:08 -0800898}
899
Dominik Laskowskifc378b02022-12-02 14:56:05 -0500900FrameRateMode Scheduler::getPreferredDisplayMode() {
Dominik Laskowski068173d2021-08-11 17:22:59 -0700901 std::lock_guard<std::mutex> lock(mPolicyLock);
Dominik Laskowskifc378b02022-12-02 14:56:05 -0500902 const auto frameRateMode =
903 leaderSelectorPtr()
904 ->getRankedFrameRates(mPolicy.contentRequirements, makeGlobalSignals())
905 .ranking.front()
906 .frameRateMode;
Dominik Laskowski95df6a12022-10-07 18:11:07 -0400907
Dominik Laskowskifc378b02022-12-02 14:56:05 -0500908 // Make sure the stored mode is up to date.
909 mPolicy.modeOpt = frameRateMode;
910
911 return frameRateMode;
Daniel Solomon0f0ddc12019-08-19 19:31:09 -0700912}
913
Peiyong Line9d809e2020-04-14 13:10:48 -0700914void Scheduler::onNewVsyncPeriodChangeTimeline(const hal::VsyncPeriodChangeTimeline& timeline) {
Ady Abraham3a77a7b2019-12-02 18:46:59 -0800915 std::lock_guard<std::mutex> lock(mVsyncTimelineLock);
916 mLastVsyncPeriodChangeTimeline = std::make_optional(timeline);
917
918 const auto maxAppliedTime = systemTime() + MAX_VSYNC_APPLIED_TIME.count();
919 if (timeline.newVsyncAppliedTimeNanos > maxAppliedTime) {
920 mLastVsyncPeriodChangeTimeline->newVsyncAppliedTimeNanos = maxAppliedTime;
921 }
922}
923
Dominik Laskowskidd5827a2022-03-17 12:44:23 -0700924bool Scheduler::onPostComposition(nsecs_t presentTime) {
925 std::lock_guard<std::mutex> lock(mVsyncTimelineLock);
926 if (mLastVsyncPeriodChangeTimeline && mLastVsyncPeriodChangeTimeline->refreshRequired) {
927 if (presentTime < mLastVsyncPeriodChangeTimeline->refreshTimeNanos) {
928 // We need to composite again as refreshTimeNanos is still in the future.
929 return true;
Dominik Laskowski8da6b0e2021-05-12 15:34:13 -0700930 }
Dominik Laskowski8da6b0e2021-05-12 15:34:13 -0700931
Dominik Laskowskidd5827a2022-03-17 12:44:23 -0700932 mLastVsyncPeriodChangeTimeline->refreshRequired = false;
Ana Krulecfefd6ae2019-02-13 17:53:08 -0800933 }
Dominik Laskowskidd5827a2022-03-17 12:44:23 -0700934 return false;
Ana Krulecfefd6ae2019-02-13 17:53:08 -0800935}
936
Ady Abraham7825c682021-05-17 15:12:14 -0700937void Scheduler::onActiveDisplayAreaChanged(uint32_t displayArea) {
Dominik Laskowski9c93d602021-10-07 19:38:26 -0700938 mLayerHistory.setDisplayArea(displayArea);
Ady Abraham8a82ba62020-01-17 12:43:17 -0800939}
940
Andy Yu2ae6b6b2021-11-18 14:51:06 -0800941void Scheduler::setGameModeRefreshRateForUid(FrameRateOverride frameRateOverride) {
942 if (frameRateOverride.frameRateHz > 0.f && frameRateOverride.frameRateHz < 1.f) {
943 return;
944 }
945
946 mFrameRateOverrideMappings.setGameModeRefreshRateForUid(frameRateOverride);
947}
948
Ady Abraham62a0be22020-12-08 16:54:10 -0800949void Scheduler::setPreferredRefreshRateForUid(FrameRateOverride frameRateOverride) {
950 if (frameRateOverride.frameRateHz > 0.f && frameRateOverride.frameRateHz < 1.f) {
951 return;
952 }
953
Andy Yu2ae6b6b2021-11-18 14:51:06 -0800954 mFrameRateOverrideMappings.setPreferredRefreshRateForUid(frameRateOverride);
Ady Abraham62a0be22020-12-08 16:54:10 -0800955}
956
Dominik Laskowski068173d2021-08-11 17:22:59 -0700957} // namespace android::scheduler