diff options
| author | 2022-06-06 17:08:14 -0700 | |
|---|---|---|
| committer | 2022-06-07 21:05:23 +0000 | |
| commit | 6a9731d3ed5c5bd1cce64db28e2bc6ada25ebc85 (patch) | |
| tree | 3b782666b01764c9b39a84b90863adc205deeb78 | |
| parent | 23a9ec0bb371a98db20a961c61cb8eb80b9fd71f (diff) | |
HW Vsync turns off correctly in Doze/AOD.
Otherwise when entering AOD mode, SF keeps HW Vsync on indefinitely,
leading to power inefficiency.
Bug: 219109873
Test: atest libsurfaceflinger_test
Test: perfetto trace
Change-Id: Idf80d4c64abe78593809be9d1ba6b7dd42d29054
9 files changed, 54 insertions, 10 deletions
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp index 37f0fec425..08a1edea60 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.cpp +++ b/services/surfaceflinger/Scheduler/Scheduler.cpp @@ -554,11 +554,12 @@ void Scheduler::onTouchHint() { } } -void Scheduler::setDisplayPowerState(bool normal) { +void Scheduler::setDisplayPowerMode(hal::PowerMode powerMode) { { std::lock_guard<std::mutex> lock(mPolicyLock); - mPolicy.isDisplayPowerStateNormal = normal; + mPolicy.displayPowerMode = powerMode; } + mVsyncSchedule->getController().setDisplayPowerMode(powerMode); if (mDisplayPowerTimer) { mDisplayPowerTimer->reset(); @@ -706,7 +707,8 @@ auto Scheduler::chooseDisplayMode() -> std::pair<DisplayModePtr, GlobalSignals> // If Display Power is not in normal operation we want to be in performance mode. When coming // back to normal mode, a grace period is given with DisplayPowerTimer. if (mDisplayPowerTimer && - (!mPolicy.isDisplayPowerStateNormal || mPolicy.displayPowerTimer == TimerState::Reset)) { + (mPolicy.displayPowerMode != hal::PowerMode::ON || + mPolicy.displayPowerTimer == TimerState::Reset)) { constexpr GlobalSignals kNoSignals; return {configs->getMaxRefreshRateByPolicy(), kNoSignals}; } diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h index 0c72124119..a8043bf94c 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.h +++ b/services/surfaceflinger/Scheduler/Scheduler.h @@ -186,7 +186,7 @@ public: // Indicates that touch interaction is taking place. void onTouchHint(); - void setDisplayPowerState(bool normal); + void setDisplayPowerMode(hal::PowerMode powerMode); VSyncDispatch& getVsyncDispatch() { return mVsyncSchedule->getDispatch(); } @@ -325,7 +325,7 @@ private: TimerState idleTimer = TimerState::Reset; TouchState touch = TouchState::Inactive; TimerState displayPowerTimer = TimerState::Expired; - bool isDisplayPowerStateNormal = true; + hal::PowerMode displayPowerMode = hal::PowerMode::ON; // Chosen display mode. DisplayModePtr mode; diff --git a/services/surfaceflinger/Scheduler/VSyncReactor.cpp b/services/surfaceflinger/Scheduler/VSyncReactor.cpp index bdcab515f2..13cd304a5f 100644 --- a/services/surfaceflinger/Scheduler/VSyncReactor.cpp +++ b/services/surfaceflinger/Scheduler/VSyncReactor.cpp @@ -146,6 +146,11 @@ bool VSyncReactor::periodConfirmed(nsecs_t vsync_timestamp, std::optional<nsecs_ return false; } + if (mDisplayPowerMode == hal::PowerMode::DOZE || + mDisplayPowerMode == hal::PowerMode::DOZE_SUSPEND) { + return true; + } + if (!mLastHwVsync && !HwcVsyncPeriod) { return false; } @@ -206,6 +211,11 @@ bool VSyncReactor::addHwVsyncTimestamp(nsecs_t timestamp, std::optional<nsecs_t> return mMoreSamplesNeeded; } +void VSyncReactor::setDisplayPowerMode(hal::PowerMode powerMode) { + std::scoped_lock lock(mMutex); + mDisplayPowerMode = powerMode; +} + void VSyncReactor::dump(std::string& result) const { std::lock_guard lock(mMutex); StringAppendF(&result, "VsyncReactor in use\n"); diff --git a/services/surfaceflinger/Scheduler/VSyncReactor.h b/services/surfaceflinger/Scheduler/VSyncReactor.h index 6a1950ac77..4501487392 100644 --- a/services/surfaceflinger/Scheduler/VSyncReactor.h +++ b/services/surfaceflinger/Scheduler/VSyncReactor.h @@ -49,6 +49,8 @@ public: bool addHwVsyncTimestamp(nsecs_t timestamp, std::optional<nsecs_t> hwcVsyncPeriod, bool* periodFlushed) final; + void setDisplayPowerMode(hal::PowerMode powerMode) final; + void dump(std::string& result) const final; private: @@ -73,6 +75,8 @@ private: std::optional<nsecs_t> mPeriodTransitioningTo GUARDED_BY(mMutex); std::optional<nsecs_t> mLastHwVsync GUARDED_BY(mMutex); + hal::PowerMode mDisplayPowerMode GUARDED_BY(mMutex) = hal::PowerMode::ON; + const bool mSupportKernelIdleTimer = false; }; diff --git a/services/surfaceflinger/Scheduler/VsyncController.h b/services/surfaceflinger/Scheduler/VsyncController.h index 59f65372a9..726a420649 100644 --- a/services/surfaceflinger/Scheduler/VsyncController.h +++ b/services/surfaceflinger/Scheduler/VsyncController.h @@ -18,7 +18,10 @@ #include <cstddef> #include <memory> +#include <mutex> +#include <DisplayHardware/HWComposer.h> +#include <DisplayHardware/Hal.h> #include <ui/FenceTime.h> #include <utils/Mutex.h> #include <utils/RefBase.h> @@ -70,6 +73,13 @@ public: */ virtual void setIgnorePresentFences(bool ignore) = 0; + /* + * Sets the primary display power mode to the controller. + * + * \param [in] powerMode + */ + virtual void setDisplayPowerMode(hal::PowerMode powerMode) = 0; + virtual void dump(std::string& result) const = 0; protected: diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 5cf9558e7e..906cf73ade 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -4947,7 +4947,7 @@ void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& display, hal: if (isDisplayActiveLocked(display)) { mTimeStats->setPowerMode(mode); mRefreshRateStats->setPowerMode(mode); - mScheduler->setDisplayPowerState(mode == hal::PowerMode::ON); + mScheduler->setDisplayPowerMode(mode); } ALOGD("Finished setting power mode %d on display %s", mode, to_string(displayId).c_str()); diff --git a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp index aab27957c3..93c809e2fd 100644 --- a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp +++ b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp @@ -159,8 +159,8 @@ TEST_F(SchedulerTest, chooseRefreshRateForContentIsNoopWhenModeSwitchingIsNotSup mScheduler->recordLayerHistory(layer.get(), 0, LayerHistory::LayerUpdateType::Buffer); ASSERT_EQ(0u, mScheduler->getNumActiveLayers()); - constexpr bool kPowerStateNormal = true; - mScheduler->setDisplayPowerState(kPowerStateNormal); + constexpr hal::PowerMode kPowerModeOn = hal::PowerMode::ON; + mScheduler->setDisplayPowerMode(kPowerModeOn); constexpr uint32_t kDisplayArea = 999'999; mScheduler->onActiveDisplayAreaChanged(kDisplayArea); @@ -226,8 +226,8 @@ TEST_F(SchedulerTest, chooseRefreshRateForContentSelectsMaxRefreshRate) { mScheduler->recordLayerHistory(layer.get(), 0, LayerHistory::LayerUpdateType::Buffer); - constexpr bool kPowerStateNormal = true; - mScheduler->setDisplayPowerState(kPowerStateNormal); + constexpr hal::PowerMode kPowerModeOn = hal::PowerMode::ON; + mScheduler->setDisplayPowerMode(kPowerModeOn); constexpr uint32_t kDisplayArea = 999'999; mScheduler->onActiveDisplayAreaChanged(kDisplayArea); diff --git a/services/surfaceflinger/tests/unittests/VSyncReactorTest.cpp b/services/surfaceflinger/tests/unittests/VSyncReactorTest.cpp index 4eb90558ab..30a3f9a4a7 100644 --- a/services/surfaceflinger/tests/unittests/VSyncReactorTest.cpp +++ b/services/surfaceflinger/tests/unittests/VSyncReactorTest.cpp @@ -349,6 +349,23 @@ TEST_F(VSyncReactorTest, addResyncSamplePeriodChanges) { } } +TEST_F(VSyncReactorTest, addHwVsyncTimestampDozePreempt) { + bool periodFlushed = false; + nsecs_t const newPeriod = 4000; + + mReactor.startPeriodTransition(newPeriod); + + auto time = 0; + // If the power mode is not DOZE or DOZE_SUSPEND, it is still collecting timestamps. + EXPECT_TRUE(mReactor.addHwVsyncTimestamp(time, std::nullopt, &periodFlushed)); + EXPECT_FALSE(periodFlushed); + + // Set power mode to DOZE to trigger period flushing. + mReactor.setDisplayPowerMode(hal::PowerMode::DOZE); + EXPECT_FALSE(mReactor.addHwVsyncTimestamp(time, std::nullopt, &periodFlushed)); + EXPECT_TRUE(periodFlushed); +} + TEST_F(VSyncReactorTest, addPresentFenceWhileAwaitingPeriodConfirmationRequestsHwVsync) { auto time = 0; bool periodFlushed = false; diff --git a/services/surfaceflinger/tests/unittests/mock/MockVsyncController.h b/services/surfaceflinger/tests/unittests/mock/MockVsyncController.h index 314f681545..4ef91dacb2 100644 --- a/services/surfaceflinger/tests/unittests/mock/MockVsyncController.h +++ b/services/surfaceflinger/tests/unittests/mock/MockVsyncController.h @@ -31,6 +31,7 @@ public: MOCK_METHOD3(addHwVsyncTimestamp, bool(nsecs_t, std::optional<nsecs_t>, bool*)); MOCK_METHOD1(startPeriodTransition, void(nsecs_t)); MOCK_METHOD1(setIgnorePresentFences, void(bool)); + MOCK_METHOD(void, setDisplayPowerMode, (hal::PowerMode), (override)); MOCK_CONST_METHOD1(dump, void(std::string&)); }; |