Loading services/surfaceflinger/Scheduler/Scheduler.cpp +51 −28 Original line number Diff line number Diff line Loading @@ -76,6 +76,7 @@ Scheduler::Scheduler(impl::EventControlThread::SetVSyncEnabledFunction function, mSupportKernelTimer = support_kernel_idle_timer(false); mSetTouchTimerMs = set_touch_timer_ms(0); mSetDisplayPowerTimerMs = set_display_power_timer_ms(0); char value[PROPERTY_VALUE_MAX]; property_get("debug.sf.set_idle_timer_ms", value, "0"); Loading Loading @@ -105,10 +106,19 @@ Scheduler::Scheduler(impl::EventControlThread::SetVSyncEnabledFunction function, [this] { expiredTouchTimerCallback(); }); mTouchTimer->start(); } if (mSetDisplayPowerTimerMs > 0) { mDisplayPowerTimer = std::make_unique<scheduler::OneShotTimer>( std::chrono::milliseconds(mSetDisplayPowerTimerMs), [this] { resetDisplayPowerTimerCallback(); }, [this] { expiredDisplayPowerTimerCallback(); }); mDisplayPowerTimer->start(); } } Scheduler::~Scheduler() { // Ensure the OneShotTimer threads are joined before we start destroying state. mDisplayPowerTimer.reset(); mTouchTimer.reset(); mIdleTimer.reset(); } Loading Loading @@ -414,8 +424,23 @@ void Scheduler::notifyTouchEvent() { mLayerHistory.clearHistory(); } void Scheduler::setDisplayPowerState(bool normal) { { std::lock_guard<std::mutex> lock(mFeatureStateLock); mIsDisplayPowerStateNormal = normal; } if (mDisplayPowerTimer) { mDisplayPowerTimer->reset(); } // Display Power event will boost the refresh rate to performance. // Clear Layer History to get fresh FPS detection mLayerHistory.clearHistory(); } void Scheduler::resetTimerCallback() { timerChangeRefreshRate(IdleTimerState::RESET); handleTimerStateChanged(&mCurrentIdleTimerState, IdleTimerState::RESET, false); ATRACE_INT("ExpiredIdleTimer", 0); } Loading @@ -428,22 +453,30 @@ void Scheduler::resetKernelTimerCallback() { } void Scheduler::expiredTimerCallback() { timerChangeRefreshRate(IdleTimerState::EXPIRED); handleTimerStateChanged(&mCurrentIdleTimerState, IdleTimerState::EXPIRED, false); ATRACE_INT("ExpiredIdleTimer", 1); } void Scheduler::resetTouchTimerCallback() { // We do not notify the applications about config changes when idle timer is reset. touchChangeRefreshRate(TouchState::ACTIVE); handleTimerStateChanged(&mCurrentTouchState, TouchState::ACTIVE, true); ATRACE_INT("TouchState", 1); } void Scheduler::expiredTouchTimerCallback() { // We do not notify the applications about config changes when idle timer expires. touchChangeRefreshRate(TouchState::INACTIVE); handleTimerStateChanged(&mCurrentTouchState, TouchState::INACTIVE, true); ATRACE_INT("TouchState", 0); } void Scheduler::resetDisplayPowerTimerCallback() { handleTimerStateChanged(&mDisplayPowerTimerState, DisplayPowerTimerState::RESET, true); ATRACE_INT("ExpiredDisplayPowerTimer", 0); } void Scheduler::expiredDisplayPowerTimerCallback() { handleTimerStateChanged(&mDisplayPowerTimerState, DisplayPowerTimerState::EXPIRED, true); ATRACE_INT("ExpiredDisplayPowerTimer", 1); } void Scheduler::expiredKernelTimerCallback() { ATRACE_INT("ExpiredKernelIdleTimer", 1); // Disable HW Vsync if the timer expired, as we don't need it Loading @@ -458,39 +491,23 @@ std::string Scheduler::doDump() { return stream.str(); } void Scheduler::timerChangeRefreshRate(IdleTimerState idleTimerState) { RefreshRateType newRefreshRateType; { std::lock_guard<std::mutex> lock(mFeatureStateLock); if (mCurrentIdleTimerState == idleTimerState) { return; } mCurrentIdleTimerState = idleTimerState; newRefreshRateType = calculateRefreshRateType(); if (mRefreshRateType == newRefreshRateType) { return; } mRefreshRateType = newRefreshRateType; } changeRefreshRate(newRefreshRateType, ConfigEvent::None); } void Scheduler::touchChangeRefreshRate(TouchState touchState) { template <class T> void Scheduler::handleTimerStateChanged(T* currentState, T newState, bool eventOnContentDetection) { ConfigEvent event = ConfigEvent::None; RefreshRateType newRefreshRateType; { std::lock_guard<std::mutex> lock(mFeatureStateLock); if (mCurrentTouchState == touchState) { if (*currentState == newState) { return; } mCurrentTouchState = touchState; *currentState = newState; newRefreshRateType = calculateRefreshRateType(); if (mRefreshRateType == newRefreshRateType) { return; } mRefreshRateType = newRefreshRateType; // Send an event in case that content detection is on as touch has a higher priority if (mCurrentContentFeatureState == ContentFeatureState::CONTENT_DETECTION_ON) { if (eventOnContentDetection && mCurrentContentFeatureState == ContentFeatureState::CONTENT_DETECTION_ON) { event = ConfigEvent::Changed; } } Loading @@ -503,6 +520,12 @@ Scheduler::RefreshRateType Scheduler::calculateRefreshRateType() { return RefreshRateType::DEFAULT; } // 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 (!mIsDisplayPowerStateNormal || mDisplayPowerTimerState == DisplayPowerTimerState::RESET) { return RefreshRateType::PERFORMANCE; } // As long as touch is active we want to be in performance mode if (mCurrentTouchState == TouchState::ACTIVE) { return RefreshRateType::PERFORMANCE; Loading services/surfaceflinger/Scheduler/Scheduler.h +18 −4 Original line number Diff line number Diff line Loading @@ -177,6 +177,9 @@ public: // Function that resets the touch timer. void notifyTouchEvent(); // Function that sets whether display power mode is normal or not. void setDisplayPowerState(bool normal); // Returns relevant information about Scheduler for dumpsys purposes. std::string doDump(); Loading @@ -197,6 +200,7 @@ private: enum class ContentFeatureState { CONTENT_DETECTION_ON, CONTENT_DETECTION_OFF }; enum class IdleTimerState { EXPIRED, RESET }; enum class TouchState { INACTIVE, ACTIVE }; enum class DisplayPowerTimerState { EXPIRED, RESET }; // Creates a connection on the given EventThread and forwards the given callbacks. sp<EventThreadConnection> createConnectionInternal(EventThread*, ResyncCallback&&, Loading @@ -221,12 +225,15 @@ private: void resetTouchTimerCallback(); // Function that is called when the touch timer expires. void expiredTouchTimerCallback(); // Function that is called when the display power timer resets. void resetDisplayPowerTimerCallback(); // Function that is called when the display power timer expires. void expiredDisplayPowerTimerCallback(); // Sets vsync period. void setVsyncPeriod(const nsecs_t period); // Idle timer feature's function to change the refresh rate. void timerChangeRefreshRate(IdleTimerState idleTimerState); // Touch timer feature's function to change the refresh rate. void touchChangeRefreshRate(TouchState touchState); // handles various timer features to change the refresh rate. template <class T> void handleTimerStateChanged(T* currentState, T newState, bool eventOnContentDetection); // Calculate the new refresh rate type RefreshRateType calculateRefreshRateType() REQUIRES(mFeatureStateLock); // Acquires a lock and calls the ChangeRefreshRateCallback() with given parameters. Loading Loading @@ -282,6 +289,10 @@ private: int64_t mSetTouchTimerMs = 0; std::unique_ptr<scheduler::OneShotTimer> mTouchTimer; // Timer used to monitor display power mode. int64_t mSetDisplayPowerTimerMs = 0; std::unique_ptr<scheduler::OneShotTimer> mDisplayPowerTimer; std::mutex mCallbackLock; ChangeRefreshRateCallback mChangeRefreshRateCallback GUARDED_BY(mCallbackLock); GetVsyncPeriod mGetVsyncPeriod GUARDED_BY(mCallbackLock); Loading @@ -293,9 +304,12 @@ private: ContentFeatureState::CONTENT_DETECTION_OFF; IdleTimerState mCurrentIdleTimerState GUARDED_BY(mFeatureStateLock) = IdleTimerState::RESET; TouchState mCurrentTouchState GUARDED_BY(mFeatureStateLock) = TouchState::INACTIVE; DisplayPowerTimerState mDisplayPowerTimerState GUARDED_BY(mFeatureStateLock) = DisplayPowerTimerState::EXPIRED; uint32_t mContentRefreshRate GUARDED_BY(mFeatureStateLock); RefreshRateType mRefreshRateType GUARDED_BY(mFeatureStateLock); bool mIsHDRContent GUARDED_BY(mFeatureStateLock) = false; bool mIsDisplayPowerStateNormal GUARDED_BY(mFeatureStateLock) = true; const scheduler::RefreshRateConfigs& mRefreshRateConfigs; Loading services/surfaceflinger/SurfaceFlinger.cpp +1 −0 Original line number Diff line number Diff line Loading @@ -4542,6 +4542,7 @@ void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& display, int if (display->isPrimary()) { mTimeStats->setPowerMode(mode); mRefreshRateStats.setPowerMode(mode); mScheduler->setDisplayPowerState(mode == HWC_POWER_MODE_NORMAL); } ALOGD("Finished setting power mode %d on display %s", mode, to_string(*displayId).c_str()); Loading services/surfaceflinger/SurfaceFlingerProperties.cpp +8 −0 Original line number Diff line number Diff line Loading @@ -242,6 +242,14 @@ int32_t set_touch_timer_ms(int32_t defaultValue) { return defaultValue; } int32_t set_display_power_timer_ms(int32_t defaultValue) { auto temp = SurfaceFlingerProperties::set_display_power_timer_ms(); if (temp.has_value()) { return *temp; } return defaultValue; } bool use_smart_90_for_video(bool defaultValue) { auto temp = SurfaceFlingerProperties::use_smart_90_for_video(); if (temp.has_value()) { Loading services/surfaceflinger/SurfaceFlingerProperties.h +2 −0 Original line number Diff line number Diff line Loading @@ -77,6 +77,8 @@ int32_t set_idle_timer_ms(int32_t defaultValue); int32_t set_touch_timer_ms(int32_t defaultValue); int32_t set_display_power_timer_ms(int32_t defaultValue); bool use_smart_90_for_video(bool defaultValue); bool enable_protected_contents(bool defaultValue); Loading Loading
services/surfaceflinger/Scheduler/Scheduler.cpp +51 −28 Original line number Diff line number Diff line Loading @@ -76,6 +76,7 @@ Scheduler::Scheduler(impl::EventControlThread::SetVSyncEnabledFunction function, mSupportKernelTimer = support_kernel_idle_timer(false); mSetTouchTimerMs = set_touch_timer_ms(0); mSetDisplayPowerTimerMs = set_display_power_timer_ms(0); char value[PROPERTY_VALUE_MAX]; property_get("debug.sf.set_idle_timer_ms", value, "0"); Loading Loading @@ -105,10 +106,19 @@ Scheduler::Scheduler(impl::EventControlThread::SetVSyncEnabledFunction function, [this] { expiredTouchTimerCallback(); }); mTouchTimer->start(); } if (mSetDisplayPowerTimerMs > 0) { mDisplayPowerTimer = std::make_unique<scheduler::OneShotTimer>( std::chrono::milliseconds(mSetDisplayPowerTimerMs), [this] { resetDisplayPowerTimerCallback(); }, [this] { expiredDisplayPowerTimerCallback(); }); mDisplayPowerTimer->start(); } } Scheduler::~Scheduler() { // Ensure the OneShotTimer threads are joined before we start destroying state. mDisplayPowerTimer.reset(); mTouchTimer.reset(); mIdleTimer.reset(); } Loading Loading @@ -414,8 +424,23 @@ void Scheduler::notifyTouchEvent() { mLayerHistory.clearHistory(); } void Scheduler::setDisplayPowerState(bool normal) { { std::lock_guard<std::mutex> lock(mFeatureStateLock); mIsDisplayPowerStateNormal = normal; } if (mDisplayPowerTimer) { mDisplayPowerTimer->reset(); } // Display Power event will boost the refresh rate to performance. // Clear Layer History to get fresh FPS detection mLayerHistory.clearHistory(); } void Scheduler::resetTimerCallback() { timerChangeRefreshRate(IdleTimerState::RESET); handleTimerStateChanged(&mCurrentIdleTimerState, IdleTimerState::RESET, false); ATRACE_INT("ExpiredIdleTimer", 0); } Loading @@ -428,22 +453,30 @@ void Scheduler::resetKernelTimerCallback() { } void Scheduler::expiredTimerCallback() { timerChangeRefreshRate(IdleTimerState::EXPIRED); handleTimerStateChanged(&mCurrentIdleTimerState, IdleTimerState::EXPIRED, false); ATRACE_INT("ExpiredIdleTimer", 1); } void Scheduler::resetTouchTimerCallback() { // We do not notify the applications about config changes when idle timer is reset. touchChangeRefreshRate(TouchState::ACTIVE); handleTimerStateChanged(&mCurrentTouchState, TouchState::ACTIVE, true); ATRACE_INT("TouchState", 1); } void Scheduler::expiredTouchTimerCallback() { // We do not notify the applications about config changes when idle timer expires. touchChangeRefreshRate(TouchState::INACTIVE); handleTimerStateChanged(&mCurrentTouchState, TouchState::INACTIVE, true); ATRACE_INT("TouchState", 0); } void Scheduler::resetDisplayPowerTimerCallback() { handleTimerStateChanged(&mDisplayPowerTimerState, DisplayPowerTimerState::RESET, true); ATRACE_INT("ExpiredDisplayPowerTimer", 0); } void Scheduler::expiredDisplayPowerTimerCallback() { handleTimerStateChanged(&mDisplayPowerTimerState, DisplayPowerTimerState::EXPIRED, true); ATRACE_INT("ExpiredDisplayPowerTimer", 1); } void Scheduler::expiredKernelTimerCallback() { ATRACE_INT("ExpiredKernelIdleTimer", 1); // Disable HW Vsync if the timer expired, as we don't need it Loading @@ -458,39 +491,23 @@ std::string Scheduler::doDump() { return stream.str(); } void Scheduler::timerChangeRefreshRate(IdleTimerState idleTimerState) { RefreshRateType newRefreshRateType; { std::lock_guard<std::mutex> lock(mFeatureStateLock); if (mCurrentIdleTimerState == idleTimerState) { return; } mCurrentIdleTimerState = idleTimerState; newRefreshRateType = calculateRefreshRateType(); if (mRefreshRateType == newRefreshRateType) { return; } mRefreshRateType = newRefreshRateType; } changeRefreshRate(newRefreshRateType, ConfigEvent::None); } void Scheduler::touchChangeRefreshRate(TouchState touchState) { template <class T> void Scheduler::handleTimerStateChanged(T* currentState, T newState, bool eventOnContentDetection) { ConfigEvent event = ConfigEvent::None; RefreshRateType newRefreshRateType; { std::lock_guard<std::mutex> lock(mFeatureStateLock); if (mCurrentTouchState == touchState) { if (*currentState == newState) { return; } mCurrentTouchState = touchState; *currentState = newState; newRefreshRateType = calculateRefreshRateType(); if (mRefreshRateType == newRefreshRateType) { return; } mRefreshRateType = newRefreshRateType; // Send an event in case that content detection is on as touch has a higher priority if (mCurrentContentFeatureState == ContentFeatureState::CONTENT_DETECTION_ON) { if (eventOnContentDetection && mCurrentContentFeatureState == ContentFeatureState::CONTENT_DETECTION_ON) { event = ConfigEvent::Changed; } } Loading @@ -503,6 +520,12 @@ Scheduler::RefreshRateType Scheduler::calculateRefreshRateType() { return RefreshRateType::DEFAULT; } // 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 (!mIsDisplayPowerStateNormal || mDisplayPowerTimerState == DisplayPowerTimerState::RESET) { return RefreshRateType::PERFORMANCE; } // As long as touch is active we want to be in performance mode if (mCurrentTouchState == TouchState::ACTIVE) { return RefreshRateType::PERFORMANCE; Loading
services/surfaceflinger/Scheduler/Scheduler.h +18 −4 Original line number Diff line number Diff line Loading @@ -177,6 +177,9 @@ public: // Function that resets the touch timer. void notifyTouchEvent(); // Function that sets whether display power mode is normal or not. void setDisplayPowerState(bool normal); // Returns relevant information about Scheduler for dumpsys purposes. std::string doDump(); Loading @@ -197,6 +200,7 @@ private: enum class ContentFeatureState { CONTENT_DETECTION_ON, CONTENT_DETECTION_OFF }; enum class IdleTimerState { EXPIRED, RESET }; enum class TouchState { INACTIVE, ACTIVE }; enum class DisplayPowerTimerState { EXPIRED, RESET }; // Creates a connection on the given EventThread and forwards the given callbacks. sp<EventThreadConnection> createConnectionInternal(EventThread*, ResyncCallback&&, Loading @@ -221,12 +225,15 @@ private: void resetTouchTimerCallback(); // Function that is called when the touch timer expires. void expiredTouchTimerCallback(); // Function that is called when the display power timer resets. void resetDisplayPowerTimerCallback(); // Function that is called when the display power timer expires. void expiredDisplayPowerTimerCallback(); // Sets vsync period. void setVsyncPeriod(const nsecs_t period); // Idle timer feature's function to change the refresh rate. void timerChangeRefreshRate(IdleTimerState idleTimerState); // Touch timer feature's function to change the refresh rate. void touchChangeRefreshRate(TouchState touchState); // handles various timer features to change the refresh rate. template <class T> void handleTimerStateChanged(T* currentState, T newState, bool eventOnContentDetection); // Calculate the new refresh rate type RefreshRateType calculateRefreshRateType() REQUIRES(mFeatureStateLock); // Acquires a lock and calls the ChangeRefreshRateCallback() with given parameters. Loading Loading @@ -282,6 +289,10 @@ private: int64_t mSetTouchTimerMs = 0; std::unique_ptr<scheduler::OneShotTimer> mTouchTimer; // Timer used to monitor display power mode. int64_t mSetDisplayPowerTimerMs = 0; std::unique_ptr<scheduler::OneShotTimer> mDisplayPowerTimer; std::mutex mCallbackLock; ChangeRefreshRateCallback mChangeRefreshRateCallback GUARDED_BY(mCallbackLock); GetVsyncPeriod mGetVsyncPeriod GUARDED_BY(mCallbackLock); Loading @@ -293,9 +304,12 @@ private: ContentFeatureState::CONTENT_DETECTION_OFF; IdleTimerState mCurrentIdleTimerState GUARDED_BY(mFeatureStateLock) = IdleTimerState::RESET; TouchState mCurrentTouchState GUARDED_BY(mFeatureStateLock) = TouchState::INACTIVE; DisplayPowerTimerState mDisplayPowerTimerState GUARDED_BY(mFeatureStateLock) = DisplayPowerTimerState::EXPIRED; uint32_t mContentRefreshRate GUARDED_BY(mFeatureStateLock); RefreshRateType mRefreshRateType GUARDED_BY(mFeatureStateLock); bool mIsHDRContent GUARDED_BY(mFeatureStateLock) = false; bool mIsDisplayPowerStateNormal GUARDED_BY(mFeatureStateLock) = true; const scheduler::RefreshRateConfigs& mRefreshRateConfigs; Loading
services/surfaceflinger/SurfaceFlinger.cpp +1 −0 Original line number Diff line number Diff line Loading @@ -4542,6 +4542,7 @@ void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& display, int if (display->isPrimary()) { mTimeStats->setPowerMode(mode); mRefreshRateStats.setPowerMode(mode); mScheduler->setDisplayPowerState(mode == HWC_POWER_MODE_NORMAL); } ALOGD("Finished setting power mode %d on display %s", mode, to_string(*displayId).c_str()); Loading
services/surfaceflinger/SurfaceFlingerProperties.cpp +8 −0 Original line number Diff line number Diff line Loading @@ -242,6 +242,14 @@ int32_t set_touch_timer_ms(int32_t defaultValue) { return defaultValue; } int32_t set_display_power_timer_ms(int32_t defaultValue) { auto temp = SurfaceFlingerProperties::set_display_power_timer_ms(); if (temp.has_value()) { return *temp; } return defaultValue; } bool use_smart_90_for_video(bool defaultValue) { auto temp = SurfaceFlingerProperties::use_smart_90_for_video(); if (temp.has_value()) { Loading
services/surfaceflinger/SurfaceFlingerProperties.h +2 −0 Original line number Diff line number Diff line Loading @@ -77,6 +77,8 @@ int32_t set_idle_timer_ms(int32_t defaultValue); int32_t set_touch_timer_ms(int32_t defaultValue); int32_t set_display_power_timer_ms(int32_t defaultValue); bool use_smart_90_for_video(bool defaultValue); bool enable_protected_contents(bool defaultValue); Loading