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