Loading services/surfaceflinger/Scheduler/Scheduler.cpp +2 −0 Original line number Diff line number Diff line Loading @@ -512,6 +512,8 @@ void Scheduler::kernelIdleTimerCallback(TimerState state) { // need to update the DispSync model anyway. disableHardwareVsync(false /* makeUnavailable */); } mSchedulerCallback.kernelTimerChanged(state == TimerState::Expired); } void Scheduler::idleTimerCallback(TimerState state) { Loading services/surfaceflinger/Scheduler/Scheduler.h +1 −0 Original line number Diff line number Diff line Loading @@ -51,6 +51,7 @@ public: virtual void changeRefreshRate(const scheduler::RefreshRateConfigs::RefreshRate&, scheduler::RefreshRateConfigEvent) = 0; virtual void repaintEverythingForHWC() = 0; virtual void kernelTimerChanged(bool expired) = 0; }; class Scheduler { Loading services/surfaceflinger/SurfaceFlinger.cpp +31 −0 Original line number Diff line number Diff line Loading @@ -216,6 +216,7 @@ const String16 sHardwareTest("android.permission.HARDWARE_TEST"); const String16 sAccessSurfaceFlinger("android.permission.ACCESS_SURFACE_FLINGER"); const String16 sReadFramebuffer("android.permission.READ_FRAME_BUFFER"); const String16 sDump("android.permission.DUMP"); const char* KERNEL_IDLE_TIMER_PROP = "vendor.display.enable_kernel_idle_timer"; // --------------------------------------------------------------------------- int64_t SurfaceFlinger::dispSyncPresentTimeOffset; Loading Loading @@ -5106,6 +5107,36 @@ void SurfaceFlinger::repaintEverythingForHWC() { mEventQueue->invalidate(); } void SurfaceFlinger::kernelTimerChanged(bool expired) { static bool updateOverlay = property_get_bool("debug.sf.kernel_idle_timer_update_overlay", true); if (!updateOverlay || !mRefreshRateOverlay) return; // Update the overlay on the main thread to avoid race conditions with // mRefreshRateConfigs->getCurrentRefreshRate() postMessageAsync(new LambdaMessage([this, expired]() NO_THREAD_SAFETY_ANALYSIS { if (mRefreshRateOverlay) { const auto kernelTimerEnabled = property_get_bool(KERNEL_IDLE_TIMER_PROP, false); const bool timerExpired = kernelTimerEnabled && expired; const auto& current = [this]() { std::lock_guard<std::mutex> lock(mActiveConfigLock); if (mDesiredActiveConfigChanged) { return mRefreshRateConfigs->getRefreshRateFromConfigId( mDesiredActiveConfig.configId); } return mRefreshRateConfigs->getCurrentRefreshRate(); }(); const auto& min = mRefreshRateConfigs->getMinRefreshRate(); if (current != min) { mRefreshRateOverlay->changeRefreshRate(timerExpired ? min : current); mEventQueue->invalidate(); } } })); } // A simple RAII class to disconnect from an ANativeWindow* when it goes out of scope class WindowDisconnector { public: Loading services/surfaceflinger/SurfaceFlinger.h +2 −0 Original line number Diff line number Diff line Loading @@ -524,6 +524,8 @@ private: void changeRefreshRate(const Scheduler::RefreshRate&, Scheduler::ConfigEvent) override; // force full composition on all displays without resetting the scheduler idle timer. void repaintEverythingForHWC() override; // Called when kernel idle timer has expired. Used to update the refresh rate overlay. void kernelTimerChanged(bool expired) override; /* ------------------------------------------------------------------------ * Message handling */ Loading services/surfaceflinger/tests/unittests/TestableScheduler.h +1 −0 Original line number Diff line number Diff line Loading @@ -92,6 +92,7 @@ public: private: void changeRefreshRate(const RefreshRate&, ConfigEvent) override {} void repaintEverythingForHWC() override {} void kernelTimerChanged(bool /*expired*/) override {} }; } // namespace android Loading
services/surfaceflinger/Scheduler/Scheduler.cpp +2 −0 Original line number Diff line number Diff line Loading @@ -512,6 +512,8 @@ void Scheduler::kernelIdleTimerCallback(TimerState state) { // need to update the DispSync model anyway. disableHardwareVsync(false /* makeUnavailable */); } mSchedulerCallback.kernelTimerChanged(state == TimerState::Expired); } void Scheduler::idleTimerCallback(TimerState state) { Loading
services/surfaceflinger/Scheduler/Scheduler.h +1 −0 Original line number Diff line number Diff line Loading @@ -51,6 +51,7 @@ public: virtual void changeRefreshRate(const scheduler::RefreshRateConfigs::RefreshRate&, scheduler::RefreshRateConfigEvent) = 0; virtual void repaintEverythingForHWC() = 0; virtual void kernelTimerChanged(bool expired) = 0; }; class Scheduler { Loading
services/surfaceflinger/SurfaceFlinger.cpp +31 −0 Original line number Diff line number Diff line Loading @@ -216,6 +216,7 @@ const String16 sHardwareTest("android.permission.HARDWARE_TEST"); const String16 sAccessSurfaceFlinger("android.permission.ACCESS_SURFACE_FLINGER"); const String16 sReadFramebuffer("android.permission.READ_FRAME_BUFFER"); const String16 sDump("android.permission.DUMP"); const char* KERNEL_IDLE_TIMER_PROP = "vendor.display.enable_kernel_idle_timer"; // --------------------------------------------------------------------------- int64_t SurfaceFlinger::dispSyncPresentTimeOffset; Loading Loading @@ -5106,6 +5107,36 @@ void SurfaceFlinger::repaintEverythingForHWC() { mEventQueue->invalidate(); } void SurfaceFlinger::kernelTimerChanged(bool expired) { static bool updateOverlay = property_get_bool("debug.sf.kernel_idle_timer_update_overlay", true); if (!updateOverlay || !mRefreshRateOverlay) return; // Update the overlay on the main thread to avoid race conditions with // mRefreshRateConfigs->getCurrentRefreshRate() postMessageAsync(new LambdaMessage([this, expired]() NO_THREAD_SAFETY_ANALYSIS { if (mRefreshRateOverlay) { const auto kernelTimerEnabled = property_get_bool(KERNEL_IDLE_TIMER_PROP, false); const bool timerExpired = kernelTimerEnabled && expired; const auto& current = [this]() { std::lock_guard<std::mutex> lock(mActiveConfigLock); if (mDesiredActiveConfigChanged) { return mRefreshRateConfigs->getRefreshRateFromConfigId( mDesiredActiveConfig.configId); } return mRefreshRateConfigs->getCurrentRefreshRate(); }(); const auto& min = mRefreshRateConfigs->getMinRefreshRate(); if (current != min) { mRefreshRateOverlay->changeRefreshRate(timerExpired ? min : current); mEventQueue->invalidate(); } } })); } // A simple RAII class to disconnect from an ANativeWindow* when it goes out of scope class WindowDisconnector { public: Loading
services/surfaceflinger/SurfaceFlinger.h +2 −0 Original line number Diff line number Diff line Loading @@ -524,6 +524,8 @@ private: void changeRefreshRate(const Scheduler::RefreshRate&, Scheduler::ConfigEvent) override; // force full composition on all displays without resetting the scheduler idle timer. void repaintEverythingForHWC() override; // Called when kernel idle timer has expired. Used to update the refresh rate overlay. void kernelTimerChanged(bool expired) override; /* ------------------------------------------------------------------------ * Message handling */ Loading
services/surfaceflinger/tests/unittests/TestableScheduler.h +1 −0 Original line number Diff line number Diff line Loading @@ -92,6 +92,7 @@ public: private: void changeRefreshRate(const RefreshRate&, ConfigEvent) override {} void repaintEverythingForHWC() override {} void kernelTimerChanged(bool /*expired*/) override {} }; } // namespace android