Merge "SurfaceFlinger: update the refresh rate overlay based on kernel idle timer" into rvc-dev
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index 3a44332..a0d63ba 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -512,6 +512,8 @@
// need to update the DispSync model anyway.
disableHardwareVsync(false /* makeUnavailable */);
}
+
+ mSchedulerCallback.kernelTimerChanged(state == TimerState::Expired);
}
void Scheduler::idleTimerCallback(TimerState state) {
diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h
index 46d1a5e..6ffda78 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.h
+++ b/services/surfaceflinger/Scheduler/Scheduler.h
@@ -51,6 +51,7 @@
virtual void changeRefreshRate(const scheduler::RefreshRateConfigs::RefreshRate&,
scheduler::RefreshRateConfigEvent) = 0;
virtual void repaintEverythingForHWC() = 0;
+ virtual void kernelTimerChanged(bool expired) = 0;
};
class Scheduler {
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index ce0a8a1..cf5e0ec 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -216,6 +216,7 @@
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;
@@ -5106,6 +5107,36 @@
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:
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index c79621b..07232d4 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -524,6 +524,8 @@
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
*/
diff --git a/services/surfaceflinger/tests/unittests/TestableScheduler.h b/services/surfaceflinger/tests/unittests/TestableScheduler.h
index 52da34b..b0b51bd 100644
--- a/services/surfaceflinger/tests/unittests/TestableScheduler.h
+++ b/services/surfaceflinger/tests/unittests/TestableScheduler.h
@@ -92,6 +92,7 @@
private:
void changeRefreshRate(const RefreshRate&, ConfigEvent) override {}
void repaintEverythingForHWC() override {}
+ void kernelTimerChanged(bool /*expired*/) override {}
};
} // namespace android