xref: /aosp_15_r20/frameworks/native/services/surfaceflinger/Display/DisplayModeController.h (revision 38e8c45f13ce32b0dcecb25141ffecaf386fa17f)
1*38e8c45fSAndroid Build Coastguard Worker /*
2*38e8c45fSAndroid Build Coastguard Worker  * Copyright 2024 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 <memory>
20*38e8c45fSAndroid Build Coastguard Worker #include <mutex>
21*38e8c45fSAndroid Build Coastguard Worker #include <string>
22*38e8c45fSAndroid Build Coastguard Worker #include <utility>
23*38e8c45fSAndroid Build Coastguard Worker 
24*38e8c45fSAndroid Build Coastguard Worker #include <android-base/thread_annotations.h>
25*38e8c45fSAndroid Build Coastguard Worker #include <ftl/function.h>
26*38e8c45fSAndroid Build Coastguard Worker #include <ftl/optional.h>
27*38e8c45fSAndroid Build Coastguard Worker #include <ui/DisplayId.h>
28*38e8c45fSAndroid Build Coastguard Worker #include <ui/DisplayMap.h>
29*38e8c45fSAndroid Build Coastguard Worker 
30*38e8c45fSAndroid Build Coastguard Worker #include "Display/DisplayModeRequest.h"
31*38e8c45fSAndroid Build Coastguard Worker #include "Display/DisplaySnapshotRef.h"
32*38e8c45fSAndroid Build Coastguard Worker #include "DisplayHardware/DisplayMode.h"
33*38e8c45fSAndroid Build Coastguard Worker #include "Scheduler/RefreshRateSelector.h"
34*38e8c45fSAndroid Build Coastguard Worker #include "ThreadContext.h"
35*38e8c45fSAndroid Build Coastguard Worker #include "TracedOrdinal.h"
36*38e8c45fSAndroid Build Coastguard Worker 
37*38e8c45fSAndroid Build Coastguard Worker namespace android {
38*38e8c45fSAndroid Build Coastguard Worker class HWComposer;
39*38e8c45fSAndroid Build Coastguard Worker } // namespace android
40*38e8c45fSAndroid Build Coastguard Worker 
41*38e8c45fSAndroid Build Coastguard Worker namespace android::display {
42*38e8c45fSAndroid Build Coastguard Worker 
43*38e8c45fSAndroid Build Coastguard Worker // Selects the DisplayMode of each physical display, in accordance with DisplayManager policy and
44*38e8c45fSAndroid Build Coastguard Worker // certain heuristic signals.
45*38e8c45fSAndroid Build Coastguard Worker class DisplayModeController {
46*38e8c45fSAndroid Build Coastguard Worker public:
47*38e8c45fSAndroid Build Coastguard Worker     using ActiveModeListener = ftl::Function<void(PhysicalDisplayId, Fps vsyncRate, Fps renderFps)>;
48*38e8c45fSAndroid Build Coastguard Worker 
49*38e8c45fSAndroid Build Coastguard Worker     DisplayModeController() = default;
50*38e8c45fSAndroid Build Coastguard Worker 
setHwComposer(HWComposer * composerPtr)51*38e8c45fSAndroid Build Coastguard Worker     void setHwComposer(HWComposer* composerPtr) { mComposerPtr = composerPtr; }
setActiveModeListener(const ActiveModeListener & listener)52*38e8c45fSAndroid Build Coastguard Worker     void setActiveModeListener(const ActiveModeListener& listener) {
53*38e8c45fSAndroid Build Coastguard Worker         mActiveModeListener = listener;
54*38e8c45fSAndroid Build Coastguard Worker     }
55*38e8c45fSAndroid Build Coastguard Worker 
56*38e8c45fSAndroid Build Coastguard Worker     // TODO: b/241285876 - Remove once ownership is no longer shared with DisplayDevice.
57*38e8c45fSAndroid Build Coastguard Worker     using RefreshRateSelectorPtr = std::shared_ptr<scheduler::RefreshRateSelector>;
58*38e8c45fSAndroid Build Coastguard Worker 
59*38e8c45fSAndroid Build Coastguard Worker     // Used by tests to inject an existing RefreshRateSelector.
60*38e8c45fSAndroid Build Coastguard Worker     // TODO: b/241285876 - Remove this.
61*38e8c45fSAndroid Build Coastguard Worker     void registerDisplay(PhysicalDisplayId, DisplaySnapshotRef, RefreshRateSelectorPtr)
62*38e8c45fSAndroid Build Coastguard Worker             EXCLUDES(mDisplayLock);
63*38e8c45fSAndroid Build Coastguard Worker 
64*38e8c45fSAndroid Build Coastguard Worker     // The referenced DisplaySnapshot must outlive the registration.
65*38e8c45fSAndroid Build Coastguard Worker     void registerDisplay(DisplaySnapshotRef, DisplayModeId, scheduler::RefreshRateSelector::Config)
66*38e8c45fSAndroid Build Coastguard Worker             REQUIRES(kMainThreadContext) EXCLUDES(mDisplayLock);
67*38e8c45fSAndroid Build Coastguard Worker     void unregisterDisplay(PhysicalDisplayId) REQUIRES(kMainThreadContext) EXCLUDES(mDisplayLock);
68*38e8c45fSAndroid Build Coastguard Worker 
69*38e8c45fSAndroid Build Coastguard Worker     // Returns `nullptr` if the display is no longer registered (or never was).
70*38e8c45fSAndroid Build Coastguard Worker     RefreshRateSelectorPtr selectorPtrFor(PhysicalDisplayId) const EXCLUDES(mDisplayLock);
71*38e8c45fSAndroid Build Coastguard Worker 
72*38e8c45fSAndroid Build Coastguard Worker     enum class DesiredModeAction { None, InitiateDisplayModeSwitch, InitiateRenderRateSwitch };
73*38e8c45fSAndroid Build Coastguard Worker     enum class ModeChangeResult { Changed, Rejected, Aborted };
74*38e8c45fSAndroid Build Coastguard Worker 
75*38e8c45fSAndroid Build Coastguard Worker     DesiredModeAction setDesiredMode(PhysicalDisplayId, DisplayModeRequest&&)
76*38e8c45fSAndroid Build Coastguard Worker             EXCLUDES(mDisplayLock);
77*38e8c45fSAndroid Build Coastguard Worker 
78*38e8c45fSAndroid Build Coastguard Worker     using DisplayModeRequestOpt = ftl::Optional<DisplayModeRequest>;
79*38e8c45fSAndroid Build Coastguard Worker 
80*38e8c45fSAndroid Build Coastguard Worker     DisplayModeRequestOpt getDesiredMode(PhysicalDisplayId) const EXCLUDES(mDisplayLock);
81*38e8c45fSAndroid Build Coastguard Worker     void clearDesiredMode(PhysicalDisplayId) EXCLUDES(mDisplayLock);
82*38e8c45fSAndroid Build Coastguard Worker 
83*38e8c45fSAndroid Build Coastguard Worker     DisplayModeRequestOpt getPendingMode(PhysicalDisplayId) const REQUIRES(kMainThreadContext)
84*38e8c45fSAndroid Build Coastguard Worker             EXCLUDES(mDisplayLock);
85*38e8c45fSAndroid Build Coastguard Worker     bool isModeSetPending(PhysicalDisplayId) const REQUIRES(kMainThreadContext)
86*38e8c45fSAndroid Build Coastguard Worker             EXCLUDES(mDisplayLock);
87*38e8c45fSAndroid Build Coastguard Worker 
88*38e8c45fSAndroid Build Coastguard Worker     scheduler::FrameRateMode getActiveMode(PhysicalDisplayId) const EXCLUDES(mDisplayLock);
89*38e8c45fSAndroid Build Coastguard Worker 
90*38e8c45fSAndroid Build Coastguard Worker     ModeChangeResult initiateModeChange(PhysicalDisplayId, DisplayModeRequest&&,
91*38e8c45fSAndroid Build Coastguard Worker                                         const hal::VsyncPeriodChangeConstraints&,
92*38e8c45fSAndroid Build Coastguard Worker                                         hal::VsyncPeriodChangeTimeline& outTimeline)
93*38e8c45fSAndroid Build Coastguard Worker             REQUIRES(kMainThreadContext) EXCLUDES(mDisplayLock);
94*38e8c45fSAndroid Build Coastguard Worker 
95*38e8c45fSAndroid Build Coastguard Worker     void finalizeModeChange(PhysicalDisplayId, DisplayModeId, Fps vsyncRate, Fps renderFps)
96*38e8c45fSAndroid Build Coastguard Worker             REQUIRES(kMainThreadContext) EXCLUDES(mDisplayLock);
97*38e8c45fSAndroid Build Coastguard Worker 
98*38e8c45fSAndroid Build Coastguard Worker     void setActiveMode(PhysicalDisplayId, DisplayModeId, Fps vsyncRate, Fps renderFps)
99*38e8c45fSAndroid Build Coastguard Worker             EXCLUDES(mDisplayLock);
100*38e8c45fSAndroid Build Coastguard Worker 
101*38e8c45fSAndroid Build Coastguard Worker     void updateKernelIdleTimer(PhysicalDisplayId) REQUIRES(kMainThreadContext)
102*38e8c45fSAndroid Build Coastguard Worker             EXCLUDES(mDisplayLock);
103*38e8c45fSAndroid Build Coastguard Worker 
104*38e8c45fSAndroid Build Coastguard Worker     struct KernelIdleTimerState {
105*38e8c45fSAndroid Build Coastguard Worker         std::optional<DisplayModeId> desiredModeIdOpt = std::nullopt;
106*38e8c45fSAndroid Build Coastguard Worker         bool isEnabled = false;
107*38e8c45fSAndroid Build Coastguard Worker     };
108*38e8c45fSAndroid Build Coastguard Worker 
109*38e8c45fSAndroid Build Coastguard Worker     KernelIdleTimerState getKernelIdleTimerState(PhysicalDisplayId) const
110*38e8c45fSAndroid Build Coastguard Worker             REQUIRES(kMainThreadContext) EXCLUDES(mDisplayLock);
111*38e8c45fSAndroid Build Coastguard Worker 
112*38e8c45fSAndroid Build Coastguard Worker private:
113*38e8c45fSAndroid Build Coastguard Worker     struct Display {
114*38e8c45fSAndroid Build Coastguard Worker         template <size_t N>
115*38e8c45fSAndroid Build Coastguard Worker         std::string concatId(const char (&)[N]) const;
116*38e8c45fSAndroid Build Coastguard Worker 
117*38e8c45fSAndroid Build Coastguard Worker         Display(DisplaySnapshotRef, RefreshRateSelectorPtr);
DisplayDisplay118*38e8c45fSAndroid Build Coastguard Worker         Display(DisplaySnapshotRef snapshot, DisplayModes modes, DisplayModeId activeModeId,
119*38e8c45fSAndroid Build Coastguard Worker                 scheduler::RefreshRateSelector::Config config)
120*38e8c45fSAndroid Build Coastguard Worker               : Display(snapshot,
121*38e8c45fSAndroid Build Coastguard Worker                         std::make_shared<scheduler::RefreshRateSelector>(std::move(modes),
122*38e8c45fSAndroid Build Coastguard Worker                                                                          activeModeId, config)) {}
123*38e8c45fSAndroid Build Coastguard Worker         const DisplaySnapshotRef snapshot;
124*38e8c45fSAndroid Build Coastguard Worker         const RefreshRateSelectorPtr selectorPtr;
125*38e8c45fSAndroid Build Coastguard Worker 
126*38e8c45fSAndroid Build Coastguard Worker         const std::string pendingModeFpsTrace;
127*38e8c45fSAndroid Build Coastguard Worker         const std::string activeModeFpsTrace;
128*38e8c45fSAndroid Build Coastguard Worker         const std::string renderRateFpsTrace;
129*38e8c45fSAndroid Build Coastguard Worker 
130*38e8c45fSAndroid Build Coastguard Worker         std::mutex desiredModeLock;
131*38e8c45fSAndroid Build Coastguard Worker         DisplayModeRequestOpt desiredModeOpt GUARDED_BY(desiredModeLock);
132*38e8c45fSAndroid Build Coastguard Worker         TracedOrdinal<bool> hasDesiredModeTrace GUARDED_BY(desiredModeLock);
133*38e8c45fSAndroid Build Coastguard Worker 
134*38e8c45fSAndroid Build Coastguard Worker         DisplayModeRequestOpt pendingModeOpt GUARDED_BY(kMainThreadContext);
135*38e8c45fSAndroid Build Coastguard Worker         bool isModeSetPending GUARDED_BY(kMainThreadContext) = false;
136*38e8c45fSAndroid Build Coastguard Worker 
137*38e8c45fSAndroid Build Coastguard Worker         bool isKernelIdleTimerEnabled GUARDED_BY(kMainThreadContext) = false;
138*38e8c45fSAndroid Build Coastguard Worker     };
139*38e8c45fSAndroid Build Coastguard Worker 
140*38e8c45fSAndroid Build Coastguard Worker     using DisplayPtr = std::unique_ptr<Display>;
141*38e8c45fSAndroid Build Coastguard Worker 
142*38e8c45fSAndroid Build Coastguard Worker     void setActiveModeLocked(PhysicalDisplayId, DisplayModeId, Fps vsyncRate, Fps renderFps)
143*38e8c45fSAndroid Build Coastguard Worker             REQUIRES(mDisplayLock);
144*38e8c45fSAndroid Build Coastguard Worker 
145*38e8c45fSAndroid Build Coastguard Worker     using KernelIdleTimerController = scheduler::RefreshRateSelector::KernelIdleTimerController;
146*38e8c45fSAndroid Build Coastguard Worker     void updateKernelIdleTimer(PhysicalDisplayId, std::chrono::milliseconds timeout,
147*38e8c45fSAndroid Build Coastguard Worker                                KernelIdleTimerController) REQUIRES(mDisplayLock);
148*38e8c45fSAndroid Build Coastguard Worker 
149*38e8c45fSAndroid Build Coastguard Worker     // Set once when initializing the DisplayModeController, which the HWComposer must outlive.
150*38e8c45fSAndroid Build Coastguard Worker     HWComposer* mComposerPtr = nullptr;
151*38e8c45fSAndroid Build Coastguard Worker 
152*38e8c45fSAndroid Build Coastguard Worker     ActiveModeListener mActiveModeListener;
153*38e8c45fSAndroid Build Coastguard Worker 
154*38e8c45fSAndroid Build Coastguard Worker     mutable std::mutex mDisplayLock;
155*38e8c45fSAndroid Build Coastguard Worker     ui::PhysicalDisplayMap<PhysicalDisplayId, DisplayPtr> mDisplays GUARDED_BY(mDisplayLock);
156*38e8c45fSAndroid Build Coastguard Worker };
157*38e8c45fSAndroid Build Coastguard Worker 
158*38e8c45fSAndroid Build Coastguard Worker } // namespace android::display
159