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

Commit 955838ff authored by Leon Scroggins's avatar Leon Scroggins Committed by Android (Google) Code Review
Browse files

Merge "Turn on and off hw vsyncs for secondary display" into main

parents a5e99090 1fc9e7f0
Loading
Loading
Loading
Loading
+33 −14
Original line number Diff line number Diff line
@@ -5821,12 +5821,15 @@ void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& display, hal:
        }

        getHwComposer().setPowerMode(displayId, mode);
        if (displayId == mActiveDisplayId && mode != hal::PowerMode::DOZE_SUSPEND) {
        if (mode != hal::PowerMode::DOZE_SUSPEND &&
            (displayId == mActiveDisplayId || FlagManager::getInstance().multithreaded_present())) {
            const bool enable =
                    mScheduler->getVsyncSchedule(displayId)->getPendingHardwareVsyncState();
            requestHardwareVsync(displayId, enable);

            if (displayId == mActiveDisplayId) {
                mScheduler->enableSyntheticVsync(false);
            }

            constexpr bool kAllowToEnable = true;
            mScheduler->resyncToHardwareVsync(displayId, kAllowToEnable, activeMode.get());
@@ -5835,8 +5838,8 @@ void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& display, hal:
        mVisibleRegionsDirty = true;
        scheduleComposite(FrameHint::kActive);
    } else if (mode == hal::PowerMode::OFF) {
        const bool currentModeNotDozeSuspend = (*currentModeOpt != hal::PowerMode::DOZE_SUSPEND);
        // Turn off the display

        if (displayId == mActiveDisplayId) {
            if (const auto display = getActivatableDisplay()) {
                onActiveDisplayChangedLocked(activeDisplay.get(), *display);
@@ -5850,14 +5853,24 @@ void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& display, hal:
                          strerror(errno));
                }

                if (*currentModeOpt != hal::PowerMode::DOZE_SUSPEND) {
                if (currentModeNotDozeSuspend) {
                    if (!FlagManager::getInstance().multithreaded_present()) {
                        mScheduler->disableHardwareVsync(displayId, true);
                    }
                    mScheduler->enableSyntheticVsync();
                }
            }
        }
        if (currentModeNotDozeSuspend && FlagManager::getInstance().multithreaded_present()) {
            constexpr bool kDisallow = true;
            mScheduler->disableHardwareVsync(displayId, kDisallow);
        }

        // Disable VSYNC before turning off the display.
        // We must disable VSYNC *before* turning off the display. The call to
        // disableHardwareVsync, above, schedules a task to turn it off after
        // this method returns. But by that point, the display is OFF, so the
        // call just updates the pending state, without actually disabling
        // VSYNC.
        requestHardwareVsync(displayId, false);
        getHwComposer().setPowerMode(displayId, mode);

@@ -5866,18 +5879,24 @@ void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& display, hal:
    } else if (mode == hal::PowerMode::DOZE || mode == hal::PowerMode::ON) {
        // Update display while dozing
        getHwComposer().setPowerMode(displayId, mode);
        if (displayId == mActiveDisplayId && *currentModeOpt == hal::PowerMode::DOZE_SUSPEND) {
        if (*currentModeOpt == hal::PowerMode::DOZE_SUSPEND &&
            (displayId == mActiveDisplayId || FlagManager::getInstance().multithreaded_present())) {
            if (displayId == mActiveDisplayId) {
                ALOGI("Force repainting for DOZE_SUSPEND -> DOZE or ON.");
                mVisibleRegionsDirty = true;
                scheduleRepaint();
                mScheduler->enableSyntheticVsync(false);
            mScheduler->resyncToHardwareVsync(displayId, true /* allowToEnable */,
                                              activeMode.get());
            }
            constexpr bool kAllowToEnable = true;
            mScheduler->resyncToHardwareVsync(displayId, kAllowToEnable, activeMode.get());
        }
    } else if (mode == hal::PowerMode::DOZE_SUSPEND) {
        // Leave display going to doze
        if (displayId == mActiveDisplayId || FlagManager::getInstance().multithreaded_present()) {
            constexpr bool kDisallow = true;
            mScheduler->disableHardwareVsync(displayId, kDisallow);
        }
        if (displayId == mActiveDisplayId) {
            mScheduler->disableHardwareVsync(displayId, true);
            mScheduler->enableSyntheticVsync();
        }
        getHwComposer().setPowerMode(displayId, mode);
+33 −0
Original line number Diff line number Diff line
@@ -188,5 +188,38 @@ TEST_F(FoldableTest, requestsHardwareVsyncForBothDisplays) {
    scheduler.onHardwareVsyncRequest(mOuterDisplay->getPhysicalId(), true);
}

TEST_F(FoldableTest, requestVsyncOnPowerOn) {
    EXPECT_CALL(mFlinger.scheduler()->mockRequestHardwareVsync, Call(kInnerDisplayId, true))
            .Times(1);
    EXPECT_CALL(mFlinger.scheduler()->mockRequestHardwareVsync, Call(kOuterDisplayId, true))
            .Times(1);

    mFlinger.setPowerModeInternal(mInnerDisplay, PowerMode::ON);
    mFlinger.setPowerModeInternal(mOuterDisplay, PowerMode::ON);
}

TEST_F(FoldableTest, disableVsyncOnPowerOffPacesetter) {
    // When the device boots, the inner display should be the pacesetter.
    ASSERT_EQ(mFlinger.scheduler()->pacesetterDisplayId(), kInnerDisplayId);

    testing::InSequence seq;
    EXPECT_CALL(mFlinger.scheduler()->mockRequestHardwareVsync, Call(kInnerDisplayId, true))
            .Times(1);
    EXPECT_CALL(mFlinger.scheduler()->mockRequestHardwareVsync, Call(kOuterDisplayId, true))
            .Times(1);

    // Turning off the pacesetter will result in disabling VSYNC.
    EXPECT_CALL(mFlinger.scheduler()->mockRequestHardwareVsync, Call(kInnerDisplayId, false))
            .Times(1);

    mFlinger.setPowerModeInternal(mInnerDisplay, PowerMode::ON);
    mFlinger.setPowerModeInternal(mOuterDisplay, PowerMode::ON);

    mFlinger.setPowerModeInternal(mInnerDisplay, PowerMode::OFF);

    // Other display is now the pacesetter.
    ASSERT_EQ(mFlinger.scheduler()->pacesetterDisplayId(), kOuterDisplayId);
}

} // namespace
} // namespace android
+9 −2
Original line number Diff line number Diff line
@@ -73,11 +73,13 @@ struct EventThreadBaseSupportedVariant {

struct EventThreadNotSupportedVariant : public EventThreadBaseSupportedVariant {
    static void setupEnableVsyncCallExpectations(DisplayTransactionTest* test) {
        setupVsyncNoCallExpectations(test);
        EXPECT_CALL(test->mFlinger.scheduler()->mockRequestHardwareVsync, Call(_, true)).Times(1);
        EXPECT_CALL(*test->mEventThread, enableSyntheticVsync(_)).Times(0);
    }

    static void setupDisableVsyncCallExpectations(DisplayTransactionTest* test) {
        setupVsyncNoCallExpectations(test);
        EXPECT_CALL(test->mFlinger.scheduler()->mockRequestHardwareVsync, Call(_, false)).Times(1);
        EXPECT_CALL(*test->mEventThread, enableSyntheticVsync(_)).Times(0);
    }
};

@@ -298,6 +300,11 @@ using PrimaryDisplayPowerCase =
// A sample configuration for the external display.
// In addition to not having event thread support, we emulate not having doze
// support.
// TODO (b/267483230): ExternalDisplay supports the features tracked in
// DispSyncIsSupportedVariant, but is the follower, so the
// expectations set by DispSyncIsSupportedVariant don't match (wrong schedule).
// We need a way to retrieve the proper DisplayId from
// setupResetModelCallExpectations (or pass it in).
template <typename TransitionVariant>
using ExternalDisplayPowerCase =
        DisplayPowerCase<ExternalDisplayVariant, DozeNotSupportedVariant<ExternalDisplayVariant>,