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

Commit 3a80a38f authored by Dominik Laskowski's avatar Dominik Laskowski
Browse files

SF: Deduplicate scheduler timer callbacks

Bug: 130554049
Test: Boot
Change-Id: I3934b90176b22bbe83480dd4e2c87374876f818b
parent d932dc73
Loading
Loading
Loading
Loading
+34 −52
Original line number Diff line number Diff line
@@ -89,12 +89,13 @@ Scheduler::Scheduler(impl::EventControlThread::SetVSyncEnabledFunction function,
        if (mSupportKernelTimer) {
            mIdleTimer = std::make_unique<scheduler::OneShotTimer>(
                    std::chrono::milliseconds(mSetIdleTimerMs),
                    [this] { resetKernelTimerCallback(); },
                    [this] { expiredKernelTimerCallback(); });
                    [this] { kernelIdleTimerCallback(TimerState::RESET); },
                    [this] { kernelIdleTimerCallback(TimerState::EXPIRED); });
        } else {
            mIdleTimer = std::make_unique<scheduler::OneShotTimer>(
                    std::chrono::milliseconds(mSetIdleTimerMs), [this] { resetTimerCallback(); },
                    [this] { expiredTimerCallback(); });
                    std::chrono::milliseconds(mSetIdleTimerMs),
                    [this] { idleTimerCallback(TimerState::RESET); },
                    [this] { idleTimerCallback(TimerState::EXPIRED); });
        }
        mIdleTimer->start();
    }
@@ -102,16 +103,17 @@ Scheduler::Scheduler(impl::EventControlThread::SetVSyncEnabledFunction function,
    if (mSetTouchTimerMs > 0) {
        // Touch events are coming to SF every 100ms, so the timer needs to be higher than that
        mTouchTimer = std::make_unique<scheduler::OneShotTimer>(
                std::chrono::milliseconds(mSetTouchTimerMs), [this] { resetTouchTimerCallback(); },
                [this] { expiredTouchTimerCallback(); });
                std::chrono::milliseconds(mSetTouchTimerMs),
                [this] { touchTimerCallback(TimerState::RESET); },
                [this] { touchTimerCallback(TimerState::EXPIRED); });
        mTouchTimer->start();
    }

    if (mSetDisplayPowerTimerMs > 0) {
        mDisplayPowerTimer = std::make_unique<scheduler::OneShotTimer>(
                std::chrono::milliseconds(mSetDisplayPowerTimerMs),
                [this] { resetDisplayPowerTimerCallback(); },
                [this] { expiredDisplayPowerTimerCallback(); });
                [this] { displayPowerTimerCallback(TimerState::RESET); },
                [this] { displayPowerTimerCallback(TimerState::EXPIRED); });
        mDisplayPowerTimer->start();
    }
}
@@ -445,60 +447,40 @@ void Scheduler::setDisplayPowerState(bool normal) {
    mLayerHistory.clearHistory();
}

