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 
74     DesiredModeAction setDesiredMode(PhysicalDisplayId, DisplayModeRequest&&)
75             EXCLUDES(mDisplayLock);
76 
77     using DisplayModeRequestOpt = ftl::Optional<DisplayModeRequest>;
78 
79     DisplayModeRequestOpt getDesiredMode(PhysicalDisplayId) const EXCLUDES(mDisplayLock);
80     void clearDesiredMode(PhysicalDisplayId) EXCLUDES(mDisplayLock);
81 
82     DisplayModeRequestOpt getPendingMode(PhysicalDisplayId) const REQUIRES(kMainThreadContext)
83             EXCLUDES(mDisplayLock);
84     bool isModeSetPending(PhysicalDisplayId) const REQUIRES(kMainThreadContext)
85             EXCLUDES(mDisplayLock);
86 
87     scheduler::FrameRateMode getActiveMode(PhysicalDisplayId) const EXCLUDES(mDisplayLock);
88 
89     bool initiateModeChange(PhysicalDisplayId, DisplayModeRequest&&,
90                             const hal::VsyncPeriodChangeConstraints&,
91                             hal::VsyncPeriodChangeTimeline& outTimeline)
92             REQUIRES(kMainThreadContext) EXCLUDES(mDisplayLock);
93 
94     void finalizeModeChange(PhysicalDisplayId, DisplayModeId, Fps vsyncRate, Fps renderFps)
95             REQUIRES(kMainThreadContext) EXCLUDES(mDisplayLock);
96 
97     void setActiveMode(PhysicalDisplayId, DisplayModeId, Fps vsyncRate, Fps renderFps)
98             EXCLUDES(mDisplayLock);
99 
100 private:
101     struct Display {
102         template <size_t N>
103         std::string concatId(const char (&)[N]) const;
104 
105         Display(DisplaySnapshotRef, RefreshRateSelectorPtr);
DisplayDisplay106         Display(DisplaySnapshotRef snapshot, DisplayModes modes, DisplayModeId activeModeId,
107                 scheduler::RefreshRateSelector::Config config)
108               : Display(snapshot,
109                         std::make_shared<scheduler::RefreshRateSelector>(std::move(modes),
110                                                                          activeModeId, config)) {}
111         const DisplaySnapshotRef snapshot;
112         const RefreshRateSelectorPtr selectorPtr;
113 
114         const std::string pendingModeFpsTrace;
115         const std::string activeModeFpsTrace;
116         const std::string renderRateFpsTrace;
117 
118         std::mutex desiredModeLock;
119         DisplayModeRequestOpt desiredModeOpt GUARDED_BY(desiredModeLock);
120         TracedOrdinal<bool> hasDesiredModeTrace GUARDED_BY(desiredModeLock);
121 
122         DisplayModeRequestOpt pendingModeOpt GUARDED_BY(kMainThreadContext);
123         bool isModeSetPending GUARDED_BY(kMainThreadContext) = false;
124     };
125 
126     using DisplayPtr = std::unique_ptr<Display>;
127 
128     void setActiveModeLocked(PhysicalDisplayId, DisplayModeId, Fps vsyncRate, Fps renderFps)
129             REQUIRES(mDisplayLock);
130 
131     // Set once when initializing the DisplayModeController, which the HWComposer must outlive.
132     HWComposer* mComposerPtr = nullptr;
133 
134     ActiveModeListener mActiveModeListener;
135 
136     mutable std::mutex mDisplayLock;
137     ui::PhysicalDisplayMap<PhysicalDisplayId, DisplayPtr> mDisplays GUARDED_BY(mDisplayLock);
138 };
139 
140 } // namespace android::display
141