summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Dominik Laskowski <domlaskowski@google.com> 2022-09-28 11:00:25 -0400
committer Dominik Laskowski <domlaskowski@google.com> 2024-05-03 11:54:34 -0400
commit6e46515ab06dd59161f10f6fc736e54a8ec23f3e (patch)
treeb1652f7609b28fc8cd5f3d89230cc4f3f504c38f
parent7ed41c5c46cfa1162e5321ebb07e5fd86103b051 (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
-rw-r--r--services/surfaceflinger/Android.bp1
-rw-r--r--services/surfaceflinger/Display/DisplayModeController.cpp49
-rw-r--r--services/surfaceflinger/Display/DisplayModeController.h73
-rw-r--r--services/surfaceflinger/Display/DisplaySnapshotRef.h27
-rw-r--r--services/surfaceflinger/Display/PhysicalDisplay.h4
-rw-r--r--services/surfaceflinger/DisplayDevice.h1
-rw-r--r--services/surfaceflinger/SurfaceFlinger.cpp91
-rw-r--r--services/surfaceflinger/SurfaceFlinger.h16
-rw-r--r--services/surfaceflinger/tests/unittests/CommitAndCompositeTest.h2
-rw-r--r--services/surfaceflinger/tests/unittests/CompositionTest.cpp2
-rw-r--r--services/surfaceflinger/tests/unittests/SurfaceFlinger_SetupNewDisplayDeviceInternalTest.cpp13
-rw-r--r--services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h87
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;
};