Merge "SF: Skip modesetting during boot animation" into main
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index c853eb7..fbb8aa1 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -1649,6 +1649,11 @@
}
void SurfaceFlinger::initiateDisplayModeChanges() {
+ if (FlagManager::getInstance().synced_resolution_switch() && mBootStage != BootStage::FINISHED)
+ [[unlikely]] {
+ return;
+ }
+
SFTRACE_CALL();
for (const auto& [displayId, physical] : mPhysicalDisplays) {
@@ -4744,8 +4749,7 @@
}
void SurfaceFlinger::requestDisplayModes(std::vector<display::DisplayModeRequest> modeRequests) {
- if (mBootStage != BootStage::FINISHED) {
- ALOGV("Currently in the boot stage, skipping display mode changes");
+ if (mBootStage != BootStage::FINISHED) [[unlikely]] {
return;
}
diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayModeSwitching.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayModeSwitching.cpp
index 3b67de1..2e34353 100644
--- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayModeSwitching.cpp
+++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayModeSwitching.cpp
@@ -258,6 +258,38 @@
EXPECT_SET_ACTIVE_CONFIG(kInnerDisplayHwcId, kModeId90);
EXPECT_SET_ACTIVE_CONFIG(kOuterDisplayHwcId, kModeId60);
}
+
+ void setupSyncedResolutionChange() {
+ EXPECT_THAT(mDisplay, HasActiveMode(&dmc(), kModeId60));
+
+ // PrimaryDisplayVariant has a 4K size, so switch to 8K.
+ EXPECT_EQ(NO_ERROR,
+ mFlinger.setDesiredDisplayModeSpecs(mDisplay->getDisplayToken().promote(),
+ mock::createDisplayModeSpecs(kModeId60_8K,
+ 60_Hz)));
+
+ EXPECT_THAT(mDisplay, HasDesiredMode(&mFlinger, kModeId60_8K));
+ }
+
+ void expectSyncedResolutionChange() {
+ // Set the display size to match the resolution.
+ DisplayState state;
+ state.what = DisplayState::eDisplaySizeChanged;
+ state.token = mDisplay->getDisplayToken().promote();
+ state.width = static_cast<uint32_t>(mock::kResolution8K.width);
+ state.height = static_cast<uint32_t>(mock::kResolution8K.height);
+
+ // The next commit should set the mode and resize the framebuffer.
+ const VsyncPeriodChangeTimeline timeline{.refreshRequired = false};
+ EXPECT_CALL(*mDisplaySurface, resizeBuffers(mock::kResolution8K));
+ EXPECT_SET_ACTIVE_CONFIG(kInnerDisplayHwcId, kModeId60_8K);
+
+ constexpr bool kModeset = true;
+ mFlinger.setDisplayStateLocked(state);
+ mFlinger.configureAndCommit(kModeset);
+
+ EXPECT_THAT(mDisplay, HasActiveMode(&dmc(), kModeId60_8K));
+ }
};
void DisplayModeSwitchingTest::setupScheduler(
@@ -441,15 +473,7 @@
TEST_P(DisplayModeSwitchingTest, changeResolutionSynced) {
SET_FLAG_FOR_TEST(flags::synced_resolution_switch, true);
- EXPECT_THAT(mDisplay, HasActiveMode(&dmc(), kModeId60));
-
- // PrimaryDisplayVariant has a 4K size, so switch to 8K.
- EXPECT_EQ(NO_ERROR,
- mFlinger.setDesiredDisplayModeSpecs(mDisplay->getDisplayToken().promote(),
- mock::createDisplayModeSpecs(kModeId60_8K,
- 60_Hz)));
-
- EXPECT_THAT(mDisplay, HasDesiredMode(&mFlinger, kModeId60_8K));
+ EXPECT_NO_FATAL_FAILURE(setupSyncedResolutionChange());
// The mode should not be set until the commit that resizes the display.
mFlinger.commit();
@@ -457,23 +481,23 @@
mFlinger.commit();
EXPECT_THAT(mDisplay, HasDesiredMode(&mFlinger, kModeId60_8K));
- // Set the display size to match the resolution.
- DisplayState state;
- state.what = DisplayState::eDisplaySizeChanged;
- state.token = mDisplay->getDisplayToken().promote();
- state.width = static_cast<uint32_t>(mock::kResolution8K.width);
- state.height = static_cast<uint32_t>(mock::kResolution8K.height);
+ EXPECT_NO_FATAL_FAILURE(expectSyncedResolutionChange());
+}
- // The next commit should set the mode and resize the framebuffer.
- const VsyncPeriodChangeTimeline timeline{.refreshRequired = false};
- EXPECT_CALL(*mDisplaySurface, resizeBuffers(mock::kResolution8K));
- EXPECT_SET_ACTIVE_CONFIG(kInnerDisplayHwcId, kModeId60_8K);
+TEST_P(DisplayModeSwitchingTest, changeResolutionSyncedDuringBoot) {
+ SET_FLAG_FOR_TEST(flags::synced_resolution_switch, true);
- constexpr bool kModeset = true;
- mFlinger.setDisplayStateLocked(state);
- mFlinger.configureAndCommit(kModeset);
+ mFlinger.mutableBootStage() = TestableSurfaceFlinger::BootStage::BOOTANIMATION;
+ EXPECT_NO_FATAL_FAILURE(setupSyncedResolutionChange());
- EXPECT_THAT(mDisplay, HasActiveMode(&dmc(), kModeId60_8K));
+ // The mode should not be set until the boot animation has finished.
+ mFlinger.commit();
+ EXPECT_THAT(mDisplay, HasDesiredMode(&mFlinger, kModeId60_8K));
+ mFlinger.commit();
+ EXPECT_THAT(mDisplay, HasDesiredMode(&mFlinger, kModeId60_8K));
+
+ mFlinger.mutableBootStage() = TestableSurfaceFlinger::BootStage::FINISHED;
+ EXPECT_NO_FATAL_FAILURE(expectSyncedResolutionChange());
}
TEST_P(DisplayModeSwitchingTest, innerXorOuterDisplay) {
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index 34acc22..8856963 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -155,6 +155,8 @@
if (!mFlinger) {
mFlinger = sp<SurfaceFlinger>::make(mFactory, SurfaceFlinger::SkipInitialization);
}
+
+ mFlinger->mBootStage = SurfaceFlinger::BootStage::FINISHED;
}
SurfaceFlinger* flinger() { return mFlinger.get(); }
@@ -677,6 +679,9 @@
const auto& hwcPhysicalDisplayIdMap() const { return getHwComposer().mPhysicalDisplayIdMap; }
const auto& hwcDisplayData() const { return getHwComposer().mDisplayData; }
+ using BootStage = SurfaceFlinger::BootStage;
+ auto& mutableBootStage() { return mFlinger->mBootStage; }
+
auto& mutableSupportsWideColor() { return mFlinger->mSupportsWideColor; }
auto& mutableDisplayModeController() { return mFlinger->mDisplayModeController; }