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
diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp
index dc69b81..8ca796e 100644
--- a/services/surfaceflinger/Android.bp
+++ b/services/surfaceflinger/Android.bp
@@ -158,6 +158,7 @@
"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 0000000..f093384
--- /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 0000000..b6a6bee
--- /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 0000000..6cc5f7e
--- /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 ef36234..9b1f1ed 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 @@
// 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 edd57cc..fc5089b 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -363,7 +363,6 @@
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 f80a6b6..b3ba0e9 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -228,7 +228,7 @@
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 @@
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 @@
')');
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 @@
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 @@
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 @@
mCurrentState.displays.add(token, state);
ALOGI("Connecting %s", displayString);
- return true;
+ return activeModeId;
}
void SurfaceFlinger::processHotplugDisconnect(PhysicalDisplayId displayId,
@@ -3633,43 +3659,21 @@
creationArgs.hasWideColorGamut = false;
creationArgs.supportedPerFrameMetadata = 0;
- if (const auto& physical = state.physical) {
- creationArgs.activeModeId = physical->activeMode->getId();
- const auto [kernelIdleTimerController, idleTimerTimeoutMs] =
- getKernelIdleTimerProperties(compositionDisplay->getId());
+ if (const auto physicalIdOpt = PhysicalDisplayId::tryCast(compositionDisplay->getId())) {
+ const auto physicalId = *physicalIdOpt;
- 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};
-
+ 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);
+ FTL_FAKE_GUARD(kMainThreadContext,
+ mDisplayModeController.selectorPtrFor(physicalId));
- creationArgs.isPrimary = physical->id == getPrimaryDisplayIdLocked();
-
- mPhysicalDisplays.get(physical->id)
+ 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 @@
}
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 83b092d..6211e2d 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 @@
// 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 @@
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 @@
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 @@
// 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 34e4ba5..d4c801f 100644
--- a/services/surfaceflinger/tests/unittests/CommitAndCompositeTest.h
+++ b/services/surfaceflinger/tests/unittests/CommitAndCompositeTest.h
@@ -60,7 +60,7 @@
.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 7d8a30a..0ddddbd 100644
--- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
@@ -282,7 +282,7 @@
.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 c0796df..1bae5ff 100644
--- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetupNewDisplayDeviceInternalTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetupNewDisplayDeviceInternalTest.cpp
@@ -255,10 +255,15 @@
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 85b1717..72ea6ed 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -657,6 +657,7 @@
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 @@
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 @@
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 @@
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 @@
mCreationArgs.refreshRateSelector =
std::make_shared<scheduler::RefreshRateSelector>(modes, activeModeId);
}
+
+ const auto activeModeOpt = modes.get(activeModeId);
+ LOG_ALWAYS_FATAL_IF(!activeModeOpt);
+ refreshRateOpt = activeModeOpt->get()->getPeakFps();
+
+ state.physical = {.id = *physicalId,
+ .hwcDisplayId = *mHwcDisplayId,
+ .activeMode = activeModeOpt->get()};
+
+ const auto it = mFlinger.mutablePhysicalDisplays()
+ .emplace_or_replace(*physicalId, mDisplayToken, *physicalId,
+ *mConnectionType, std::move(modes),
+ ui::ColorModes(), std::nullopt)
+ .first;
+
+ mFlinger.mutableDisplayModeController()
+ .registerDisplay(*physicalId, it->second.snapshot(),
+ mCreationArgs.refreshRateSelector);
+
+ 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);
- 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 activeMode = modes.get(activeModeId);
- LOG_ALWAYS_FATAL_IF(!activeMode);
- const auto fps = activeMode->get()->getPeakFps();
-
- state.physical = {.id = physicalId,
- .hwcDisplayId = *mHwcDisplayId,
- .activeMode = activeMode->get()};
-
- mFlinger.mutablePhysicalDisplays().emplace_or_replace(physicalId, mDisplayToken,
- physicalId, *mConnectionType,
- std::move(modes),
- ui::ColorModes(),
- std::nullopt);
-
- if (mFlinger.scheduler() && mRegisterDisplay) {
- mFlinger.scheduler()->registerDisplay(physicalId,
- display->holdRefreshRateSelector(),
- std::move(controller),
- std::move(tracker));
- }
-
- display->setActiveMode(activeModeId, fps, fps);
+ if (refreshRateOpt) {
+ display->setActiveMode(activeModeId, *refreshRateOpt, *refreshRateOpt);
}
mFlinger.mutableCurrentState().displays.add(mDisplayToken, state);
@@ -1112,7 +1116,8 @@
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;
};