Move toggling of kernel idle timer to SF
Idle timer is toggled from the SF code using the following logic:
- If the device policy refresh rate min = max, we turn off the timer.
- If the device policy refresh rate min > the device min,
we turn off the timer.
- Do not toggle the timer if deviceMin == policyMin.
- Timer is on in all other cases.
Bug: 140204874
Bug: 158012424
Bug: 145561154
Test: atest SurfaceFlinger_test
Test: atest libsurfaceflinger_unittest
Test: Select force 90hz through Developer Settings. Toggles timer off.
Test: Low brightness zone. Toggles timer off.
Change-Id: I9858765861a3b13e11c3930be8f77d85dae6c0c0
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index ef315e2..2e01903 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -23,6 +23,7 @@
#include "SurfaceFlinger.h"
+#include <android-base/properties.h>
#include <android/configuration.h>
#include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h>
#include <android/hardware/configstore/1.1/ISurfaceFlingerConfigs.h>
@@ -444,6 +445,9 @@
}
useFrameRateApi = use_frame_rate_api(true);
+
+ mKernelIdleTimerEnabled = mSupportKernelIdleTimer = sysprop::support_kernel_idle_timer(false);
+ base::SetProperty(KERNEL_IDLE_TIMER_PROP, mKernelIdleTimerEnabled ? "true" : "false");
}
SurfaceFlinger::~SurfaceFlinger() = default;
@@ -5355,8 +5359,7 @@
const auto& min = mRefreshRateConfigs->getMinRefreshRate();
if (current != min) {
- const auto kernelTimerEnabled = property_get_bool(KERNEL_IDLE_TIMER_PROP, false);
- const bool timerExpired = kernelTimerEnabled && expired;
+ const bool timerExpired = mKernelIdleTimerEnabled && expired;
if (Mutex::Autolock lock(mStateLock); mRefreshRateOverlay) {
mRefreshRateOverlay->changeRefreshRate(timerExpired ? min : current);
@@ -5366,6 +5369,35 @@
}));
}
+void SurfaceFlinger::toggleKernelIdleTimer() {
+ using KernelIdleTimerAction = scheduler::RefreshRateConfigs::KernelIdleTimerAction;
+
+ // If the support for kernel idle timer is disabled in SF code, don't do anything.
+ if (!mSupportKernelIdleTimer) {
+ return;
+ }
+ const KernelIdleTimerAction action = mRefreshRateConfigs->getIdleTimerAction();
+
+ switch (action) {
+ case KernelIdleTimerAction::TurnOff:
+ if (mKernelIdleTimerEnabled) {
+ ATRACE_INT("KernelIdleTimer", 0);
+ base::SetProperty(KERNEL_IDLE_TIMER_PROP, "false");
+ mKernelIdleTimerEnabled = false;
+ }
+ break;
+ case KernelIdleTimerAction::TurnOn:
+ if (!mKernelIdleTimerEnabled) {
+ ATRACE_INT("KernelIdleTimer", 1);
+ base::SetProperty(KERNEL_IDLE_TIMER_PROP, "true");
+ mKernelIdleTimerEnabled = true;
+ }
+ break;
+ case KernelIdleTimerAction::NoChange:
+ break;
+ }
+}
+
// A simple RAII class to disconnect from an ANativeWindow* when it goes out of scope
class WindowDisconnector {
public:
@@ -5992,14 +6024,14 @@
currentPolicy.primaryRange.max, currentPolicy.appRequestRange.min,
currentPolicy.appRequestRange.max);
- // TODO(b/140204874): This hack triggers a notification that something has changed, so
- // that listeners that care about a change in allowed configs can get the notification.
- // Giving current ActiveConfig so that most other listeners would just drop the event
+ // TODO(b/140204874): Leave the event in until we do proper testing with all apps that might
+ // be depending in this callback.
const nsecs_t vsyncPeriod =
mRefreshRateConfigs->getRefreshRateFromConfigId(display->getActiveConfig())
.getVsyncPeriod();
mScheduler->onPrimaryDisplayConfigChanged(mAppConnectionHandle, display->getId()->value,
display->getActiveConfig(), vsyncPeriod);
+ toggleKernelIdleTimer();
auto configId = mScheduler->getPreferredConfigId();
auto& preferredRefreshRate = configId