diff options
author | 2023-08-14 13:08:13 +0000 | |
---|---|---|
committer | 2023-08-14 13:08:13 +0000 | |
commit | 18f8c58c3654d769a6ac69ff7ea74ef322f0ea2d (patch) | |
tree | 1c515acbec329b63419916bca6f11949fbf84fd1 | |
parent | 4232a0d856ee3879fd2a456b2a078907aba7af99 (diff) | |
parent | e1a3b59deb8e1981dde6a705eb89bf2bc6622314 (diff) |
Merge "SF: Fix jank after folding due to power sequence" into udc-qpr-dev am: 507c115dde am: e1a3b59deb
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/native/+/24372572
Change-Id: Id9177e039e07cab9791c70bf18ddb1093b9e7cd5
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
-rw-r--r-- | services/surfaceflinger/SurfaceFlinger.cpp | 40 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceFlinger.h | 6 | ||||
-rw-r--r-- | services/surfaceflinger/tests/unittests/SurfaceFlinger_FoldableTest.cpp | 32 |
3 files changed, 65 insertions, 13 deletions
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 328a382e88..2639f92b44 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -5713,18 +5713,22 @@ void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& display, hal: // Turn off the display if (displayId == mActiveDisplayId) { - if (setSchedFifo(false) != NO_ERROR) { - ALOGW("Failed to set SCHED_OTHER after powering off active display: %s", - strerror(errno)); - } - if (setSchedAttr(false) != NO_ERROR) { - ALOGW("Failed set uclamp.min after powering off active display: %s", - strerror(errno)); - } + if (const auto display = getActivatableDisplay()) { + onActiveDisplayChangedLocked(activeDisplay.get(), *display); + } else { + if (setSchedFifo(false) != NO_ERROR) { + ALOGW("Failed to set SCHED_OTHER after powering off active display: %s", + strerror(errno)); + } + if (setSchedAttr(false) != NO_ERROR) { + ALOGW("Failed set uclamp.min after powering off active display: %s", + strerror(errno)); + } - if (*currentModeOpt != hal::PowerMode::DOZE_SUSPEND) { - mScheduler->disableHardwareVsync(displayId, true); - mScheduler->enableSyntheticVsync(); + if (*currentModeOpt != hal::PowerMode::DOZE_SUSPEND) { + mScheduler->disableHardwareVsync(displayId, true); + mScheduler->enableSyntheticVsync(); + } } } @@ -8343,6 +8347,20 @@ void SurfaceFlinger::onActiveDisplaySizeChanged(const DisplayDevice& activeDispl getRenderEngine().onActiveDisplaySizeChanged(activeDisplay.getSize()); } +sp<DisplayDevice> SurfaceFlinger::getActivatableDisplay() const { + if (mPhysicalDisplays.size() == 1) return nullptr; + + // TODO(b/255635821): Choose the pacesetter display, considering both internal and external + // displays. For now, pick the other internal display, assuming a dual-display foldable. + return findDisplay([this](const DisplayDevice& display) REQUIRES(mStateLock) { + const auto idOpt = PhysicalDisplayId::tryCast(display.getId()); + return idOpt && *idOpt != mActiveDisplayId && display.isPoweredOn() && + mPhysicalDisplays.get(*idOpt) + .transform(&PhysicalDisplay::isInternal) + .value_or(false); + }); +} + void SurfaceFlinger::onActiveDisplayChangedLocked(const DisplayDevice* inactiveDisplayPtr, const DisplayDevice& activeDisplay) { ATRACE_CALL(); diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index d9c1101de8..0b91e714a1 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -941,7 +941,8 @@ private: template <typename Predicate> sp<DisplayDevice> findDisplay(Predicate p) const REQUIRES(mStateLock) { const auto it = std::find_if(mDisplays.begin(), mDisplays.end(), - [&](const auto& pair) { return p(*pair.second); }); + [&](const auto& pair) + REQUIRES(mStateLock) { return p(*pair.second); }); return it == mDisplays.end() ? nullptr : it->second; } @@ -1054,6 +1055,9 @@ private: VirtualDisplayId acquireVirtualDisplay(ui::Size, ui::PixelFormat) REQUIRES(mStateLock); void releaseVirtualDisplay(VirtualDisplayId); + // Returns a display other than `mActiveDisplayId` that can be activated, if any. + sp<DisplayDevice> getActivatableDisplay() const REQUIRES(mStateLock, kMainThreadContext); + void onActiveDisplayChangedLocked(const DisplayDevice* inactiveDisplayPtr, const DisplayDevice& activeDisplay) REQUIRES(mStateLock, kMainThreadContext); diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_FoldableTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_FoldableTest.cpp index bd2344c60d..ed8d909e63 100644 --- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_FoldableTest.cpp +++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_FoldableTest.cpp @@ -55,13 +55,17 @@ struct FoldableTest : DisplayTransactionTest { sp<DisplayDevice> mInnerDisplay, mOuterDisplay; }; -TEST_F(FoldableTest, foldUnfold) { +TEST_F(FoldableTest, promotesPacesetterOnBoot) { // When the device boots, the inner display should be the pacesetter. ASSERT_EQ(mFlinger.scheduler()->pacesetterDisplayId(), kInnerDisplayId); // ...and should still be after powering on. mFlinger.setPowerModeInternal(mInnerDisplay, PowerMode::ON); ASSERT_EQ(mFlinger.scheduler()->pacesetterDisplayId(), kInnerDisplayId); +} + +TEST_F(FoldableTest, promotesPacesetterOnFoldUnfold) { + mFlinger.setPowerModeInternal(mInnerDisplay, PowerMode::ON); // The outer display should become the pacesetter after folding. mFlinger.setPowerModeInternal(mInnerDisplay, PowerMode::OFF); @@ -72,6 +76,10 @@ TEST_F(FoldableTest, foldUnfold) { mFlinger.setPowerModeInternal(mOuterDisplay, PowerMode::OFF); mFlinger.setPowerModeInternal(mInnerDisplay, PowerMode::ON); ASSERT_EQ(mFlinger.scheduler()->pacesetterDisplayId(), kInnerDisplayId); +} + +TEST_F(FoldableTest, promotesPacesetterOnConcurrentPowerOn) { + mFlinger.setPowerModeInternal(mInnerDisplay, PowerMode::ON); // The inner display should stay the pacesetter if both are powered on. // TODO(b/255635821): The pacesetter should depend on the displays' refresh rates. @@ -81,6 +89,28 @@ TEST_F(FoldableTest, foldUnfold) { // The outer display should become the pacesetter if designated. mFlinger.scheduler()->setPacesetterDisplay(kOuterDisplayId); ASSERT_EQ(mFlinger.scheduler()->pacesetterDisplayId(), kOuterDisplayId); + + // The inner display should become the pacesetter if designated. + mFlinger.scheduler()->setPacesetterDisplay(kInnerDisplayId); + ASSERT_EQ(mFlinger.scheduler()->pacesetterDisplayId(), kInnerDisplayId); +} + +TEST_F(FoldableTest, promotesPacesetterOnConcurrentPowerOff) { + mFlinger.setPowerModeInternal(mInnerDisplay, PowerMode::ON); + mFlinger.setPowerModeInternal(mOuterDisplay, PowerMode::ON); + + // The outer display should become the pacesetter if the inner display powers off. + mFlinger.setPowerModeInternal(mInnerDisplay, PowerMode::OFF); + ASSERT_EQ(mFlinger.scheduler()->pacesetterDisplayId(), kOuterDisplayId); + + // The outer display should stay the pacesetter if both are powered on. + // TODO(b/255635821): The pacesetter should depend on the displays' refresh rates. + mFlinger.setPowerModeInternal(mInnerDisplay, PowerMode::ON); + ASSERT_EQ(mFlinger.scheduler()->pacesetterDisplayId(), kOuterDisplayId); + + // The inner display should become the pacesetter if the outer display powers off. + mFlinger.setPowerModeInternal(mOuterDisplay, PowerMode::OFF); + ASSERT_EQ(mFlinger.scheduler()->pacesetterDisplayId(), kInnerDisplayId); } TEST_F(FoldableTest, doesNotRequestHardwareVsyncIfPoweredOff) { |