/* * Copyright 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #pragma once #include #include #include #include #include #include #include #include #include #include "Display/DisplayModeRequest.h" #include "Display/DisplaySnapshotRef.h" #include "DisplayHardware/DisplayMode.h" #include "Scheduler/RefreshRateSelector.h" #include "ThreadContext.h" #include "TracedOrdinal.h" namespace android { class HWComposer; } // namespace android namespace android::display { // Selects the DisplayMode of each physical display, in accordance with DisplayManager policy and // certain heuristic signals. class DisplayModeController { public: using ActiveModeListener = ftl::Function; DisplayModeController() = default; void setHwComposer(HWComposer* composerPtr) { mComposerPtr = composerPtr; } void setActiveModeListener(const ActiveModeListener& listener) { mActiveModeListener = listener; } // TODO: b/241285876 - Remove once ownership is no longer shared with DisplayDevice. using RefreshRateSelectorPtr = std::shared_ptr; // Used by tests to inject an existing RefreshRateSelector. // TODO: b/241285876 - Remove this. void registerDisplay(PhysicalDisplayId, DisplaySnapshotRef, RefreshRateSelectorPtr) EXCLUDES(mDisplayLock); // The referenced DisplaySnapshot must outlive the registration. void registerDisplay(DisplaySnapshotRef, DisplayModeId, scheduler::RefreshRateSelector::Config) REQUIRES(kMainThreadContext) EXCLUDES(mDisplayLock); void unregisterDisplay(PhysicalDisplayId) REQUIRES(kMainThreadContext) EXCLUDES(mDisplayLock); // Returns `nullptr` if the display is no longer registered (or never was). RefreshRateSelectorPtr selectorPtrFor(PhysicalDisplayId) const EXCLUDES(mDisplayLock); enum class DesiredModeAction { None, InitiateDisplayModeSwitch, InitiateRenderRateSwitch }; enum class ModeChangeResult { Changed, Rejected, Aborted }; DesiredModeAction setDesiredMode(PhysicalDisplayId, DisplayModeRequest&&) EXCLUDES(mDisplayLock); using DisplayModeRequestOpt = ftl::Optional; DisplayModeRequestOpt getDesiredMode(PhysicalDisplayId) const EXCLUDES(mDisplayLock); void clearDesiredMode(PhysicalDisplayId) EXCLUDES(mDisplayLock); DisplayModeRequestOpt getPendingMode(PhysicalDisplayId) const REQUIRES(kMainThreadContext) EXCLUDES(mDisplayLock); bool isModeSetPending(PhysicalDisplayId) const REQUIRES(kMainThreadContext) EXCLUDES(mDisplayLock); scheduler::FrameRateMode getActiveMode(PhysicalDisplayId) const EXCLUDES(mDisplayLock); ModeChangeResult initiateModeChange(PhysicalDisplayId, DisplayModeRequest&&, const hal::VsyncPeriodChangeConstraints&, hal::VsyncPeriodChangeTimeline& outTimeline) REQUIRES(kMainThreadContext) EXCLUDES(mDisplayLock); void finalizeModeChange(PhysicalDisplayId, DisplayModeId, Fps vsyncRate, Fps renderFps) REQUIRES(kMainThreadContext) EXCLUDES(mDisplayLock); void setActiveMode(PhysicalDisplayId, DisplayModeId, Fps vsyncRate, Fps renderFps) EXCLUDES(mDisplayLock); void updateKernelIdleTimer(PhysicalDisplayId) REQUIRES(kMainThreadContext) EXCLUDES(mDisplayLock); struct KernelIdleTimerState { std::optional desiredModeIdOpt = std::nullopt; bool isEnabled = false; }; KernelIdleTimerState getKernelIdleTimerState(PhysicalDisplayId) const REQUIRES(kMainThreadContext) EXCLUDES(mDisplayLock); private: struct Display { template std::string concatId(const char (&)[N]) const; Display(DisplaySnapshotRef, RefreshRateSelectorPtr); Display(DisplaySnapshotRef snapshot, DisplayModes modes, DisplayModeId activeModeId, scheduler::RefreshRateSelector::Config config) : Display(snapshot, std::make_shared(std::move(modes), activeModeId, config)) {} const DisplaySnapshotRef snapshot; const RefreshRateSelectorPtr selectorPtr; const std::string pendingModeFpsTrace; const std::string activeModeFpsTrace; const std::string renderRateFpsTrace; std::mutex desiredModeLock; DisplayModeRequestOpt desiredModeOpt GUARDED_BY(desiredModeLock); TracedOrdinal hasDesiredModeTrace GUARDED_BY(desiredModeLock); DisplayModeRequestOpt pendingModeOpt GUARDED_BY(kMainThreadContext); bool isModeSetPending GUARDED_BY(kMainThreadContext) = false; bool isKernelIdleTimerEnabled GUARDED_BY(kMainThreadContext) = false; }; using DisplayPtr = std::unique_ptr; void setActiveModeLocked(PhysicalDisplayId, DisplayModeId, Fps vsyncRate, Fps renderFps) REQUIRES(mDisplayLock); using KernelIdleTimerController = scheduler::RefreshRateSelector::KernelIdleTimerController; void updateKernelIdleTimer(PhysicalDisplayId, std::chrono::milliseconds timeout, KernelIdleTimerController) REQUIRES(mDisplayLock); // Set once when initializing the DisplayModeController, which the HWComposer must outlive. HWComposer* mComposerPtr = nullptr; ActiveModeListener mActiveModeListener; mutable std::mutex mDisplayLock; ui::PhysicalDisplayMap mDisplays GUARDED_BY(mDisplayLock); }; } // namespace android::display