Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e1a3b59d authored by Treehugger Robot's avatar Treehugger Robot Committed by Automerger Merge Worker
Browse files

Merge "SF: Fix jank after folding due to power sequence" into udc-qpr-dev am: 507c115d

parents 461cd47c 507c115d
Loading
Loading
Loading
Loading
+29 −11
Original line number Diff line number Diff line
@@ -5522,6 +5522,9 @@ void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& display, hal:
        // Turn off the display

        if (displayId == mActiveDisplayId) {
            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));
@@ -5536,6 +5539,7 @@ void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& display, hal:
                    mScheduler->enableSyntheticVsync();
                }
            }
        }

        // Disable VSYNC before turning off the display.
        requestHardwareVsync(displayId, false);
@@ -7951,6 +7955,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();
+5 −1
Original line number Diff line number Diff line
@@ -934,7 +934,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;
    }
@@ -1047,6 +1048,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);
+31 −1
Original line number Diff line number Diff line
@@ -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) {