xref: /aosp_15_r20/frameworks/native/services/surfaceflinger/Scheduler/Scheduler.h (revision 38e8c45f13ce32b0dcecb25141ffecaf386fa17f)
1*38e8c45fSAndroid Build Coastguard Worker /*
2*38e8c45fSAndroid Build Coastguard Worker  * Copyright 2018 The Android Open Source Project
3*38e8c45fSAndroid Build Coastguard Worker  *
4*38e8c45fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*38e8c45fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*38e8c45fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*38e8c45fSAndroid Build Coastguard Worker  *
8*38e8c45fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*38e8c45fSAndroid Build Coastguard Worker  *
10*38e8c45fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*38e8c45fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*38e8c45fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*38e8c45fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*38e8c45fSAndroid Build Coastguard Worker  * limitations under the License.
15*38e8c45fSAndroid Build Coastguard Worker  */
16*38e8c45fSAndroid Build Coastguard Worker 
17*38e8c45fSAndroid Build Coastguard Worker #pragma once
18*38e8c45fSAndroid Build Coastguard Worker 
19*38e8c45fSAndroid Build Coastguard Worker #include <atomic>
20*38e8c45fSAndroid Build Coastguard Worker #include <cstdint>
21*38e8c45fSAndroid Build Coastguard Worker #include <functional>
22*38e8c45fSAndroid Build Coastguard Worker #include <future>
23*38e8c45fSAndroid Build Coastguard Worker #include <memory>
24*38e8c45fSAndroid Build Coastguard Worker #include <mutex>
25*38e8c45fSAndroid Build Coastguard Worker #include <unordered_map>
26*38e8c45fSAndroid Build Coastguard Worker #include <utility>
27*38e8c45fSAndroid Build Coastguard Worker 
28*38e8c45fSAndroid Build Coastguard Worker // TODO(b/129481165): remove the #pragma below and fix conversion issues
29*38e8c45fSAndroid Build Coastguard Worker #pragma clang diagnostic push
30*38e8c45fSAndroid Build Coastguard Worker #pragma clang diagnostic ignored "-Wconversion"
31*38e8c45fSAndroid Build Coastguard Worker #pragma clang diagnostic ignored "-Wextra"
32*38e8c45fSAndroid Build Coastguard Worker #include <ui/GraphicTypes.h>
33*38e8c45fSAndroid Build Coastguard Worker #pragma clang diagnostic pop // ignored "-Wconversion -Wextra"
34*38e8c45fSAndroid Build Coastguard Worker 
35*38e8c45fSAndroid Build Coastguard Worker #include <ftl/fake_guard.h>
36*38e8c45fSAndroid Build Coastguard Worker #include <ftl/non_null.h>
37*38e8c45fSAndroid Build Coastguard Worker #include <ftl/optional.h>
38*38e8c45fSAndroid Build Coastguard Worker #include <scheduler/Features.h>
39*38e8c45fSAndroid Build Coastguard Worker #include <scheduler/FrameRateMode.h>
40*38e8c45fSAndroid Build Coastguard Worker #include <scheduler/FrameTargeter.h>
41*38e8c45fSAndroid Build Coastguard Worker #include <scheduler/Time.h>
42*38e8c45fSAndroid Build Coastguard Worker #include <scheduler/VsyncConfig.h>
43*38e8c45fSAndroid Build Coastguard Worker #include <ui/DisplayId.h>
44*38e8c45fSAndroid Build Coastguard Worker #include <ui/DisplayMap.h>
45*38e8c45fSAndroid Build Coastguard Worker 
46*38e8c45fSAndroid Build Coastguard Worker #include "DisplayHardware/DisplayMode.h"
47*38e8c45fSAndroid Build Coastguard Worker #include "EventThread.h"
48*38e8c45fSAndroid Build Coastguard Worker #include "FrameRateOverrideMappings.h"
49*38e8c45fSAndroid Build Coastguard Worker #include "ISchedulerCallback.h"
50*38e8c45fSAndroid Build Coastguard Worker #include "LayerHistory.h"
51*38e8c45fSAndroid Build Coastguard Worker #include "MessageQueue.h"
52*38e8c45fSAndroid Build Coastguard Worker #include "OneShotTimer.h"
53*38e8c45fSAndroid Build Coastguard Worker #include "RefreshRateSelector.h"
54*38e8c45fSAndroid Build Coastguard Worker #include "SmallAreaDetectionAllowMappings.h"
55*38e8c45fSAndroid Build Coastguard Worker #include "Utils/Dumper.h"
56*38e8c45fSAndroid Build Coastguard Worker #include "VsyncModulator.h"
57*38e8c45fSAndroid Build Coastguard Worker 
58*38e8c45fSAndroid Build Coastguard Worker #include <FrontEnd/LayerHierarchy.h>
59*38e8c45fSAndroid Build Coastguard Worker 
60*38e8c45fSAndroid Build Coastguard Worker namespace android {
61*38e8c45fSAndroid Build Coastguard Worker 
62*38e8c45fSAndroid Build Coastguard Worker class FenceTime;
63*38e8c45fSAndroid Build Coastguard Worker class TimeStats;
64*38e8c45fSAndroid Build Coastguard Worker 
65*38e8c45fSAndroid Build Coastguard Worker namespace frametimeline {
66*38e8c45fSAndroid Build Coastguard Worker class TokenManager;
67*38e8c45fSAndroid Build Coastguard Worker } // namespace frametimeline
68*38e8c45fSAndroid Build Coastguard Worker 
69*38e8c45fSAndroid Build Coastguard Worker namespace surfaceflinger {
70*38e8c45fSAndroid Build Coastguard Worker class Factory;
71*38e8c45fSAndroid Build Coastguard Worker } // namespace surfaceflinger
72*38e8c45fSAndroid Build Coastguard Worker 
73*38e8c45fSAndroid Build Coastguard Worker namespace scheduler {
74*38e8c45fSAndroid Build Coastguard Worker 
75*38e8c45fSAndroid Build Coastguard Worker using GlobalSignals = RefreshRateSelector::GlobalSignals;
76*38e8c45fSAndroid Build Coastguard Worker 
77*38e8c45fSAndroid Build Coastguard Worker class RefreshRateStats;
78*38e8c45fSAndroid Build Coastguard Worker class VsyncConfiguration;
79*38e8c45fSAndroid Build Coastguard Worker class VsyncSchedule;
80*38e8c45fSAndroid Build Coastguard Worker 
81*38e8c45fSAndroid Build Coastguard Worker enum class Cycle {
82*38e8c45fSAndroid Build Coastguard Worker     Render,       // Surface rendering.
83*38e8c45fSAndroid Build Coastguard Worker     LastComposite // Ahead of display compositing by one refresh period.
84*38e8c45fSAndroid Build Coastguard Worker };
85*38e8c45fSAndroid Build Coastguard Worker 
86*38e8c45fSAndroid Build Coastguard Worker class Scheduler : public IEventThreadCallback, android::impl::MessageQueue {
87*38e8c45fSAndroid Build Coastguard Worker     using Impl = android::impl::MessageQueue;
88*38e8c45fSAndroid Build Coastguard Worker 
89*38e8c45fSAndroid Build Coastguard Worker public:
90*38e8c45fSAndroid Build Coastguard Worker     Scheduler(ICompositor&, ISchedulerCallback&, FeatureFlags, surfaceflinger::Factory&,
91*38e8c45fSAndroid Build Coastguard Worker               Fps activeRefreshRate, TimeStats&);
92*38e8c45fSAndroid Build Coastguard Worker     virtual ~Scheduler();
93*38e8c45fSAndroid Build Coastguard Worker 
94*38e8c45fSAndroid Build Coastguard Worker     void startTimers();
95*38e8c45fSAndroid Build Coastguard Worker 
96*38e8c45fSAndroid Build Coastguard Worker     // TODO: b/241285191 - Remove this API by promoting pacesetter in onScreen{Acquired,Released}.
97*38e8c45fSAndroid Build Coastguard Worker     void setPacesetterDisplay(PhysicalDisplayId) REQUIRES(kMainThreadContext)
98*38e8c45fSAndroid Build Coastguard Worker             EXCLUDES(mDisplayLock);
99*38e8c45fSAndroid Build Coastguard Worker 
100*38e8c45fSAndroid Build Coastguard Worker     using RefreshRateSelectorPtr = std::shared_ptr<RefreshRateSelector>;
101*38e8c45fSAndroid Build Coastguard Worker 
102*38e8c45fSAndroid Build Coastguard Worker     using ConstVsyncSchedulePtr = std::shared_ptr<const VsyncSchedule>;
103*38e8c45fSAndroid Build Coastguard Worker     using VsyncSchedulePtr = std::shared_ptr<VsyncSchedule>;
104*38e8c45fSAndroid Build Coastguard Worker 
105*38e8c45fSAndroid Build Coastguard Worker     // After registration/unregistration, `activeDisplayId` is promoted to pacesetter. Note that the
106*38e8c45fSAndroid Build Coastguard Worker     // active display is never unregistered, since hotplug disconnect never happens for activatable
107*38e8c45fSAndroid Build Coastguard Worker     // displays, i.e. a foldable's internal displays or otherwise the (internal or external) primary
108*38e8c45fSAndroid Build Coastguard Worker     // display.
109*38e8c45fSAndroid Build Coastguard Worker     // TODO: b/255635821 - Remove active display parameters.
110*38e8c45fSAndroid Build Coastguard Worker     void registerDisplay(PhysicalDisplayId, RefreshRateSelectorPtr,
111*38e8c45fSAndroid Build Coastguard Worker                          PhysicalDisplayId activeDisplayId) REQUIRES(kMainThreadContext)
112*38e8c45fSAndroid Build Coastguard Worker             EXCLUDES(mDisplayLock);
113*38e8c45fSAndroid Build Coastguard Worker     void unregisterDisplay(PhysicalDisplayId, PhysicalDisplayId activeDisplayId)
114*38e8c45fSAndroid Build Coastguard Worker             REQUIRES(kMainThreadContext) EXCLUDES(mDisplayLock);
115*38e8c45fSAndroid Build Coastguard Worker 
116*38e8c45fSAndroid Build Coastguard Worker     void run();
117*38e8c45fSAndroid Build Coastguard Worker 
118*38e8c45fSAndroid Build Coastguard Worker     void initVsync(frametimeline::TokenManager&, std::chrono::nanoseconds workDuration);
119*38e8c45fSAndroid Build Coastguard Worker 
120*38e8c45fSAndroid Build Coastguard Worker     using Impl::setDuration;
121*38e8c45fSAndroid Build Coastguard Worker 
122*38e8c45fSAndroid Build Coastguard Worker     using Impl::getScheduledFrameResult;
123*38e8c45fSAndroid Build Coastguard Worker     using Impl::scheduleConfigure;
124*38e8c45fSAndroid Build Coastguard Worker     using Impl::scheduleFrame;
125*38e8c45fSAndroid Build Coastguard Worker 
126*38e8c45fSAndroid Build Coastguard Worker     // Schedule an asynchronous or synchronous task on the main thread.
127*38e8c45fSAndroid Build Coastguard Worker     template <typename F, typename T = std::invoke_result_t<F>>
schedule(F && f)128*38e8c45fSAndroid Build Coastguard Worker     [[nodiscard]] std::future<T> schedule(F&& f) {
129*38e8c45fSAndroid Build Coastguard Worker         auto [task, future] = makeTask(std::move(f));
130*38e8c45fSAndroid Build Coastguard Worker         postMessage(std::move(task));
131*38e8c45fSAndroid Build Coastguard Worker         return std::move(future);
132*38e8c45fSAndroid Build Coastguard Worker     }
133*38e8c45fSAndroid Build Coastguard Worker 
134*38e8c45fSAndroid Build Coastguard Worker     template <typename F, typename T = std::invoke_result_t<F>>
scheduleDelayed(F && f,nsecs_t uptimeDelay)135*38e8c45fSAndroid Build Coastguard Worker     [[nodiscard]] std::future<T> scheduleDelayed(F&& f, nsecs_t uptimeDelay) {
136*38e8c45fSAndroid Build Coastguard Worker         auto [task, future] = makeTask(std::move(f));
137*38e8c45fSAndroid Build Coastguard Worker         postMessageDelayed(std::move(task), uptimeDelay);
138*38e8c45fSAndroid Build Coastguard Worker         return std::move(future);
139*38e8c45fSAndroid Build Coastguard Worker     }
140*38e8c45fSAndroid Build Coastguard Worker 
141*38e8c45fSAndroid Build Coastguard Worker     void createEventThread(Cycle, frametimeline::TokenManager*,
142*38e8c45fSAndroid Build Coastguard Worker                            std::chrono::nanoseconds workDuration,
143*38e8c45fSAndroid Build Coastguard Worker                            std::chrono::nanoseconds readyDuration);
144*38e8c45fSAndroid Build Coastguard Worker 
145*38e8c45fSAndroid Build Coastguard Worker     sp<IDisplayEventConnection> createDisplayEventConnection(
146*38e8c45fSAndroid Build Coastguard Worker             Cycle, EventRegistrationFlags eventRegistration = {},
147*38e8c45fSAndroid Build Coastguard Worker             const sp<IBinder>& layerHandle = nullptr) EXCLUDES(mChoreographerLock);
148*38e8c45fSAndroid Build Coastguard Worker 
149*38e8c45fSAndroid Build Coastguard Worker     enum class Hotplug { Connected, Disconnected };
150*38e8c45fSAndroid Build Coastguard Worker     void dispatchHotplug(PhysicalDisplayId, Hotplug);
151*38e8c45fSAndroid Build Coastguard Worker 
152*38e8c45fSAndroid Build Coastguard Worker     void dispatchHotplugError(int32_t errorCode);
153*38e8c45fSAndroid Build Coastguard Worker 
154*38e8c45fSAndroid Build Coastguard Worker     // Returns true if the PhysicalDisplayId is the pacesetter.
155*38e8c45fSAndroid Build Coastguard Worker     bool onDisplayModeChanged(PhysicalDisplayId, const FrameRateMode&,
156*38e8c45fSAndroid Build Coastguard Worker                               bool clearContentRequirements) EXCLUDES(mPolicyLock);
157*38e8c45fSAndroid Build Coastguard Worker 
158*38e8c45fSAndroid Build Coastguard Worker     void onDisplayModeRejected(PhysicalDisplayId, DisplayModeId);
159*38e8c45fSAndroid Build Coastguard Worker 
160*38e8c45fSAndroid Build Coastguard Worker     void enableSyntheticVsync(bool = true) REQUIRES(kMainThreadContext);
161*38e8c45fSAndroid Build Coastguard Worker     void omitVsyncDispatching(bool) REQUIRES(kMainThreadContext);
162*38e8c45fSAndroid Build Coastguard Worker 
163*38e8c45fSAndroid Build Coastguard Worker     void onHdcpLevelsChanged(Cycle, PhysicalDisplayId, int32_t, int32_t);
164*38e8c45fSAndroid Build Coastguard Worker 
165*38e8c45fSAndroid Build Coastguard Worker     // Modifies work duration in the event thread.
166*38e8c45fSAndroid Build Coastguard Worker     void setDuration(Cycle, std::chrono::nanoseconds workDuration,
167*38e8c45fSAndroid Build Coastguard Worker                      std::chrono::nanoseconds readyDuration);
168*38e8c45fSAndroid Build Coastguard Worker 
vsyncModulator()169*38e8c45fSAndroid Build Coastguard Worker     VsyncModulator& vsyncModulator() { return *mVsyncModulator; }
170*38e8c45fSAndroid Build Coastguard Worker 
171*38e8c45fSAndroid Build Coastguard Worker     // In some cases, we should only modulate for the pacesetter display. In those
172*38e8c45fSAndroid Build Coastguard Worker     // cases, the caller should pass in the relevant display, and the method
173*38e8c45fSAndroid Build Coastguard Worker     // will no-op if it's not the pacesetter. Other cases are not specific to a
174*38e8c45fSAndroid Build Coastguard Worker     // display.
175*38e8c45fSAndroid Build Coastguard Worker     template <typename... Args,
176*38e8c45fSAndroid Build Coastguard Worker               typename Handler = std::optional<VsyncConfig> (VsyncModulator::*)(Args...)>
modulateVsync(std::optional<PhysicalDisplayId> id,Handler handler,Args...args)177*38e8c45fSAndroid Build Coastguard Worker     void modulateVsync(std::optional<PhysicalDisplayId> id, Handler handler, Args... args) {
178*38e8c45fSAndroid Build Coastguard Worker         if (id) {
179*38e8c45fSAndroid Build Coastguard Worker             std::scoped_lock lock(mDisplayLock);
180*38e8c45fSAndroid Build Coastguard Worker             ftl::FakeGuard guard(kMainThreadContext);
181*38e8c45fSAndroid Build Coastguard Worker             if (id != mPacesetterDisplayId) {
182*38e8c45fSAndroid Build Coastguard Worker                 return;
183*38e8c45fSAndroid Build Coastguard Worker             }
184*38e8c45fSAndroid Build Coastguard Worker         }
185*38e8c45fSAndroid Build Coastguard Worker 
186*38e8c45fSAndroid Build Coastguard Worker         if (const auto config = (*mVsyncModulator.*handler)(args...)) {
187*38e8c45fSAndroid Build Coastguard Worker             setVsyncConfig(*config, getPacesetterVsyncPeriod());
188*38e8c45fSAndroid Build Coastguard Worker         }
189*38e8c45fSAndroid Build Coastguard Worker     }
190*38e8c45fSAndroid Build Coastguard Worker 
191*38e8c45fSAndroid Build Coastguard Worker     void updatePhaseConfiguration(PhysicalDisplayId, Fps);
192*38e8c45fSAndroid Build Coastguard Worker 
getVsyncConfiguration()193*38e8c45fSAndroid Build Coastguard Worker     const VsyncConfiguration& getVsyncConfiguration() const { return *mVsyncConfiguration; }
194*38e8c45fSAndroid Build Coastguard Worker 
195*38e8c45fSAndroid Build Coastguard Worker     // Sets the render rate for the scheduler to run at.
196*38e8c45fSAndroid Build Coastguard Worker     void setRenderRate(PhysicalDisplayId, Fps, bool applyImmediately);
197*38e8c45fSAndroid Build Coastguard Worker 
198*38e8c45fSAndroid Build Coastguard Worker     void enableHardwareVsync(PhysicalDisplayId) REQUIRES(kMainThreadContext);
199*38e8c45fSAndroid Build Coastguard Worker     void disableHardwareVsync(PhysicalDisplayId, bool disallow) REQUIRES(kMainThreadContext);
200*38e8c45fSAndroid Build Coastguard Worker 
201*38e8c45fSAndroid Build Coastguard Worker     // Resyncs the scheduler to hardware vsync.
202*38e8c45fSAndroid Build Coastguard Worker     // If allowToEnable is true, then hardware vsync will be turned on.
203*38e8c45fSAndroid Build Coastguard Worker     // Otherwise, if hardware vsync is not already enabled then this method will
204*38e8c45fSAndroid Build Coastguard Worker     // no-op.
205*38e8c45fSAndroid Build Coastguard Worker     // If modePtr is nullopt, use the active display mode.
206*38e8c45fSAndroid Build Coastguard Worker     void resyncToHardwareVsync(PhysicalDisplayId id, bool allowToEnable,
EXCLUDES(mDisplayLock)207*38e8c45fSAndroid Build Coastguard Worker                                DisplayModePtr modePtr = nullptr) EXCLUDES(mDisplayLock) {
208*38e8c45fSAndroid Build Coastguard Worker         std::scoped_lock lock(mDisplayLock);
209*38e8c45fSAndroid Build Coastguard Worker         ftl::FakeGuard guard(kMainThreadContext);
210*38e8c45fSAndroid Build Coastguard Worker         resyncToHardwareVsyncLocked(id, allowToEnable, modePtr);
211*38e8c45fSAndroid Build Coastguard Worker     }
212*38e8c45fSAndroid Build Coastguard Worker     void resync() override EXCLUDES(mDisplayLock);
forceNextResync()213*38e8c45fSAndroid Build Coastguard Worker     void forceNextResync() { mLastResyncTime = 0; }
214*38e8c45fSAndroid Build Coastguard Worker 
215*38e8c45fSAndroid Build Coastguard Worker     // Passes a vsync sample to VsyncController. Returns true if
216*38e8c45fSAndroid Build Coastguard Worker     // VsyncController detected that the vsync period changed and false
217*38e8c45fSAndroid Build Coastguard Worker     // otherwise.
218*38e8c45fSAndroid Build Coastguard Worker     bool addResyncSample(PhysicalDisplayId, nsecs_t timestamp,
219*38e8c45fSAndroid Build Coastguard Worker                          std::optional<nsecs_t> hwcVsyncPeriod);
220*38e8c45fSAndroid Build Coastguard Worker     void addPresentFence(PhysicalDisplayId, std::shared_ptr<FenceTime>)
221*38e8c45fSAndroid Build Coastguard Worker             REQUIRES(kMainThreadContext);
222*38e8c45fSAndroid Build Coastguard Worker 
223*38e8c45fSAndroid Build Coastguard Worker     // Layers are registered on creation, and unregistered when the weak reference expires.
224*38e8c45fSAndroid Build Coastguard Worker     void registerLayer(Layer*, FrameRateCompatibility);
225*38e8c45fSAndroid Build Coastguard Worker     void recordLayerHistory(int32_t id, const LayerProps& layerProps, nsecs_t presentTime,
226*38e8c45fSAndroid Build Coastguard Worker                             nsecs_t now, LayerHistory::LayerUpdateType) EXCLUDES(mDisplayLock);
227*38e8c45fSAndroid Build Coastguard Worker     void setModeChangePending(bool pending);
228*38e8c45fSAndroid Build Coastguard Worker     void setDefaultFrameRateCompatibility(int32_t id, scheduler::FrameRateCompatibility);
229*38e8c45fSAndroid Build Coastguard Worker     void setLayerProperties(int32_t id, const LayerProps&);
230*38e8c45fSAndroid Build Coastguard Worker     void deregisterLayer(Layer*);
231*38e8c45fSAndroid Build Coastguard Worker     void onLayerDestroyed(Layer*) EXCLUDES(mChoreographerLock);
232*38e8c45fSAndroid Build Coastguard Worker 
233*38e8c45fSAndroid Build Coastguard Worker     // Detects content using layer history, and selects a matching refresh rate.
234*38e8c45fSAndroid Build Coastguard Worker     void chooseRefreshRateForContent(const surfaceflinger::frontend::LayerHierarchy*,
235*38e8c45fSAndroid Build Coastguard Worker                                      bool updateAttachedChoreographer) EXCLUDES(mDisplayLock);
236*38e8c45fSAndroid Build Coastguard Worker 
237*38e8c45fSAndroid Build Coastguard Worker     void resetIdleTimer();
238*38e8c45fSAndroid Build Coastguard Worker 
239*38e8c45fSAndroid Build Coastguard Worker     // Indicates that touch interaction is taking place.
240*38e8c45fSAndroid Build Coastguard Worker     void onTouchHint();
241*38e8c45fSAndroid Build Coastguard Worker 
242*38e8c45fSAndroid Build Coastguard Worker     void setDisplayPowerMode(PhysicalDisplayId, hal::PowerMode) REQUIRES(kMainThreadContext);
243*38e8c45fSAndroid Build Coastguard Worker 
244*38e8c45fSAndroid Build Coastguard Worker     // TODO(b/255635821): Track this per display.
245*38e8c45fSAndroid Build Coastguard Worker     void setActiveDisplayPowerModeForRefreshRateStats(hal::PowerMode) REQUIRES(kMainThreadContext);
246*38e8c45fSAndroid Build Coastguard Worker 
247*38e8c45fSAndroid Build Coastguard Worker     ConstVsyncSchedulePtr getVsyncSchedule(std::optional<PhysicalDisplayId> = std::nullopt) const
248*38e8c45fSAndroid Build Coastguard Worker             EXCLUDES(mDisplayLock);
249*38e8c45fSAndroid Build Coastguard Worker 
250*38e8c45fSAndroid Build Coastguard Worker     VsyncSchedulePtr getVsyncSchedule(std::optional<PhysicalDisplayId> idOpt = std::nullopt)
EXCLUDES(mDisplayLock)251*38e8c45fSAndroid Build Coastguard Worker             EXCLUDES(mDisplayLock) {
252*38e8c45fSAndroid Build Coastguard Worker         return std::const_pointer_cast<VsyncSchedule>(std::as_const(*this).getVsyncSchedule(idOpt));
253*38e8c45fSAndroid Build Coastguard Worker     }
254*38e8c45fSAndroid Build Coastguard Worker 
expectedPresentTimeForPacesetter()255*38e8c45fSAndroid Build Coastguard Worker     TimePoint expectedPresentTimeForPacesetter() const EXCLUDES(mDisplayLock) {
256*38e8c45fSAndroid Build Coastguard Worker         std::scoped_lock lock(mDisplayLock);
257*38e8c45fSAndroid Build Coastguard Worker         return pacesetterDisplayLocked()
258*38e8c45fSAndroid Build Coastguard Worker                 .transform([](const Display& display) {
259*38e8c45fSAndroid Build Coastguard Worker                     return display.targeterPtr->target().expectedPresentTime();
260*38e8c45fSAndroid Build Coastguard Worker                 })
261*38e8c45fSAndroid Build Coastguard Worker                 .value_or(TimePoint());
262*38e8c45fSAndroid Build Coastguard Worker     }
263*38e8c45fSAndroid Build Coastguard Worker 
264*38e8c45fSAndroid Build Coastguard Worker     // Returns true if a given vsync timestamp is considered valid vsync
265*38e8c45fSAndroid Build Coastguard Worker     // for a given uid
266*38e8c45fSAndroid Build Coastguard Worker     bool isVsyncValid(TimePoint expectedVsyncTime, uid_t uid) const;
267*38e8c45fSAndroid Build Coastguard Worker 
268*38e8c45fSAndroid Build Coastguard Worker     bool isVsyncInPhase(TimePoint expectedVsyncTime, Fps frameRate) const;
269*38e8c45fSAndroid Build Coastguard Worker 
270*38e8c45fSAndroid Build Coastguard Worker     void dump(utils::Dumper&) const;
271*38e8c45fSAndroid Build Coastguard Worker     void dump(Cycle, std::string&) const;
272*38e8c45fSAndroid Build Coastguard Worker     void dumpVsync(std::string&) const EXCLUDES(mDisplayLock);
273*38e8c45fSAndroid Build Coastguard Worker 
274*38e8c45fSAndroid Build Coastguard Worker     // Returns the preferred refresh rate and frame rate for the pacesetter display.
275*38e8c45fSAndroid Build Coastguard Worker     FrameRateMode getPreferredDisplayMode();
276*38e8c45fSAndroid Build Coastguard Worker 
277*38e8c45fSAndroid Build Coastguard Worker     // Notifies the scheduler about a refresh rate timeline change.
278*38e8c45fSAndroid Build Coastguard Worker     void onNewVsyncPeriodChangeTimeline(const hal::VsyncPeriodChangeTimeline& timeline);
279*38e8c45fSAndroid Build Coastguard Worker 
280*38e8c45fSAndroid Build Coastguard Worker     // Notifies the scheduler once the composition is presented. Returns if recomposite is needed.
281*38e8c45fSAndroid Build Coastguard Worker     bool onCompositionPresented(nsecs_t presentTime);
282*38e8c45fSAndroid Build Coastguard Worker 
283*38e8c45fSAndroid Build Coastguard Worker     // Notifies the scheduler when the display size has changed. Called from SF's main thread
284*38e8c45fSAndroid Build Coastguard Worker     void onActiveDisplayAreaChanged(uint32_t displayArea);
285*38e8c45fSAndroid Build Coastguard Worker 
286*38e8c45fSAndroid Build Coastguard Worker     // Stores the preferred refresh rate that an app should run at.
287*38e8c45fSAndroid Build Coastguard Worker     // FrameRateOverride.refreshRateHz == 0 means no preference.
288*38e8c45fSAndroid Build Coastguard Worker     void setPreferredRefreshRateForUid(FrameRateOverride);
289*38e8c45fSAndroid Build Coastguard Worker 
290*38e8c45fSAndroid Build Coastguard Worker     // Stores the frame rate override that a game should run at set by game interventions.
291*38e8c45fSAndroid Build Coastguard Worker     // FrameRateOverride.refreshRateHz == 0 means no preference.
292*38e8c45fSAndroid Build Coastguard Worker     void setGameModeFrameRateForUid(FrameRateOverride) EXCLUDES(mDisplayLock);
293*38e8c45fSAndroid Build Coastguard Worker 
294*38e8c45fSAndroid Build Coastguard Worker     // Stores the frame rate override that a game should run rat set by default game frame rate.
295*38e8c45fSAndroid Build Coastguard Worker     // FrameRateOverride.refreshRateHz == 0 means no preference, game default game frame rate is not
296*38e8c45fSAndroid Build Coastguard Worker     // enabled.
297*38e8c45fSAndroid Build Coastguard Worker     //
298*38e8c45fSAndroid Build Coastguard Worker     // "ro.surface_flinger.game_default_frame_rate_override" sets the frame rate value,
299*38e8c45fSAndroid Build Coastguard Worker     // "persist.graphics.game_default_frame_rate.enabled" controls whether this feature is enabled.
300*38e8c45fSAndroid Build Coastguard Worker     void setGameDefaultFrameRateForUid(FrameRateOverride) EXCLUDES(mDisplayLock);
301*38e8c45fSAndroid Build Coastguard Worker 
302*38e8c45fSAndroid Build Coastguard Worker     void updateSmallAreaDetection(std::vector<std::pair<int32_t, float>>& uidThresholdMappings);
303*38e8c45fSAndroid Build Coastguard Worker 
304*38e8c45fSAndroid Build Coastguard Worker     void setSmallAreaDetectionThreshold(int32_t appId, float threshold);
305*38e8c45fSAndroid Build Coastguard Worker 
306*38e8c45fSAndroid Build Coastguard Worker     // Returns true if the dirty area is less than threshold.
307*38e8c45fSAndroid Build Coastguard Worker     bool isSmallDirtyArea(int32_t appId, uint32_t dirtyArea);
308*38e8c45fSAndroid Build Coastguard Worker 
309*38e8c45fSAndroid Build Coastguard Worker     // Retrieves the overridden refresh rate for a given uid.
310*38e8c45fSAndroid Build Coastguard Worker     std::optional<Fps> getFrameRateOverride(uid_t) const EXCLUDES(mDisplayLock);
311*38e8c45fSAndroid Build Coastguard Worker 
getPacesetterVsyncPeriod()312*38e8c45fSAndroid Build Coastguard Worker     Period getPacesetterVsyncPeriod() const EXCLUDES(mDisplayLock) {
313*38e8c45fSAndroid Build Coastguard Worker         return pacesetterSelectorPtr()->getActiveMode().fps.getPeriod();
314*38e8c45fSAndroid Build Coastguard Worker     }
315*38e8c45fSAndroid Build Coastguard Worker 
getPacesetterRefreshRate()316*38e8c45fSAndroid Build Coastguard Worker     Fps getPacesetterRefreshRate() const EXCLUDES(mDisplayLock) {
317*38e8c45fSAndroid Build Coastguard Worker         return pacesetterSelectorPtr()->getActiveMode().fps;
318*38e8c45fSAndroid Build Coastguard Worker     }
319*38e8c45fSAndroid Build Coastguard Worker 
320*38e8c45fSAndroid Build Coastguard Worker     Fps getNextFrameInterval(PhysicalDisplayId, TimePoint currentExpectedPresentTime) const
321*38e8c45fSAndroid Build Coastguard Worker             EXCLUDES(mDisplayLock);
322*38e8c45fSAndroid Build Coastguard Worker 
323*38e8c45fSAndroid Build Coastguard Worker     // Returns the framerate of the layer with the given sequence ID
getLayerFramerate(nsecs_t now,int32_t id)324*38e8c45fSAndroid Build Coastguard Worker     float getLayerFramerate(nsecs_t now, int32_t id) const {
325*38e8c45fSAndroid Build Coastguard Worker         return mLayerHistory.getLayerFramerate(now, id);
326*38e8c45fSAndroid Build Coastguard Worker     }
327*38e8c45fSAndroid Build Coastguard Worker 
328*38e8c45fSAndroid Build Coastguard Worker     void updateFrameRateOverrides(GlobalSignals, Fps displayRefreshRate) EXCLUDES(mPolicyLock);
329*38e8c45fSAndroid Build Coastguard Worker 
330*38e8c45fSAndroid Build Coastguard Worker     // Returns true if the small dirty detection is enabled for the appId.
supportSmallDirtyDetection(int32_t appId)331*38e8c45fSAndroid Build Coastguard Worker     bool supportSmallDirtyDetection(int32_t appId) {
332*38e8c45fSAndroid Build Coastguard Worker         return mFeatures.test(Feature::kSmallDirtyContentDetection) &&
333*38e8c45fSAndroid Build Coastguard Worker                 mSmallAreaDetectionAllowMappings.getThresholdForAppId(appId).has_value();
334*38e8c45fSAndroid Build Coastguard Worker     }
335*38e8c45fSAndroid Build Coastguard Worker 
336*38e8c45fSAndroid Build Coastguard Worker     // Injects a delay that is a fraction of the predicted frame duration for the next frame.
injectPacesetterDelay(float frameDurationFraction)337*38e8c45fSAndroid Build Coastguard Worker     void injectPacesetterDelay(float frameDurationFraction) REQUIRES(kMainThreadContext) {
338*38e8c45fSAndroid Build Coastguard Worker         mPacesetterFrameDurationFractionToSkip = frameDurationFraction;
339*38e8c45fSAndroid Build Coastguard Worker     }
340*38e8c45fSAndroid Build Coastguard Worker 
341*38e8c45fSAndroid Build Coastguard Worker     // Propagates a flag to the EventThread indicating that buffer stuffing
342*38e8c45fSAndroid Build Coastguard Worker     // recovery should begin.
343*38e8c45fSAndroid Build Coastguard Worker     void addBufferStuffedUids(BufferStuffingMap bufferStuffedUids);
344*38e8c45fSAndroid Build Coastguard Worker 
setDebugPresentDelay(TimePoint delay)345*38e8c45fSAndroid Build Coastguard Worker     void setDebugPresentDelay(TimePoint delay) { mDebugPresentDelay = delay; }
346*38e8c45fSAndroid Build Coastguard Worker 
347*38e8c45fSAndroid Build Coastguard Worker private:
348*38e8c45fSAndroid Build Coastguard Worker     friend class TestableScheduler;
349*38e8c45fSAndroid Build Coastguard Worker 
350*38e8c45fSAndroid Build Coastguard Worker     enum class ContentDetectionState { Off, On };
351*38e8c45fSAndroid Build Coastguard Worker     enum class TimerState { Reset, Expired };
352*38e8c45fSAndroid Build Coastguard Worker     enum class TouchState { Inactive, Active };
353*38e8c45fSAndroid Build Coastguard Worker 
354*38e8c45fSAndroid Build Coastguard Worker     // impl::MessageQueue overrides:
355*38e8c45fSAndroid Build Coastguard Worker     void onFrameSignal(ICompositor&, VsyncId, TimePoint expectedVsyncTime) override
356*38e8c45fSAndroid Build Coastguard Worker             REQUIRES(kMainThreadContext, mDisplayLock);
357*38e8c45fSAndroid Build Coastguard Worker 
358*38e8c45fSAndroid Build Coastguard Worker     // Used to skip event dispatch before EventThread creation during boot.
359*38e8c45fSAndroid Build Coastguard Worker     // TODO: b/241285191 - Reorder Scheduler initialization to avoid this.
hasEventThreads()360*38e8c45fSAndroid Build Coastguard Worker     bool hasEventThreads() const {
361*38e8c45fSAndroid Build Coastguard Worker         return CC_LIKELY(
362*38e8c45fSAndroid Build Coastguard Worker                 mRenderEventThread &&
363*38e8c45fSAndroid Build Coastguard Worker                 (FlagManager::getInstance().deprecate_vsync_sf() || mLastCompositeEventThread));
364*38e8c45fSAndroid Build Coastguard Worker     }
365*38e8c45fSAndroid Build Coastguard Worker 
eventThreadFor(Cycle cycle)366*38e8c45fSAndroid Build Coastguard Worker     EventThread& eventThreadFor(Cycle cycle) const {
367*38e8c45fSAndroid Build Coastguard Worker         return *(cycle == Cycle::Render ? mRenderEventThread : mLastCompositeEventThread);
368*38e8c45fSAndroid Build Coastguard Worker     }
369*38e8c45fSAndroid Build Coastguard Worker 
370*38e8c45fSAndroid Build Coastguard Worker     // Update feature state machine to given state when corresponding timer resets or expires.
371*38e8c45fSAndroid Build Coastguard Worker     void kernelIdleTimerCallback(TimerState) EXCLUDES(mDisplayLock);
372*38e8c45fSAndroid Build Coastguard Worker     void idleTimerCallback(TimerState);
373*38e8c45fSAndroid Build Coastguard Worker     void touchTimerCallback(TimerState);
374*38e8c45fSAndroid Build Coastguard Worker     void displayPowerTimerCallback(TimerState);
375*38e8c45fSAndroid Build Coastguard Worker 
376*38e8c45fSAndroid Build Coastguard Worker     // VsyncSchedule delegate.
377*38e8c45fSAndroid Build Coastguard Worker     void onHardwareVsyncRequest(PhysicalDisplayId, bool enable);
378*38e8c45fSAndroid Build Coastguard Worker 
379*38e8c45fSAndroid Build Coastguard Worker     void resyncToHardwareVsyncLocked(PhysicalDisplayId, bool allowToEnable,
380*38e8c45fSAndroid Build Coastguard Worker                                      DisplayModePtr modePtr = nullptr)
381*38e8c45fSAndroid Build Coastguard Worker             REQUIRES(kMainThreadContext, mDisplayLock);
382*38e8c45fSAndroid Build Coastguard Worker     void resyncAllToHardwareVsync(bool allowToEnable) EXCLUDES(mDisplayLock);
383*38e8c45fSAndroid Build Coastguard Worker     void setVsyncConfig(const VsyncConfig&, Period vsyncPeriod);
384*38e8c45fSAndroid Build Coastguard Worker 
385*38e8c45fSAndroid Build Coastguard Worker     // TODO: b/241286431 - Remove this option, which assumes that the pacesetter does not change
386*38e8c45fSAndroid Build Coastguard Worker     // when a (secondary) display is registered or unregistered. In the short term, this avoids
387*38e8c45fSAndroid Build Coastguard Worker     // a deadlock where the main thread joins with the timer thread as the timer thread waits to
388*38e8c45fSAndroid Build Coastguard Worker     // lock a mutex held by the main thread.
389*38e8c45fSAndroid Build Coastguard Worker     struct PromotionParams {
390*38e8c45fSAndroid Build Coastguard Worker         // Whether to stop and start the idle timer. Ignored unless connected_display flag is set.
391*38e8c45fSAndroid Build Coastguard Worker         bool toggleIdleTimer;
392*38e8c45fSAndroid Build Coastguard Worker     };
393*38e8c45fSAndroid Build Coastguard Worker 
394*38e8c45fSAndroid Build Coastguard Worker     void promotePacesetterDisplay(PhysicalDisplayId pacesetterId, PromotionParams)
395*38e8c45fSAndroid Build Coastguard Worker             REQUIRES(kMainThreadContext) EXCLUDES(mDisplayLock);
396*38e8c45fSAndroid Build Coastguard Worker 
397*38e8c45fSAndroid Build Coastguard Worker     // Changes to the displays (e.g. registering and unregistering) must be made
398*38e8c45fSAndroid Build Coastguard Worker     // while mDisplayLock is locked, and the new pacesetter then must be promoted while
399*38e8c45fSAndroid Build Coastguard Worker     // mDisplayLock is still locked. However, a new pacesetter means that
400*38e8c45fSAndroid Build Coastguard Worker     // MessageQueue and EventThread need to use the new pacesetter's
401*38e8c45fSAndroid Build Coastguard Worker     // VsyncSchedule, and this must happen while mDisplayLock is *not* locked,
402*38e8c45fSAndroid Build Coastguard Worker     // or else we may deadlock with EventThread.
403*38e8c45fSAndroid Build Coastguard Worker     std::shared_ptr<VsyncSchedule> promotePacesetterDisplayLocked(PhysicalDisplayId pacesetterId,
404*38e8c45fSAndroid Build Coastguard Worker                                                                   PromotionParams)
405*38e8c45fSAndroid Build Coastguard Worker             REQUIRES(kMainThreadContext, mDisplayLock);
406*38e8c45fSAndroid Build Coastguard Worker     void applyNewVsyncSchedule(std::shared_ptr<VsyncSchedule>) EXCLUDES(mDisplayLock);
407*38e8c45fSAndroid Build Coastguard Worker 
408*38e8c45fSAndroid Build Coastguard Worker     // If toggleIdleTimer is true, the calling thread blocks until the pacesetter's idle timer
409*38e8c45fSAndroid Build Coastguard Worker     // thread exits, in which case mDisplayLock must not be locked by the caller to avoid deadlock,
410*38e8c45fSAndroid Build Coastguard Worker     // since the timer thread locks it before exit.
411*38e8c45fSAndroid Build Coastguard Worker     void demotePacesetterDisplay(PromotionParams) REQUIRES(kMainThreadContext)
412*38e8c45fSAndroid Build Coastguard Worker             EXCLUDES(mDisplayLock, mPolicyLock);
413*38e8c45fSAndroid Build Coastguard Worker 
414*38e8c45fSAndroid Build Coastguard Worker     void registerDisplayInternal(PhysicalDisplayId, RefreshRateSelectorPtr, VsyncSchedulePtr,
415*38e8c45fSAndroid Build Coastguard Worker                                  PhysicalDisplayId activeDisplayId) REQUIRES(kMainThreadContext)
416*38e8c45fSAndroid Build Coastguard Worker             EXCLUDES(mDisplayLock);
417*38e8c45fSAndroid Build Coastguard Worker 
418*38e8c45fSAndroid Build Coastguard Worker     struct Policy;
419*38e8c45fSAndroid Build Coastguard Worker 
420*38e8c45fSAndroid Build Coastguard Worker     // Sets the S state of the policy to the T value under mPolicyLock, and chooses a display mode
421*38e8c45fSAndroid Build Coastguard Worker     // that fulfills the new policy if the state changed. Returns the signals that were considered.
422*38e8c45fSAndroid Build Coastguard Worker     template <typename S, typename T>
423*38e8c45fSAndroid Build Coastguard Worker     GlobalSignals applyPolicy(S Policy::*, T&&) EXCLUDES(mPolicyLock);
424*38e8c45fSAndroid Build Coastguard Worker 
425*38e8c45fSAndroid Build Coastguard Worker     struct DisplayModeChoice {
DisplayModeChoiceDisplayModeChoice426*38e8c45fSAndroid Build Coastguard Worker         DisplayModeChoice(FrameRateMode mode, GlobalSignals consideredSignals)
427*38e8c45fSAndroid Build Coastguard Worker               : mode(std::move(mode)), consideredSignals(consideredSignals) {}
428*38e8c45fSAndroid Build Coastguard Worker 
fromDisplayModeChoice429*38e8c45fSAndroid Build Coastguard Worker         static DisplayModeChoice from(RefreshRateSelector::RankedFrameRates rankedFrameRates) {
430*38e8c45fSAndroid Build Coastguard Worker             return {rankedFrameRates.ranking.front().frameRateMode,
431*38e8c45fSAndroid Build Coastguard Worker                     rankedFrameRates.consideredSignals};
432*38e8c45fSAndroid Build Coastguard Worker         }
433*38e8c45fSAndroid Build Coastguard Worker 
434*38e8c45fSAndroid Build Coastguard Worker         FrameRateMode mode;
435*38e8c45fSAndroid Build Coastguard Worker         GlobalSignals consideredSignals;
436*38e8c45fSAndroid Build Coastguard Worker 
437*38e8c45fSAndroid Build Coastguard Worker         bool operator==(const DisplayModeChoice& other) const {
438*38e8c45fSAndroid Build Coastguard Worker             return mode == other.mode && consideredSignals == other.consideredSignals;
439*38e8c45fSAndroid Build Coastguard Worker         }
440*38e8c45fSAndroid Build Coastguard Worker 
441*38e8c45fSAndroid Build Coastguard Worker         // For tests.
442*38e8c45fSAndroid Build Coastguard Worker         friend std::ostream& operator<<(std::ostream& stream, const DisplayModeChoice& choice) {
443*38e8c45fSAndroid Build Coastguard Worker             return stream << '{' << to_string(*choice.mode.modePtr) << " considering "
444*38e8c45fSAndroid Build Coastguard Worker                           << choice.consideredSignals.toString().c_str() << '}';
445*38e8c45fSAndroid Build Coastguard Worker         }
446*38e8c45fSAndroid Build Coastguard Worker     };
447*38e8c45fSAndroid Build Coastguard Worker 
448*38e8c45fSAndroid Build Coastguard Worker     using DisplayModeChoiceMap = ui::PhysicalDisplayMap<PhysicalDisplayId, DisplayModeChoice>;
449*38e8c45fSAndroid Build Coastguard Worker 
450*38e8c45fSAndroid Build Coastguard Worker     // See mDisplayLock for thread safety.
451*38e8c45fSAndroid Build Coastguard Worker     DisplayModeChoiceMap chooseDisplayModes() const
452*38e8c45fSAndroid Build Coastguard Worker             REQUIRES(mPolicyLock, mDisplayLock, kMainThreadContext);
453*38e8c45fSAndroid Build Coastguard Worker 
454*38e8c45fSAndroid Build Coastguard Worker     GlobalSignals makeGlobalSignals() const REQUIRES(mPolicyLock);
455*38e8c45fSAndroid Build Coastguard Worker 
456*38e8c45fSAndroid Build Coastguard Worker     bool updateFrameRateOverridesLocked(GlobalSignals, Fps displayRefreshRate)
457*38e8c45fSAndroid Build Coastguard Worker             REQUIRES(mPolicyLock);
458*38e8c45fSAndroid Build Coastguard Worker 
459*38e8c45fSAndroid Build Coastguard Worker     void onFrameRateOverridesChanged();
460*38e8c45fSAndroid Build Coastguard Worker 
461*38e8c45fSAndroid Build Coastguard Worker     void updateAttachedChoreographers(const surfaceflinger::frontend::LayerHierarchy&,
462*38e8c45fSAndroid Build Coastguard Worker                                       Fps displayRefreshRate);
463*38e8c45fSAndroid Build Coastguard Worker     int updateAttachedChoreographersInternal(const surfaceflinger::frontend::LayerHierarchy&,
464*38e8c45fSAndroid Build Coastguard Worker                                              Fps displayRefreshRate, int parentDivisor);
465*38e8c45fSAndroid Build Coastguard Worker     void updateAttachedChoreographersFrameRate(const surfaceflinger::frontend::RequestedLayerState&,
466*38e8c45fSAndroid Build Coastguard Worker                                                Fps fps) EXCLUDES(mChoreographerLock);
467*38e8c45fSAndroid Build Coastguard Worker 
468*38e8c45fSAndroid Build Coastguard Worker     void emitModeChangeIfNeeded() REQUIRES(mPolicyLock) EXCLUDES(mDisplayLock);
469*38e8c45fSAndroid Build Coastguard Worker 
470*38e8c45fSAndroid Build Coastguard Worker     // IEventThreadCallback overrides
471*38e8c45fSAndroid Build Coastguard Worker     bool throttleVsync(TimePoint, uid_t) override;
472*38e8c45fSAndroid Build Coastguard Worker     // Get frame interval
473*38e8c45fSAndroid Build Coastguard Worker     Period getVsyncPeriod(uid_t) override EXCLUDES(mDisplayLock);
474*38e8c45fSAndroid Build Coastguard Worker     void onExpectedPresentTimePosted(TimePoint expectedPresentTime) override EXCLUDES(mDisplayLock);
475*38e8c45fSAndroid Build Coastguard Worker 
476*38e8c45fSAndroid Build Coastguard Worker     std::unique_ptr<EventThread> mRenderEventThread;
477*38e8c45fSAndroid Build Coastguard Worker     std::unique_ptr<EventThread> mLastCompositeEventThread;
478*38e8c45fSAndroid Build Coastguard Worker 
479*38e8c45fSAndroid Build Coastguard Worker     std::atomic<nsecs_t> mLastResyncTime = 0;
480*38e8c45fSAndroid Build Coastguard Worker 
481*38e8c45fSAndroid Build Coastguard Worker     const FeatureFlags mFeatures;
482*38e8c45fSAndroid Build Coastguard Worker 
483*38e8c45fSAndroid Build Coastguard Worker     // Stores phase offsets configured per refresh rate.
484*38e8c45fSAndroid Build Coastguard Worker     const std::unique_ptr<VsyncConfiguration> mVsyncConfiguration;
485*38e8c45fSAndroid Build Coastguard Worker 
486*38e8c45fSAndroid Build Coastguard Worker     // Shifts the VSYNC phase during certain transactions and refresh rate changes.
487*38e8c45fSAndroid Build Coastguard Worker     const sp<VsyncModulator> mVsyncModulator;
488*38e8c45fSAndroid Build Coastguard Worker 
489*38e8c45fSAndroid Build Coastguard Worker     const std::unique_ptr<RefreshRateStats> mRefreshRateStats;
490*38e8c45fSAndroid Build Coastguard Worker 
491*38e8c45fSAndroid Build Coastguard Worker     // Used to choose refresh rate if content detection is enabled.
492*38e8c45fSAndroid Build Coastguard Worker     LayerHistory mLayerHistory;
493*38e8c45fSAndroid Build Coastguard Worker 
494*38e8c45fSAndroid Build Coastguard Worker     // Timer used to monitor touch events.
495*38e8c45fSAndroid Build Coastguard Worker     ftl::Optional<OneShotTimer> mTouchTimer;
496*38e8c45fSAndroid Build Coastguard Worker     // Timer used to monitor display power mode.
497*38e8c45fSAndroid Build Coastguard Worker     ftl::Optional<OneShotTimer> mDisplayPowerTimer;
498*38e8c45fSAndroid Build Coastguard Worker 
499*38e8c45fSAndroid Build Coastguard Worker     // Injected delay prior to compositing, for simulating jank.
500*38e8c45fSAndroid Build Coastguard Worker     float mPacesetterFrameDurationFractionToSkip GUARDED_BY(kMainThreadContext) = 0.f;
501*38e8c45fSAndroid Build Coastguard Worker 
502*38e8c45fSAndroid Build Coastguard Worker     ISchedulerCallback& mSchedulerCallback;
503*38e8c45fSAndroid Build Coastguard Worker 
504*38e8c45fSAndroid Build Coastguard Worker     // mDisplayLock may be locked while under mPolicyLock.
505*38e8c45fSAndroid Build Coastguard Worker     mutable std::mutex mPolicyLock;
506*38e8c45fSAndroid Build Coastguard Worker 
507*38e8c45fSAndroid Build Coastguard Worker     // Only required for reads outside kMainThreadContext. kMainThreadContext is the only writer, so
508*38e8c45fSAndroid Build Coastguard Worker     // must lock for writes but not reads. See also mPolicyLock for locking order.
509*38e8c45fSAndroid Build Coastguard Worker     mutable std::mutex mDisplayLock;
510*38e8c45fSAndroid Build Coastguard Worker 
511*38e8c45fSAndroid Build Coastguard Worker     using FrameTargeterPtr = std::unique_ptr<FrameTargeter>;
512*38e8c45fSAndroid Build Coastguard Worker 
513*38e8c45fSAndroid Build Coastguard Worker     struct Display {
DisplayDisplay514*38e8c45fSAndroid Build Coastguard Worker         Display(PhysicalDisplayId displayId, RefreshRateSelectorPtr selectorPtr,
515*38e8c45fSAndroid Build Coastguard Worker                 VsyncSchedulePtr schedulePtr, FeatureFlags features)
516*38e8c45fSAndroid Build Coastguard Worker               : displayId(displayId),
517*38e8c45fSAndroid Build Coastguard Worker                 selectorPtr(std::move(selectorPtr)),
518*38e8c45fSAndroid Build Coastguard Worker                 schedulePtr(std::move(schedulePtr)),
519*38e8c45fSAndroid Build Coastguard Worker                 targeterPtr(std::make_unique<FrameTargeter>(displayId, features)) {}
520*38e8c45fSAndroid Build Coastguard Worker 
521*38e8c45fSAndroid Build Coastguard Worker         const PhysicalDisplayId displayId;
522*38e8c45fSAndroid Build Coastguard Worker 
523*38e8c45fSAndroid Build Coastguard Worker         // Effectively const except in move constructor.
524*38e8c45fSAndroid Build Coastguard Worker         RefreshRateSelectorPtr selectorPtr;
525*38e8c45fSAndroid Build Coastguard Worker         VsyncSchedulePtr schedulePtr;
526*38e8c45fSAndroid Build Coastguard Worker         FrameTargeterPtr targeterPtr;
527*38e8c45fSAndroid Build Coastguard Worker 
528*38e8c45fSAndroid Build Coastguard Worker         hal::PowerMode powerMode = hal::PowerMode::OFF;
529*38e8c45fSAndroid Build Coastguard Worker     };
530*38e8c45fSAndroid Build Coastguard Worker 
531*38e8c45fSAndroid Build Coastguard Worker     using DisplayRef = std::reference_wrapper<Display>;
532*38e8c45fSAndroid Build Coastguard Worker     using ConstDisplayRef = std::reference_wrapper<const Display>;
533*38e8c45fSAndroid Build Coastguard Worker 
534*38e8c45fSAndroid Build Coastguard Worker     ui::PhysicalDisplayMap<PhysicalDisplayId, Display> mDisplays GUARDED_BY(mDisplayLock)
535*38e8c45fSAndroid Build Coastguard Worker             GUARDED_BY(kMainThreadContext);
536*38e8c45fSAndroid Build Coastguard Worker 
537*38e8c45fSAndroid Build Coastguard Worker     ftl::Optional<PhysicalDisplayId> mPacesetterDisplayId GUARDED_BY(mDisplayLock)
538*38e8c45fSAndroid Build Coastguard Worker             GUARDED_BY(kMainThreadContext);
539*38e8c45fSAndroid Build Coastguard Worker 
pacesetterDisplayLocked()540*38e8c45fSAndroid Build Coastguard Worker     ftl::Optional<DisplayRef> pacesetterDisplayLocked() REQUIRES(mDisplayLock) {
541*38e8c45fSAndroid Build Coastguard Worker         return static_cast<const Scheduler*>(this)->pacesetterDisplayLocked().transform(
542*38e8c45fSAndroid Build Coastguard Worker                 [](const Display& display) { return std::ref(const_cast<Display&>(display)); });
543*38e8c45fSAndroid Build Coastguard Worker     }
544*38e8c45fSAndroid Build Coastguard Worker 
pacesetterDisplayLocked()545*38e8c45fSAndroid Build Coastguard Worker     ftl::Optional<ConstDisplayRef> pacesetterDisplayLocked() const REQUIRES(mDisplayLock) {
546*38e8c45fSAndroid Build Coastguard Worker         ftl::FakeGuard guard(kMainThreadContext);
547*38e8c45fSAndroid Build Coastguard Worker         return mPacesetterDisplayId.and_then([this](PhysicalDisplayId pacesetterId)
548*38e8c45fSAndroid Build Coastguard Worker                                                      REQUIRES(mDisplayLock, kMainThreadContext) {
549*38e8c45fSAndroid Build Coastguard Worker                                                          return mDisplays.get(pacesetterId);
550*38e8c45fSAndroid Build Coastguard Worker                                                      });
551*38e8c45fSAndroid Build Coastguard Worker     }
552*38e8c45fSAndroid Build Coastguard Worker 
553*38e8c45fSAndroid Build Coastguard Worker     // The pacesetter must exist as a precondition.
pacesetterPtrLocked()554*38e8c45fSAndroid Build Coastguard Worker     ftl::NonNull<const Display*> pacesetterPtrLocked() const REQUIRES(mDisplayLock) {
555*38e8c45fSAndroid Build Coastguard Worker         return ftl::as_non_null(&pacesetterDisplayLocked()->get());
556*38e8c45fSAndroid Build Coastguard Worker     }
557*38e8c45fSAndroid Build Coastguard Worker 
pacesetterSelectorPtr()558*38e8c45fSAndroid Build Coastguard Worker     RefreshRateSelectorPtr pacesetterSelectorPtr() const EXCLUDES(mDisplayLock) {
559*38e8c45fSAndroid Build Coastguard Worker         std::scoped_lock lock(mDisplayLock);
560*38e8c45fSAndroid Build Coastguard Worker         return pacesetterSelectorPtrLocked();
561*38e8c45fSAndroid Build Coastguard Worker     }
562*38e8c45fSAndroid Build Coastguard Worker 
pacesetterSelectorPtrLocked()563*38e8c45fSAndroid Build Coastguard Worker     RefreshRateSelectorPtr pacesetterSelectorPtrLocked() const REQUIRES(mDisplayLock) {
564*38e8c45fSAndroid Build Coastguard Worker         return pacesetterDisplayLocked()
565*38e8c45fSAndroid Build Coastguard Worker                 .transform([](const Display& display) { return display.selectorPtr; })
566*38e8c45fSAndroid Build Coastguard Worker                 .or_else([] { return std::optional<RefreshRateSelectorPtr>(nullptr); })
567*38e8c45fSAndroid Build Coastguard Worker                 .value();
568*38e8c45fSAndroid Build Coastguard Worker     }
569*38e8c45fSAndroid Build Coastguard Worker 
570*38e8c45fSAndroid Build Coastguard Worker     ConstVsyncSchedulePtr getVsyncScheduleLocked(
571*38e8c45fSAndroid Build Coastguard Worker             std::optional<PhysicalDisplayId> = std::nullopt) const REQUIRES(mDisplayLock);
572*38e8c45fSAndroid Build Coastguard Worker 
573*38e8c45fSAndroid Build Coastguard Worker     VsyncSchedulePtr getVsyncScheduleLocked(std::optional<PhysicalDisplayId> idOpt = std::nullopt)
REQUIRES(mDisplayLock)574*38e8c45fSAndroid Build Coastguard Worker             REQUIRES(mDisplayLock) {
575*38e8c45fSAndroid Build Coastguard Worker         return std::const_pointer_cast<VsyncSchedule>(
576*38e8c45fSAndroid Build Coastguard Worker                 static_cast<const Scheduler*>(this)->getVsyncScheduleLocked(idOpt));
577*38e8c45fSAndroid Build Coastguard Worker     }
578*38e8c45fSAndroid Build Coastguard Worker 
579*38e8c45fSAndroid Build Coastguard Worker     struct Policy {
580*38e8c45fSAndroid Build Coastguard Worker         // Policy for choosing the display mode.
581*38e8c45fSAndroid Build Coastguard Worker         LayerHistory::Summary contentRequirements;
582*38e8c45fSAndroid Build Coastguard Worker         TimerState idleTimer = TimerState::Reset;
583*38e8c45fSAndroid Build Coastguard Worker         TouchState touch = TouchState::Inactive;
584*38e8c45fSAndroid Build Coastguard Worker         TimerState displayPowerTimer = TimerState::Expired;
585*38e8c45fSAndroid Build Coastguard Worker         hal::PowerMode displayPowerMode = hal::PowerMode::ON;
586*38e8c45fSAndroid Build Coastguard Worker 
587*38e8c45fSAndroid Build Coastguard Worker         // Chosen display mode.
588*38e8c45fSAndroid Build Coastguard Worker         ftl::Optional<FrameRateMode> modeOpt;
589*38e8c45fSAndroid Build Coastguard Worker 
590*38e8c45fSAndroid Build Coastguard Worker         // Display mode of latest emitted event.
591*38e8c45fSAndroid Build Coastguard Worker         std::optional<FrameRateMode> emittedModeOpt;
592*38e8c45fSAndroid Build Coastguard Worker     } mPolicy GUARDED_BY(mPolicyLock);
593*38e8c45fSAndroid Build Coastguard Worker 
594*38e8c45fSAndroid Build Coastguard Worker     std::mutex mChoreographerLock;
595*38e8c45fSAndroid Build Coastguard Worker 
596*38e8c45fSAndroid Build Coastguard Worker     struct AttachedChoreographers {
597*38e8c45fSAndroid Build Coastguard Worker         Fps frameRate;
598*38e8c45fSAndroid Build Coastguard Worker         std::unordered_set<wp<EventThreadConnection>, WpHash> connections;
599*38e8c45fSAndroid Build Coastguard Worker     };
600*38e8c45fSAndroid Build Coastguard Worker     // Map keyed by layer ID (sequence) to choreographer connections.
601*38e8c45fSAndroid Build Coastguard Worker     std::unordered_map<int32_t, AttachedChoreographers> mAttachedChoreographers
602*38e8c45fSAndroid Build Coastguard Worker             GUARDED_BY(mChoreographerLock);
603*38e8c45fSAndroid Build Coastguard Worker 
604*38e8c45fSAndroid Build Coastguard Worker     std::mutex mVsyncTimelineLock;
605*38e8c45fSAndroid Build Coastguard Worker     std::optional<hal::VsyncPeriodChangeTimeline> mLastVsyncPeriodChangeTimeline
606*38e8c45fSAndroid Build Coastguard Worker             GUARDED_BY(mVsyncTimelineLock);
607*38e8c45fSAndroid Build Coastguard Worker     static constexpr std::chrono::nanoseconds MAX_VSYNC_APPLIED_TIME = 200ms;
608*38e8c45fSAndroid Build Coastguard Worker 
609*38e8c45fSAndroid Build Coastguard Worker     FrameRateOverrideMappings mFrameRateOverrideMappings;
610*38e8c45fSAndroid Build Coastguard Worker     SmallAreaDetectionAllowMappings mSmallAreaDetectionAllowMappings;
611*38e8c45fSAndroid Build Coastguard Worker 
612*38e8c45fSAndroid Build Coastguard Worker     std::atomic<std::optional<TimePoint>> mDebugPresentDelay;
613*38e8c45fSAndroid Build Coastguard Worker };
614*38e8c45fSAndroid Build Coastguard Worker 
615*38e8c45fSAndroid Build Coastguard Worker } // namespace scheduler
616*38e8c45fSAndroid Build Coastguard Worker } // namespace android
617