diff options
| author | 2022-09-28 11:00:25 -0400 | |
|---|---|---|
| committer | 2024-05-03 11:54:34 -0400 | |
| commit | 6e46515ab06dd59161f10f6fc736e54a8ec23f3e (patch) | |
| tree | b1652f7609b28fc8cd5f3d89230cc4f3f504c38f | |
| parent | 7ed41c5c46cfa1162e5321ebb07e5fd86103b051 (diff) | |
SF: Introduce DisplayModeController
DisplayModeController will centralize the logic and state for selecting
the DisplayMode of each physical display. For now, register a display's
DisplaySnapshot with DMC during configure, and move the creation of its
RefreshRateSelector to DMC::registerDisplay.
Bug: 241285876
Test: presubmit
Change-Id: I673914328bea64636b8bcd193e710131926334a5
12 files changed, 266 insertions, 100 deletions
diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp index dc69b819c8..8ca796e93d 100644 --- a/services/surfaceflinger/Android.bp +++ b/services/surfaceflinger/Android.bp @@ -158,6 +158,7 @@ filegroup { "BackgroundExecutor.cpp", "Client.cpp", "ClientCache.cpp", + "Display/DisplayModeController.cpp", "Display/DisplaySnapshot.cpp", "DisplayDevice.cpp", "DisplayHardware/AidlComposerHal.cpp", diff --git a/services/surfaceflinger/Display/DisplayModeController.cpp b/services/surfaceflinger/Display/DisplayModeController.cpp new file mode 100644 index 0000000000..f093384921 --- /dev/null +++ b/services/surfaceflinger/Display/DisplayModeController.cpp @@ -0,0 +1,49 @@ +/* + * 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. + */ + +#undef LOG_TAG +#define LOG_TAG "DisplayModeController" +#define ATRACE_TAG ATRACE_TAG_GRAPHICS + +#include "Display/DisplayModeController.h" +#include "Display/DisplaySnapshot.h" + +#include <log/log.h> + +namespace android::display { + +void DisplayModeController::registerDisplay(DisplaySnapshotRef snapshotRef, + DisplayModeId activeModeId, + scheduler::RefreshRateSelector::Config config) { + const auto& snapshot = snapshotRef.get(); + const auto displayId = snapshot.displayId(); + + mDisplays.emplace_or_replace(displayId, snapshotRef, snapshot.displayModes(), activeModeId, + config); +} + +void DisplayModeController::unregisterDisplay(PhysicalDisplayId displayId) { + const bool ok = mDisplays.erase(displayId); + ALOGE_IF(!ok, "%s: Unknown display %s", __func__, to_string(displayId).c_str()); +} + +auto DisplayModeController::selectorPtrFor(PhysicalDisplayId displayId) -> RefreshRateSelectorPtr { + return mDisplays.get(displayId) + .transform([](const Display& display) { return display.selectorPtr; }) + .value_or(nullptr); +} + +} // namespace android::display diff --git a/services/surfaceflinger/Display/DisplayModeController.h b/services/surfaceflinger/Display/DisplayModeController.h new file mode 100644 index 0000000000..b6a6bee714 --- /dev/null +++ b/services/surfaceflinger/Display/DisplayModeController.h @@ -0,0 +1,73 @@ +/* + * 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 <memory> +#include <utility> + +#include <android-base/thread_annotations.h> +#include <ui/DisplayId.h> +#include <ui/DisplayMap.h> + +#include "Display/DisplaySnapshotRef.h" +#include "DisplayHardware/DisplayMode.h" +#include "Scheduler/RefreshRateSelector.h" +#include "ThreadContext.h" + +namespace android::display { + +// Selects the DisplayMode of each physical display, in accordance with DisplayManager policy and +// certain heuristic signals. +class DisplayModeController { +public: + // The referenced DisplaySnapshot must outlive the registration. + void registerDisplay(DisplaySnapshotRef, DisplayModeId, scheduler::RefreshRateSelector::Config) + REQUIRES(kMainThreadContext); + void unregisterDisplay(PhysicalDisplayId) REQUIRES(kMainThreadContext); + + // TODO(b/241285876): Remove once ownership is no longer shared with DisplayDevice. + using RefreshRateSelectorPtr = std::shared_ptr<scheduler::RefreshRateSelector>; + + // Returns `nullptr` if the display is no longer registered (or never was). + RefreshRateSelectorPtr selectorPtrFor(PhysicalDisplayId) REQUIRES(kMainThreadContext); + + // Used by tests to inject an existing RefreshRateSelector. + // TODO(b/241285876): Remove this. + void registerDisplay(PhysicalDisplayId displayId, DisplaySnapshotRef snapshotRef, + RefreshRateSelectorPtr selectorPtr) { + mDisplays.emplace_or_replace(displayId, snapshotRef, selectorPtr); + } + +private: + struct Display { + Display(DisplaySnapshotRef snapshot, RefreshRateSelectorPtr selectorPtr) + : snapshot(snapshot), selectorPtr(std::move(selectorPtr)) {} + + Display(DisplaySnapshotRef snapshot, DisplayModes modes, DisplayModeId activeModeId, + scheduler::RefreshRateSelector::Config config) + : Display(snapshot, + std::make_shared<scheduler::RefreshRateSelector>(std::move(modes), + activeModeId, config)) {} + + const DisplaySnapshotRef snapshot; + const RefreshRateSelectorPtr selectorPtr; + }; + + ui::PhysicalDisplayMap<PhysicalDisplayId, Display> mDisplays; +}; + +} // namespace android::display diff --git a/services/surfaceflinger/Display/DisplaySnapshotRef.h b/services/surfaceflinger/Display/DisplaySnapshotRef.h new file mode 100644 index 0000000000..6cc5f7e807 --- /dev/null +++ b/services/surfaceflinger/Display/DisplaySnapshotRef.h @@ -0,0 +1,27 @@ +/* + * Copyright 2022 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 <functional> + +namespace android::display { + +class DisplaySnapshot; + +using DisplaySnapshotRef = std::reference_wrapper<const DisplaySnapshot>; + +} // namespace android::display diff --git a/services/surfaceflinger/Display/PhysicalDisplay.h b/services/surfaceflinger/Display/PhysicalDisplay.h index ef36234942..9b1f1ed921 100644 --- a/services/surfaceflinger/Display/PhysicalDisplay.h +++ b/services/surfaceflinger/Display/PhysicalDisplay.h @@ -25,6 +25,7 @@ #include <utils/StrongPointer.h> #include "DisplaySnapshot.h" +#include "DisplaySnapshotRef.h" namespace android::display { @@ -45,8 +46,7 @@ public: // Transformers for PhysicalDisplays::get. - using SnapshotRef = std::reference_wrapper<const DisplaySnapshot>; - SnapshotRef snapshotRef() const { return std::cref(mSnapshot); } + DisplaySnapshotRef snapshotRef() const { return std::cref(mSnapshot); } bool isInternal() const { return mSnapshot.connectionType() == ui::DisplayConnectionType::Internal; diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h index edd57cce91..fc5089b6d3 100644 --- a/services/surfaceflinger/DisplayDevice.h +++ b/services/surfaceflinger/DisplayDevice.h @@ -363,7 +363,6 @@ struct DisplayDeviceCreationArgs { hardware::graphics::composer::hal::PowerMode initialPowerMode{ hardware::graphics::composer::hal::PowerMode::OFF}; bool isPrimary{false}; - DisplayModeId activeModeId; // Refer to DisplayDevice::mRequestedRefreshRate, for virtual display only Fps requestedRefreshRate; }; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index f80a6b61ea..b3ba0e90f9 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -228,7 +228,7 @@ bool validateCompositionDataspace(Dataspace dataspace) { return dataspace == Dataspace::V0_SRGB || dataspace == Dataspace::DISPLAY_P3; } -std::chrono::milliseconds getIdleTimerTimeout(DisplayId displayId) { +std::chrono::milliseconds getIdleTimerTimeout(PhysicalDisplayId displayId) { if (const int32_t displayIdleTimerMs = base::GetIntProperty("debug.sf.set_idle_timer_ms_"s + std::to_string(displayId.value), @@ -242,7 +242,7 @@ std::chrono::milliseconds getIdleTimerTimeout(DisplayId displayId) { return std::chrono::milliseconds(millis); } -bool getKernelIdleTimerSyspropConfig(DisplayId displayId) { +bool getKernelIdleTimerSyspropConfig(PhysicalDisplayId displayId) { const bool displaySupportKernelIdleTimer = base::GetBoolProperty("debug.sf.support_kernel_idle_timer_"s + std::to_string(displayId.value), @@ -3520,15 +3520,40 @@ bool SurfaceFlinger::configureLocked() { ')'); if (connection == hal::Connection::CONNECTED) { - if (!processHotplugConnect(displayId, hwcDisplayId, std::move(*info), - displayString.c_str())) { + const auto activeModeIdOpt = + processHotplugConnect(displayId, hwcDisplayId, std::move(*info), + displayString.c_str()); + if (!activeModeIdOpt) { if (FlagManager::getInstance().hotplug2()) { mScheduler->dispatchHotplugError( static_cast<int32_t>(DisplayHotplugEvent::ERROR_UNKNOWN)); } getHwComposer().disconnectDisplay(displayId); + continue; } + + const auto [kernelIdleTimerController, idleTimerTimeoutMs] = + getKernelIdleTimerProperties(displayId); + + using Config = scheduler::RefreshRateSelector::Config; + const Config config = + {.enableFrameRateOverride = sysprop::enable_frame_rate_override(true) + ? Config::FrameRateOverride::Enabled + : Config::FrameRateOverride::Disabled, + .frameRateMultipleThreshold = + base::GetIntProperty("debug.sf.frame_rate_multiple_threshold"s, 0), + .legacyIdleTimerTimeout = idleTimerTimeoutMs, + .kernelIdleTimerController = kernelIdleTimerController}; + + const auto snapshotOpt = + mPhysicalDisplays.get(displayId).transform(&PhysicalDisplay::snapshotRef); + LOG_ALWAYS_FATAL_IF(!snapshotOpt); + + mDisplayModeController.registerDisplay(*snapshotOpt, *activeModeIdOpt, config); } else { + // Unregister before destroying the DisplaySnapshot below. + mDisplayModeController.unregisterDisplay(displayId); + processHotplugDisconnect(displayId, displayString.c_str()); } } @@ -3537,16 +3562,17 @@ bool SurfaceFlinger::configureLocked() { return !events.empty(); } -bool SurfaceFlinger::processHotplugConnect(PhysicalDisplayId displayId, - hal::HWDisplayId hwcDisplayId, - DisplayIdentificationInfo&& info, - const char* displayString) { +std::optional<DisplayModeId> SurfaceFlinger::processHotplugConnect(PhysicalDisplayId displayId, + hal::HWDisplayId hwcDisplayId, + DisplayIdentificationInfo&& info, + const char* displayString) { auto [displayModes, activeMode] = loadDisplayModes(displayId); if (!activeMode) { ALOGE("Failed to hotplug %s", displayString); - return false; + return std::nullopt; } + const DisplayModeId activeModeId = activeMode->getId(); ui::ColorModes colorModes = getHwComposer().getColorModes(displayId); if (const auto displayOpt = mPhysicalDisplays.get(displayId)) { @@ -3569,7 +3595,7 @@ bool SurfaceFlinger::processHotplugConnect(PhysicalDisplayId displayId, state.sequenceId = DisplayDeviceState{}.sequenceId; // Generate new sequenceId. state.physical->activeMode = std::move(activeMode); ALOGI("Reconnecting %s", displayString); - return true; + return activeModeId; } const sp<IBinder> token = sp<BBinder>::make(); @@ -3590,7 +3616,7 @@ bool SurfaceFlinger::processHotplugConnect(PhysicalDisplayId displayId, mCurrentState.displays.add(token, state); ALOGI("Connecting %s", displayString); - return true; + return activeModeId; } void SurfaceFlinger::processHotplugDisconnect(PhysicalDisplayId displayId, @@ -3633,43 +3659,21 @@ sp<DisplayDevice> SurfaceFlinger::setupNewDisplayDeviceInternal( creationArgs.hasWideColorGamut = false; creationArgs.supportedPerFrameMetadata = 0; - if (const auto& physical = state.physical) { - creationArgs.activeModeId = physical->activeMode->getId(); - const auto [kernelIdleTimerController, idleTimerTimeoutMs] = - getKernelIdleTimerProperties(compositionDisplay->getId()); - - using Config = scheduler::RefreshRateSelector::Config; - const auto enableFrameRateOverride = sysprop::enable_frame_rate_override(true) - ? Config::FrameRateOverride::Enabled - : Config::FrameRateOverride::Disabled; - const Config config = - {.enableFrameRateOverride = enableFrameRateOverride, - .frameRateMultipleThreshold = - base::GetIntProperty("debug.sf.frame_rate_multiple_threshold"s, 0), - .legacyIdleTimerTimeout = idleTimerTimeoutMs, - .kernelIdleTimerController = kernelIdleTimerController}; + if (const auto physicalIdOpt = PhysicalDisplayId::tryCast(compositionDisplay->getId())) { + const auto physicalId = *physicalIdOpt; + creationArgs.isPrimary = physicalId == getPrimaryDisplayIdLocked(); creationArgs.refreshRateSelector = - mPhysicalDisplays.get(physical->id) - .transform(&PhysicalDisplay::snapshotRef) - .transform([&](const display::DisplaySnapshot& snapshot) { - return std::make_shared< - scheduler::RefreshRateSelector>(snapshot.displayModes(), - creationArgs.activeModeId, - config); - }) - .value_or(nullptr); - - creationArgs.isPrimary = physical->id == getPrimaryDisplayIdLocked(); - - mPhysicalDisplays.get(physical->id) + FTL_FAKE_GUARD(kMainThreadContext, + mDisplayModeController.selectorPtrFor(physicalId)); + + mPhysicalDisplays.get(physicalId) .transform(&PhysicalDisplay::snapshotRef) .transform(ftl::unit_fn([&](const display::DisplaySnapshot& snapshot) { for (const auto mode : snapshot.colorModes()) { creationArgs.hasWideColorGamut |= ui::isWideColorMode(mode); creationArgs.hwcColorModes - .emplace(mode, - getHwComposer().getRenderIntents(physical->id, mode)); + .emplace(mode, getHwComposer().getRenderIntents(physicalId, mode)); } })); } @@ -7672,13 +7676,12 @@ void SurfaceFlinger::kernelTimerChanged(bool expired) { } std::pair<std::optional<KernelIdleTimerController>, std::chrono::milliseconds> -SurfaceFlinger::getKernelIdleTimerProperties(DisplayId displayId) { +SurfaceFlinger::getKernelIdleTimerProperties(PhysicalDisplayId displayId) { const bool isKernelIdleTimerHwcSupported = getHwComposer().getComposer()->isSupported( android::Hwc2::Composer::OptionalFeature::KernelIdleTimer); const auto timeout = getIdleTimerTimeout(displayId); if (isKernelIdleTimerHwcSupported) { - if (const auto id = PhysicalDisplayId::tryCast(displayId); - getHwComposer().hasDisplayIdleTimerCapability(*id)) { + if (getHwComposer().hasDisplayIdleTimerCapability(displayId)) { // In order to decide if we can use the HWC api for idle timer // we query DisplayCapability::DISPLAY_IDLE_TIMER directly on the composer // without relying on hasDisplayCapability. diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 83b092d831..6211e2d5a9 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -65,6 +65,7 @@ #include <ui/FenceResult.h> #include <common/FlagManager.h> +#include "Display/DisplayModeController.h" #include "Display/PhysicalDisplay.h" #include "DisplayDevice.h" #include "DisplayHardware/HWC2.h" @@ -707,7 +708,7 @@ private: // Get the controller and timeout that will help decide how the kernel idle timer will be // configured and what value to use as the timeout. std::pair<std::optional<KernelIdleTimerController>, std::chrono::milliseconds> - getKernelIdleTimerProperties(DisplayId) REQUIRES(mStateLock); + getKernelIdleTimerProperties(PhysicalDisplayId) REQUIRES(mStateLock); // Updates the kernel idle timer either through HWC or through sysprop // depending on which controller is provided void updateKernelIdleTimer(std::chrono::milliseconds timeoutMs, KernelIdleTimerController, @@ -989,8 +990,7 @@ private: return getDefaultDisplayDeviceLocked(); } - using DisplayDeviceAndSnapshot = - std::pair<sp<DisplayDevice>, display::PhysicalDisplay::SnapshotRef>; + using DisplayDeviceAndSnapshot = std::pair<sp<DisplayDevice>, display::DisplaySnapshotRef>; // Combinator for ftl::Optional<PhysicalDisplay>::and_then. auto getDisplayDeviceAndSnapshot() REQUIRES(mStateLock) { @@ -1059,9 +1059,11 @@ private: bool configureLocked() REQUIRES(mStateLock) REQUIRES(kMainThreadContext) EXCLUDES(mHotplugMutex); - // Returns false on hotplug failure. - bool processHotplugConnect(PhysicalDisplayId, hal::HWDisplayId, DisplayIdentificationInfo&&, - const char* displayString) REQUIRES(mStateLock, kMainThreadContext); + // Returns the active mode ID, or nullopt on hotplug failure. + std::optional<DisplayModeId> processHotplugConnect(PhysicalDisplayId, hal::HWDisplayId, + DisplayIdentificationInfo&&, + const char* displayString) + REQUIRES(mStateLock, kMainThreadContext); void processHotplugDisconnect(PhysicalDisplayId, const char* displayString) REQUIRES(mStateLock, kMainThreadContext); @@ -1324,6 +1326,8 @@ private: // reads from ISchedulerCallback::requestDisplayModes may happen concurrently. std::atomic<PhysicalDisplayId> mActiveDisplayId GUARDED_BY(mStateLock); + display::DisplayModeController mDisplayModeController; + struct { DisplayIdGenerator<GpuVirtualDisplayId> gpu; std::optional<DisplayIdGenerator<HalVirtualDisplayId>> hal; diff --git a/services/surfaceflinger/tests/unittests/CommitAndCompositeTest.h b/services/surfaceflinger/tests/unittests/CommitAndCompositeTest.h index 34e4ba5e78..d4c801f050 100644 --- a/services/surfaceflinger/tests/unittests/CommitAndCompositeTest.h +++ b/services/surfaceflinger/tests/unittests/CommitAndCompositeTest.h @@ -60,7 +60,7 @@ struct CommitAndCompositeTest : testing::Test { .setNativeWindow(mNativeWindow) .setPowerMode(hal::PowerMode::ON) .setRefreshRateSelector(mFlinger.scheduler()->refreshRateSelector()) - .skipRegisterDisplay() + .skipSchedulerRegistration() .inject(); } diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp index 7d8a30a727..0ddddbd7f3 100644 --- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp +++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp @@ -282,7 +282,7 @@ struct BaseDisplayVariant { .setSecure(Derived::IS_SECURE) .setPowerMode(Derived::INIT_POWER_MODE) .setRefreshRateSelector(test->mFlinger.scheduler()->refreshRateSelector()) - .skipRegisterDisplay() + .skipSchedulerRegistration() .inject(); Mock::VerifyAndClear(test->mNativeWindow.get()); diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetupNewDisplayDeviceInternalTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetupNewDisplayDeviceInternalTest.cpp index c0796df6cb..1bae5ffd30 100644 --- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetupNewDisplayDeviceInternalTest.cpp +++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetupNewDisplayDeviceInternalTest.cpp @@ -255,10 +255,15 @@ void SetupNewDisplayDeviceInternalTest::setupNewDisplayDeviceInternalTest() { colorModes.push_back(ColorMode::DISPLAY_P3); } - mFlinger.mutablePhysicalDisplays().emplace_or_replace(*displayId, displayToken, *displayId, - *connectionType, - makeModes(activeMode), - std::move(colorModes), std::nullopt); + const auto it = mFlinger.mutablePhysicalDisplays() + .emplace_or_replace(*displayId, displayToken, *displayId, + *connectionType, makeModes(activeMode), + std::move(colorModes), std::nullopt) + .first; + + FTL_FAKE_GUARD(kMainThreadContext, + mFlinger.mutableDisplayModeController() + .registerDisplay(it->second.snapshot(), activeMode->getId(), {})); } state.isSecure = static_cast<bool>(Case::Display::SECURE); diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h index 85b17176fa..72ea6ed7e5 100644 --- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h +++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h @@ -657,6 +657,7 @@ public: auto& mutableSupportsWideColor() { return mFlinger->mSupportsWideColor; } + auto& mutableDisplayModeController() { return mFlinger->mDisplayModeController; } auto& mutableCurrentState() { return mFlinger->mCurrentState; } auto& mutableDisplayColorSetting() { return mFlinger->mDisplayColorSetting; } auto& mutableDisplays() { return mFlinger->mDisplays; } @@ -967,14 +968,14 @@ public: auto& setDisplayModes(DisplayModes modes, DisplayModeId activeModeId) { mDisplayModes = std::move(modes); - mCreationArgs.activeModeId = activeModeId; + mActiveModeId = activeModeId; mCreationArgs.refreshRateSelector = nullptr; return *this; } auto& setRefreshRateSelector(RefreshRateSelectorPtr selectorPtr) { mDisplayModes = selectorPtr->displayModes(); - mCreationArgs.activeModeId = selectorPtr->getActiveMode().modePtr->getId(); + mActiveModeId = selectorPtr->getActiveMode().modePtr->getId(); mCreationArgs.refreshRateSelector = std::move(selectorPtr); return *this; } @@ -1016,8 +1017,9 @@ public: return *this; } - auto& skipRegisterDisplay() { - mRegisterDisplay = false; + // Used to avoid overwriting mocks injected by TestableSurfaceFlinger::setupMockScheduler. + auto& skipSchedulerRegistration() { + mSchedulerRegistration = false; return *this; } @@ -1030,12 +1032,24 @@ public: std::shared_ptr<android::scheduler::VSyncTracker> tracker) NO_THREAD_SAFETY_ANALYSIS { const auto displayId = mCreationArgs.compositionDisplay->getDisplayId(); + LOG_ALWAYS_FATAL_IF(!displayId); auto& modes = mDisplayModes; - auto& activeModeId = mCreationArgs.activeModeId; + auto& activeModeId = mActiveModeId; + std::optional<Fps> refreshRateOpt; - if (displayId && !mCreationArgs.refreshRateSelector) { - if (const auto physicalId = PhysicalDisplayId::tryCast(*displayId)) { + DisplayDeviceState state; + state.isSecure = mCreationArgs.isSecure; + + if (const auto physicalId = PhysicalDisplayId::tryCast(*displayId)) { + LOG_ALWAYS_FATAL_IF(!mConnectionType); + LOG_ALWAYS_FATAL_IF(!mHwcDisplayId); + + if (mCreationArgs.isPrimary) { + mFlinger.mutableActiveDisplayId() = *physicalId; + } + + if (!mCreationArgs.refreshRateSelector) { if (modes.empty()) { constexpr DisplayModeId kModeId{0}; DisplayModePtr mode = @@ -1057,48 +1071,38 @@ public: mCreationArgs.refreshRateSelector = std::make_shared<scheduler::RefreshRateSelector>(modes, activeModeId); } - } - - sp<DisplayDevice> display = sp<DisplayDevice>::make(mCreationArgs); - mFlinger.mutableDisplays().emplace_or_replace(mDisplayToken, display); - - DisplayDeviceState state; - state.isSecure = mCreationArgs.isSecure; - - if (mConnectionType) { - LOG_ALWAYS_FATAL_IF(!displayId); - const auto physicalIdOpt = PhysicalDisplayId::tryCast(*displayId); - LOG_ALWAYS_FATAL_IF(!physicalIdOpt); - const auto physicalId = *physicalIdOpt; - - if (mCreationArgs.isPrimary) { - mFlinger.mutableActiveDisplayId() = physicalId; - } - LOG_ALWAYS_FATAL_IF(!mHwcDisplayId); + const auto activeModeOpt = modes.get(activeModeId); + LOG_ALWAYS_FATAL_IF(!activeModeOpt); + refreshRateOpt = activeModeOpt->get()->getPeakFps(); - const auto activeMode = modes.get(activeModeId); - LOG_ALWAYS_FATAL_IF(!activeMode); - const auto fps = activeMode->get()->getPeakFps(); - - state.physical = {.id = physicalId, + state.physical = {.id = *physicalId, .hwcDisplayId = *mHwcDisplayId, - .activeMode = activeMode->get()}; + .activeMode = activeModeOpt->get()}; + + const auto it = mFlinger.mutablePhysicalDisplays() + .emplace_or_replace(*physicalId, mDisplayToken, *physicalId, + *mConnectionType, std::move(modes), + ui::ColorModes(), std::nullopt) + .first; - mFlinger.mutablePhysicalDisplays().emplace_or_replace(physicalId, mDisplayToken, - physicalId, *mConnectionType, - std::move(modes), - ui::ColorModes(), - std::nullopt); + mFlinger.mutableDisplayModeController() + .registerDisplay(*physicalId, it->second.snapshot(), + mCreationArgs.refreshRateSelector); - if (mFlinger.scheduler() && mRegisterDisplay) { - mFlinger.scheduler()->registerDisplay(physicalId, - display->holdRefreshRateSelector(), + if (mFlinger.scheduler() && mSchedulerRegistration) { + mFlinger.scheduler()->registerDisplay(*physicalId, + mCreationArgs.refreshRateSelector, std::move(controller), std::move(tracker)); } + } + + sp<DisplayDevice> display = sp<DisplayDevice>::make(mCreationArgs); + mFlinger.mutableDisplays().emplace_or_replace(mDisplayToken, display); - display->setActiveMode(activeModeId, fps, fps); + if (refreshRateOpt) { + display->setActiveMode(activeModeId, *refreshRateOpt, *refreshRateOpt); } mFlinger.mutableCurrentState().displays.add(mDisplayToken, state); @@ -1112,7 +1116,8 @@ public: sp<BBinder> mDisplayToken = sp<BBinder>::make(); DisplayDeviceCreationArgs mCreationArgs; DisplayModes mDisplayModes; - bool mRegisterDisplay = true; + DisplayModeId mActiveModeId; + bool mSchedulerRegistration = true; const std::optional<ui::DisplayConnectionType> mConnectionType; const std::optional<hal::HWDisplayId> mHwcDisplayId; }; |