SF: Clean up API for refresh rate selection
Define types for each step: ScoredRefreshRate, RefreshRateRanking,
RankedRefreshRates, DisplayModeChoice, and DisplayModeRequest. The
last will replace DisplayDevice::ActiveModeInfo in a follow-up CL.
Add Scheduler::mLeaderDisplayId (always the primary display for now)
and provisionally use its DisplayModeChoice until Scheduler::Policy
is tracked per display.
Rewrite multi-display tests, which relied on each DisplayMode having
the same PhysicalDisplayId, and did not actually verify mode/display
association (`expectedDisplays` was unused). Test RefreshRateRanking
ordering by descending score.
Bug: 241285191
Test: libsurfaceflinger_unittest
Change-Id: I1d24d6a1fa9285aa7fc4bf2dd6654fa660d27b08
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 029dd9f..8e29715 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -1064,30 +1064,28 @@
return NO_ERROR;
}
-void SurfaceFlinger::setDesiredActiveMode(const ActiveModeInfo& info) {
+void SurfaceFlinger::setDesiredActiveMode(display::DisplayModeRequest&& request) {
ATRACE_CALL();
- if (!info.mode) {
- ALOGW("requested display mode is null");
- return;
- }
- auto display = getDisplayDeviceLocked(info.mode->getPhysicalDisplayId());
+ auto display = getDisplayDeviceLocked(request.modePtr->getPhysicalDisplayId());
if (!display) {
ALOGW("%s: display is no longer valid", __func__);
return;
}
- if (display->setDesiredActiveMode(info)) {
+ const Fps refreshRate = request.modePtr->getFps();
+
+ if (display->setDesiredActiveMode(DisplayDevice::ActiveModeInfo(std::move(request)))) {
scheduleComposite(FrameHint::kNone);
// Start receiving vsync samples now, so that we can detect a period
// switch.
- mScheduler->resyncToHardwareVsync(true, info.mode->getFps());
+ mScheduler->resyncToHardwareVsync(true, refreshRate);
// As we called to set period, we will call to onRefreshRateChangeCompleted once
// VsyncController model is locked.
modulateVsync(&VsyncModulator::onRefreshRateChangeInitiated);
- updatePhaseConfiguration(info.mode->getFps());
+ updatePhaseConfiguration(refreshRate);
mScheduler->setModeChangePending(true);
}
}
@@ -1179,7 +1177,7 @@
mRefreshRateStats->setRefreshRate(refreshRate);
updatePhaseConfiguration(refreshRate);
- if (upcomingModeInfo.event != DisplayModeEvent::None) {
+ if (upcomingModeInfo.event != scheduler::DisplayModeEvent::None) {
mScheduler->onPrimaryDisplayModeChanged(mAppConnectionHandle, upcomingModeInfo.mode);
}
}
@@ -3331,34 +3329,33 @@
mCompositionEngine->updateCursorAsync(refreshArgs);
}
-void SurfaceFlinger::requestDisplayModes(
- std::vector<scheduler::DisplayModeConfig> displayModeConfigs) {
+void SurfaceFlinger::requestDisplayModes(std::vector<display::DisplayModeRequest> modeRequests) {
if (mBootStage != BootStage::FINISHED) {
ALOGV("Currently in the boot stage, skipping display mode changes");
return;
}
ATRACE_CALL();
+
// If this is called from the main thread mStateLock must be locked before
// Currently the only way to call this function from the main thread is from
// Scheduler::chooseRefreshRateForContent
ConditionalLock lock(mStateLock, std::this_thread::get_id() != mMainThreadId);
- std::for_each(displayModeConfigs.begin(), displayModeConfigs.end(),
- [&](const auto& config) REQUIRES(mStateLock) {
- const auto& displayModePtr = config.displayModePtr;
- if (const auto display =
- getDisplayDeviceLocked(displayModePtr->getPhysicalDisplayId());
- display->refreshRateConfigs().isModeAllowed(displayModePtr->getId())) {
- const auto event = config.signals.idle ? DisplayModeEvent::None
- : DisplayModeEvent::Changed;
- setDesiredActiveMode({displayModePtr, event});
- } else {
- ALOGV("Skipping disallowed mode %d for display %" PRId64,
- displayModePtr->getId().value(), display->getPhysicalId().value);
- }
- });
+ for (auto& request : modeRequests) {
+ const auto& modePtr = request.modePtr;
+ const auto display = getDisplayDeviceLocked(modePtr->getPhysicalDisplayId());
+
+ if (!display) continue;
+
+ if (display->refreshRateConfigs().isModeAllowed(modePtr->getId())) {
+ setDesiredActiveMode(std::move(request));
+ } else {
+ ALOGV("%s: Mode %d is disallowed for display %s", __func__, modePtr->getId().value(),
+ to_string(display->getId()).c_str());
+ }
+ }
}
void SurfaceFlinger::triggerOnFrameRateOverridesChanged() {
@@ -6583,18 +6580,19 @@
}
}
-std::optional<DisplayModePtr> SurfaceFlinger::getPreferredDisplayMode(
+std::optional<ftl::NonNull<DisplayModePtr>> SurfaceFlinger::getPreferredDisplayMode(
PhysicalDisplayId displayId, DisplayModeId defaultModeId) const {
if (const auto schedulerMode = mScheduler->getPreferredDisplayMode();
schedulerMode && schedulerMode->getPhysicalDisplayId() == displayId) {
- return schedulerMode;
+ return ftl::as_non_null(schedulerMode);
}
return mPhysicalDisplays.get(displayId)
.transform(&PhysicalDisplay::snapshotRef)
.and_then([&](const display::DisplaySnapshot& snapshot) {
return snapshot.displayModes().get(defaultModeId);
- });
+ })
+ .transform(&ftl::as_non_null<const DisplayModePtr&>);
}
status_t SurfaceFlinger::setDesiredDisplayModeSpecsInternal(
@@ -6650,7 +6648,7 @@
return INVALID_OPERATION;
}
- setDesiredActiveMode({std::move(preferredMode), DisplayModeEvent::Changed});
+ setDesiredActiveMode({std::move(preferredMode), .emitEvent = true});
return NO_ERROR;
}