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