Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a09852aa authored by Ady Abraham's avatar Ady Abraham
Browse files

SurfaceFlinger: update the refresh rate overlay based on kernel idle timer

The frameworks maintains its own copy of inactivity timer to track the
kernel idle timer. Update the refresh rate overlay based on that timer.

Test: Enable refresh rate overlay from developer options
Bug: 149710432
Change-Id: I6c50d64575149317106f72fecdd50cef4e08db6a
parent 57cabaca
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -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) {
+1 −0
Original line number Diff line number Diff line
@@ -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 {
+31 −0
Original line number Diff line number Diff line
@@ -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;
@@ -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:
+2 −0
Original line number Diff line number Diff line
@@ -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
     */
+1 −0
Original line number Diff line number Diff line
@@ -92,6 +92,7 @@ public:
private:
    void changeRefreshRate(const RefreshRate&, ConfigEvent) override {}
    void repaintEverythingForHWC() override {}
    void kernelTimerChanged(bool /*expired*/) override {}
};

} // namespace android