diff options
7 files changed, 53 insertions, 10 deletions
diff --git a/services/surfaceflinger/DisplayHardware/Hal.h b/services/surfaceflinger/DisplayHardware/Hal.h index bb2888e0fb..02d065881b 100644 --- a/services/surfaceflinger/DisplayHardware/Hal.h +++ b/services/surfaceflinger/DisplayHardware/Hal.h @@ -166,4 +166,15 @@ inline std::string to_string(hardware::graphics::composer::hal::PowerMode mode) } } +inline std::string to_string(hardware::graphics::composer::hal::Vsync vsync) { + switch (vsync) { + case hardware::graphics::composer::hal::Vsync::ENABLE: + return "Enable"; + case hardware::graphics::composer::hal::Vsync::DISABLE: + return "Disable"; + default: + return "Unknown"; + } +} + } // namespace android diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp index 1a5f0f44ba..1989d57cd7 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.cpp +++ b/services/surfaceflinger/Scheduler/Scheduler.cpp @@ -324,6 +324,7 @@ void Scheduler::onScreenAcquired(ConnectionHandle handle) { thread = mConnections[handle].thread.get(); } thread->onScreenAcquired(); + mScreenAcquired = true; } void Scheduler::onScreenReleased(ConnectionHandle handle) { @@ -334,6 +335,7 @@ void Scheduler::onScreenReleased(ConnectionHandle handle) { thread = mConnections[handle].thread.get(); } thread->onScreenReleased(); + mScreenAcquired = false; } void Scheduler::onFrameRateOverridesChanged(ConnectionHandle handle, PhysicalDisplayId displayId) { @@ -760,6 +762,13 @@ void Scheduler::dump(std::string& result) const { } StringAppendF(&result, "}\n"); } + + { + std::lock_guard lock(mHWVsyncLock); + StringAppendF(&result, + "mScreenAcquired=%d mPrimaryHWVsyncEnabled=%d mHWVsyncAvailable=%d\n", + mScreenAcquired.load(), mPrimaryHWVsyncEnabled, mHWVsyncAvailable); + } } void Scheduler::dumpVsync(std::string& s) const { diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h index 2f97328824..ee519f33a3 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.h +++ b/services/surfaceflinger/Scheduler/Scheduler.h @@ -282,7 +282,7 @@ private: InjectVSyncSource* mVSyncInjector = nullptr; ConnectionHandle mInjectorConnectionHandle; - std::mutex mHWVsyncLock; + mutable std::mutex mHWVsyncLock; bool mPrimaryHWVsyncEnabled GUARDED_BY(mHWVsyncLock) = false; bool mHWVsyncAvailable GUARDED_BY(mHWVsyncLock) = false; @@ -345,6 +345,9 @@ private: GUARDED_BY(mFrameRateOverridesLock); scheduler::RefreshRateConfigs::UidToFrameRateOverride mFrameRateOverridesFromBackdoor GUARDED_BY(mFrameRateOverridesLock); + + // Keeps track of whether the screen is acquired for debug + std::atomic<bool> mScreenAcquired = false; }; } // namespace android diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 82bd398278..29d35c2a8b 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -1824,7 +1824,7 @@ void SurfaceFlinger::setVsyncEnabled(bool enabled) { if (const auto display = getDefaultDisplayDeviceLocked(); display && display->isPoweredOn()) { - getHwComposer().setVsyncEnabled(display->getPhysicalId(), mHWCVsyncPendingState); + setHWCVsyncEnabled(display->getPhysicalId(), mHWCVsyncPendingState); } })); } @@ -4585,6 +4585,12 @@ void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& display, hal: return; } + const auto activeDisplay = getDisplayDeviceLocked(mActiveDisplayToken); + if (activeDisplay != display && display->isInternal() && activeDisplay && + activeDisplay->isPoweredOn()) { + ALOGW("Trying to change power mode on non active display while the active display is ON"); + } + display->setPowerMode(mode); if (mInterceptor->isEnabled()) { @@ -4592,7 +4598,7 @@ void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& display, hal: } const auto vsyncPeriod = display->refreshRateConfigs().getCurrentRefreshRate().getVsyncPeriod(); if (currentMode == hal::PowerMode::OFF) { - const auto activeDisplay = getDisplayDeviceLocked(mActiveDisplayToken); + // Turn on the display if (display->isInternal() && (!activeDisplay || !activeDisplay->isPoweredOn())) { onActiveDisplayChangedLocked(display); } @@ -4605,8 +4611,8 @@ void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& display, hal: ALOGW("Couldn't set SCHED_FIFO on display on: %s\n", strerror(errno)); } getHwComposer().setPowerMode(displayId, mode); - if (display->isInternal() && mode != hal::PowerMode::DOZE_SUSPEND) { - getHwComposer().setVsyncEnabled(displayId, mHWCVsyncPendingState); + if (isDisplayActiveLocked(display) && mode != hal::PowerMode::DOZE_SUSPEND) { + setHWCVsyncEnabled(displayId, mHWCVsyncPendingState); mScheduler->onScreenAcquired(mAppConnectionHandle); mScheduler->resyncToHardwareVsync(true, vsyncPeriod); } @@ -4622,13 +4628,13 @@ void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& display, hal: if (SurfaceFlinger::setSchedAttr(false) != NO_ERROR) { ALOGW("Couldn't set uclamp.min on display off: %s\n", strerror(errno)); } - if (display->isInternal() && currentMode != hal::PowerMode::DOZE_SUSPEND) { + if (isDisplayActiveLocked(display) && currentMode != hal::PowerMode::DOZE_SUSPEND) { mScheduler->disableHardwareVsync(true); mScheduler->onScreenReleased(mAppConnectionHandle); } // Make sure HWVsync is disabled before turning off the display - getHwComposer().setVsyncEnabled(displayId, hal::Vsync::DISABLE); + setHWCVsyncEnabled(displayId, hal::Vsync::DISABLE); getHwComposer().setPowerMode(displayId, mode); mVisibleRegionsDirty = true; @@ -4636,13 +4642,13 @@ 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 (display->isInternal() && currentMode == hal::PowerMode::DOZE_SUSPEND) { + if (isDisplayActiveLocked(display) && currentMode == hal::PowerMode::DOZE_SUSPEND) { mScheduler->onScreenAcquired(mAppConnectionHandle); mScheduler->resyncToHardwareVsync(true, vsyncPeriod); } } else if (mode == hal::PowerMode::DOZE_SUSPEND) { // Leave display going to doze - if (display->isInternal()) { + if (isDisplayActiveLocked(display)) { mScheduler->disableHardwareVsync(true); mScheduler->onScreenReleased(mAppConnectionHandle); } @@ -4652,7 +4658,7 @@ void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& display, hal: getHwComposer().setPowerMode(displayId, mode); } - if (display->isInternal()) { + if (isDisplayActiveLocked(display)) { mTimeStats->setPowerMode(mode); mRefreshRateStats->setPowerMode(mode); mScheduler->setDisplayPowerState(mode == hal::PowerMode::ON); @@ -4831,6 +4837,8 @@ void SurfaceFlinger::dumpVSync(std::string& result) const { mScheduler->dump(mAppConnectionHandle, result); mScheduler->dumpVsync(result); + StringAppendF(&result, "mHWCVsyncPendingState=%s mLastHWCVsyncState=%s\n", + to_string(mHWCVsyncPendingState).c_str(), to_string(mLastHWCVsyncState).c_str()); } void SurfaceFlinger::dumpPlannerInfo(const DumpArgs& args, std::string& result) const { diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index dba2bd6b48..9e2e216964 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -1064,6 +1064,11 @@ private: */ nsecs_t getVsyncPeriodFromHWC() const REQUIRES(mStateLock); + void setHWCVsyncEnabled(PhysicalDisplayId id, hal::Vsync enabled) { + mLastHWCVsyncState = enabled; + getHwComposer().setVsyncEnabled(id, enabled); + } + // Sets the refresh rate by switching active configs, if they are available for // the desired refresh rate. void changeRefreshRateLocked(const RefreshRate&, Scheduler::ModeEvent) REQUIRES(mStateLock); @@ -1422,6 +1427,7 @@ private: std::atomic<nsecs_t> mExpectedPresentTime = 0; nsecs_t mScheduledPresentTime = 0; hal::Vsync mHWCVsyncPendingState = hal::Vsync::DISABLE; + hal::Vsync mLastHWCVsyncState = hal::Vsync::DISABLE; // below flags are set by main thread only bool mSetActiveModePending = false; diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetPowerModeInternalTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetPowerModeInternalTest.cpp index 65024202b8..eea1002236 100644 --- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetPowerModeInternalTest.cpp +++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetPowerModeInternalTest.cpp @@ -260,6 +260,11 @@ struct DisplayPowerCase { auto display = Display::makeFakeExistingDisplayInjector(test); display.inject(); display.mutableDisplayDevice()->setPowerMode(mode); + if (display.mutableDisplayDevice()->isInternal()) { + test->mFlinger.mutableActiveDisplayToken() = + display.mutableDisplayDevice()->getDisplayToken(); + } + return display; } diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h index 40c881e902..a23361e856 100644 --- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h +++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h @@ -442,6 +442,7 @@ public: auto& mutableInternalHwcDisplayId() { return getHwComposer().mInternalHwcDisplayId; } auto& mutableExternalHwcDisplayId() { return getHwComposer().mExternalHwcDisplayId; } auto& mutableUseFrameRateApi() { return mFlinger->useFrameRateApi; } + auto& mutableActiveDisplayToken() { return mFlinger->mActiveDisplayToken; } auto fromHandle(const sp<IBinder>& handle) { return mFlinger->fromHandle(handle); |