void Scheduler::resetTimerCallback() {
    handleTimerStateChanged(&mCurrentIdleTimerState, IdleTimerState::RESET, false);
    ATRACE_INT("ExpiredIdleTimer", 0);
}
void Scheduler::kernelIdleTimerCallback(TimerState state) {
    ATRACE_INT("ExpiredKernelIdleTimer", static_cast<int>(state));

void Scheduler::resetKernelTimerCallback() {
    ATRACE_INT("ExpiredKernelIdleTimer", 0);
    std::lock_guard<std::mutex> lock(mCallbackLock);
    if (mGetVsyncPeriod && mGetCurrentRefreshRateTypeCallback) {
    if (!mGetCurrentRefreshRateTypeCallback || !mGetVsyncPeriod) return;

    const auto type = mGetCurrentRefreshRateTypeCallback();
    if (state == TimerState::RESET && type == RefreshRateType::PERFORMANCE) {
        // If we're not in performance mode then the kernel timer shouldn't do
        // anything, as the refresh rate during DPU power collapse will be the
        // same.
        if (mGetCurrentRefreshRateTypeCallback() == Scheduler::RefreshRateType::PERFORMANCE) {
            resyncToHardwareVsync(true, mGetVsyncPeriod());
        }
    }
}

void Scheduler::expiredTimerCallback() {
    handleTimerStateChanged(&mCurrentIdleTimerState, IdleTimerState::EXPIRED, false);
    ATRACE_INT("ExpiredIdleTimer", 1);
        resyncToHardwareVsync(true /* makeAvailable */, mGetVsyncPeriod());
    } else if (state == TimerState::EXPIRED && type != RefreshRateType::PERFORMANCE) {
        // Disable HW VSYNC if the timer expired, as we don't need it enabled if
        // we're not pushing frames, and if we're in PERFORMANCE mode then we'll
        // need to update the DispSync model anyway.
        disableHardwareVsync(false /* makeUnavailable */);
    }

void Scheduler::resetTouchTimerCallback() {
    handleTimerStateChanged(&mCurrentTouchState, TouchState::ACTIVE, true);
    ATRACE_INT("TouchState", 1);
}

void Scheduler::expiredTouchTimerCallback() {
    handleTimerStateChanged(&mCurrentTouchState, TouchState::INACTIVE, true);
    ATRACE_INT("TouchState", 0);
}

void Scheduler::resetDisplayPowerTimerCallback() {
    handleTimerStateChanged(&mDisplayPowerTimerState, DisplayPowerTimerState::RESET, true);
    ATRACE_INT("ExpiredDisplayPowerTimer", 0);
void Scheduler::idleTimerCallback(TimerState state) {
    handleTimerStateChanged(&mCurrentIdleTimerState, state, false /* eventOnContentDetection */);
    ATRACE_INT("ExpiredIdleTimer", static_cast<int>(state));
}

void Scheduler::expiredDisplayPowerTimerCallback() {
    handleTimerStateChanged(&mDisplayPowerTimerState, DisplayPowerTimerState::EXPIRED, true);
    ATRACE_INT("ExpiredDisplayPowerTimer", 1);
void Scheduler::touchTimerCallback(TimerState state) {
    const TouchState touch = state == TimerState::RESET ? TouchState::ACTIVE : TouchState::INACTIVE;
    handleTimerStateChanged(&mCurrentTouchState, touch, true /* eventOnContentDetection */);
    ATRACE_INT("TouchState", static_cast<int>(touch));
}

void Scheduler::expiredKernelTimerCallback() {
    std::lock_guard<std::mutex> lock(mCallbackLock);
    ATRACE_INT("ExpiredKernelIdleTimer", 1);
    if (mGetCurrentRefreshRateTypeCallback) {
        if (mGetCurrentRefreshRateTypeCallback() != Scheduler::RefreshRateType::PERFORMANCE) {
            // Disable HW Vsync if the timer expired, as we don't need it
            // enabled if we're not pushing frames, and if we're in PERFORMANCE
            // mode then we'll need to re-update the DispSync model anyways.
            disableHardwareVsync(false);
        }
    }
void Scheduler::displayPowerTimerCallback(TimerState state) {
    handleTimerStateChanged(&mDisplayPowerTimerState, state, true /* eventOnContentDetection */);
    ATRACE_INT("ExpiredDisplayPowerTimer", static_cast<int>(state));
}

std::string Scheduler::doDump() {
@@ -539,7 +521,7 @@ Scheduler::RefreshRateType Scheduler::calculateRefreshRateType() {

    // 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) {
    if (!mIsDisplayPowerStateNormal || mDisplayPowerTimerState == TimerState::RESET) {
        return RefreshRateType::PERFORMANCE;
    }

@@ -549,7 +531,7 @@ Scheduler::RefreshRateType Scheduler::calculateRefreshRateType() {
    }

    // If timer has expired as it means there is no new content on the screen
    if (mCurrentIdleTimerState == IdleTimerState::EXPIRED) {
    if (mCurrentIdleTimerState == TimerState::EXPIRED) {
        return RefreshRateType::DEFAULT;
    }

+10 −26
Original line number Diff line number Diff line
@@ -200,10 +200,9 @@ private:

    // In order to make sure that the features don't override themselves, we need a state machine
    // to keep track which feature requested the config change.
    enum class ContentFeatureState { CONTENT_DETECTION_ON, CONTENT_DETECTION_OFF };
    enum class IdleTimerState { EXPIRED, RESET };
    enum class ContentFeatureState { CONTENT_DETECTION_OFF, CONTENT_DETECTION_ON };
    enum class TimerState { RESET, EXPIRED };
    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&&,
@@ -212,26 +211,12 @@ private:
    nsecs_t calculateAverage() const;
    void updateFrameSkipping(const int64_t skipCount);

    // Function that is called when the timer resets.
    void resetTimerCallback();
    // Function that is called when the timer expires.
    void expiredTimerCallback();
    // Function that is called when the timer resets when paired with a display
    // driver timeout in the kernel. This enables hardware vsync when we move
    // out from idle.
    void resetKernelTimerCallback();
    // Function that is called when the timer expires when paired with a display
    // driver timeout in the kernel. This disables hardware vsync when we move
    // into idle.
    void expiredKernelTimerCallback();
    // Function that is called when the touch timer resets.
    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();
    // Update feature state machine to given state when corresponding timer resets or expires.
    void kernelIdleTimerCallback(TimerState);
    void idleTimerCallback(TimerState);
    void touchTimerCallback(TimerState);
    void displayPowerTimerCallback(TimerState);

    // Sets vsync period.
    void setVsyncPeriod(const nsecs_t period);
    // handles various timer features to change the refresh rate.
@@ -306,10 +291,9 @@ private:
    std::mutex mFeatureStateLock;
    ContentFeatureState mCurrentContentFeatureState GUARDED_BY(mFeatureStateLock) =
            ContentFeatureState::CONTENT_DETECTION_OFF;
    IdleTimerState mCurrentIdleTimerState GUARDED_BY(mFeatureStateLock) = IdleTimerState::RESET;
    TimerState mCurrentIdleTimerState GUARDED_BY(mFeatureStateLock) = TimerState::RESET;
    TouchState mCurrentTouchState GUARDED_BY(mFeatureStateLock) = TouchState::INACTIVE;
    DisplayPowerTimerState mDisplayPowerTimerState GUARDED_BY(mFeatureStateLock) =
            DisplayPowerTimerState::EXPIRED;
    TimerState mDisplayPowerTimerState GUARDED_BY(mFeatureStateLock) = TimerState::EXPIRED;
    uint32_t mContentRefreshRate GUARDED_BY(mFeatureStateLock);
    RefreshRateType mRefreshRateType GUARDED_BY(mFeatureStateLock);
    bool mIsHDRContent GUARDED_BY(mFeatureStateLock) = false;