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

Commit 1cf7e629 authored by Midas Chien's avatar Midas Chien Committed by Automerger Merge Worker
Browse files

Merge "Move toggling of kernel idle timer to SF" into rvc-dev am: 6cd3197b...

Merge "Move toggling of kernel idle timer to SF" into rvc-dev am: 6cd3197b am: ace4db14 am: df567355

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/native/+/11838967

Change-Id: I354fe586e4afb52da9e95de72a78725e74a427aa
parents d43b08e0 df567355
Loading
Loading
Loading
Loading
+24 −0
Original line number Original line Diff line number Diff line
@@ -595,4 +595,28 @@ float RefreshRateConfigs::findClosestKnownFrameRate(float frameRate) const {
    return distance1 < distance2 ? *lowerBound : *std::prev(lowerBound);
    return distance1 < distance2 ? *lowerBound : *std::prev(lowerBound);
}
}


RefreshRateConfigs::KernelIdleTimerAction RefreshRateConfigs::getIdleTimerAction() const {
    std::lock_guard lock(mLock);
    const auto& deviceMin = getMinRefreshRate();
    const auto& minByPolicy = getMinRefreshRateByPolicyLocked();
    const auto& maxByPolicy = getMaxRefreshRateByPolicyLocked();

    // Kernel idle timer will set the refresh rate to the device min. If DisplayManager says that
    // the min allowed refresh rate is higher than the device min, we do not want to enable the
    // timer.
    if (deviceMin < minByPolicy) {
        return RefreshRateConfigs::KernelIdleTimerAction::TurnOff;
    }
    if (minByPolicy == maxByPolicy) {
        // Do not sent the call to toggle off kernel idle timer if the device min and policy min and
        // max are all the same. This saves us extra unnecessary calls to sysprop.
        if (deviceMin == minByPolicy) {
            return RefreshRateConfigs::KernelIdleTimerAction::NoChange;
        }
        return RefreshRateConfigs::KernelIdleTimerAction::TurnOff;
    }
    // Turn on the timer in all other cases.
    return RefreshRateConfigs::KernelIdleTimerAction::TurnOn;
}

} // namespace android::scheduler
} // namespace android::scheduler
+13 −0
Original line number Original line Diff line number Diff line
@@ -82,6 +82,8 @@ public:
            return configId != other.configId || hwcConfig != other.hwcConfig;
            return configId != other.configId || hwcConfig != other.hwcConfig;
        }
        }


        bool operator<(const RefreshRate& other) const { return getFps() < other.getFps(); }

        bool operator==(const RefreshRate& other) const { return !(*this != other); }
        bool operator==(const RefreshRate& other) const { return !(*this != other); }


    private:
    private:
@@ -271,6 +273,17 @@ public:
    RefreshRateConfigs(const std::vector<std::shared_ptr<const HWC2::Display::Config>>& configs,
    RefreshRateConfigs(const std::vector<std::shared_ptr<const HWC2::Display::Config>>& configs,
                       HwcConfigIndexType currentConfigId);
                       HwcConfigIndexType currentConfigId);


    // Class to enumerate options around toggling the kernel timer on and off. We have an option
    // for no change to avoid extra calls to kernel.
    enum class KernelIdleTimerAction {
        NoChange, // Do not change the idle timer.
        TurnOff,  // Turn off the idle timer.
        TurnOn    // Turn on the idle timer.
    };
    // Checks whether kernel idle timer should be active depending the policy decisions around
    // refresh rates.
    KernelIdleTimerAction getIdleTimerAction() const;

private:
private:
    friend class RefreshRateConfigsTest;
    friend class RefreshRateConfigsTest;


+37 −5
Original line number Original line Diff line number Diff line
@@ -23,6 +23,7 @@


#include "SurfaceFlinger.h"
#include "SurfaceFlinger.h"


#include <android-base/properties.h>
#include <android/configuration.h>
#include <android/configuration.h>
#include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h>
#include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h>
#include <android/hardware/configstore/1.1/ISurfaceFlingerConfigs.h>
#include <android/hardware/configstore/1.1/ISurfaceFlingerConfigs.h>
@@ -444,6 +445,9 @@ SurfaceFlinger::SurfaceFlinger(Factory& factory) : SurfaceFlinger(factory, SkipI
    }
    }


    useFrameRateApi = use_frame_rate_api(true);
    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;
SurfaceFlinger::~SurfaceFlinger() = default;
@@ -5355,8 +5359,7 @@ void SurfaceFlinger::kernelTimerChanged(bool expired) {
        const auto& min = mRefreshRateConfigs->getMinRefreshRate();
        const auto& min = mRefreshRateConfigs->getMinRefreshRate();


        if (current != min) {
        if (current != min) {
            const auto kernelTimerEnabled = property_get_bool(KERNEL_IDLE_TIMER_PROP, false);
            const bool timerExpired = mKernelIdleTimerEnabled && expired;
            const bool timerExpired = kernelTimerEnabled && expired;


            if (Mutex::Autolock lock(mStateLock); mRefreshRateOverlay) {
            if (Mutex::Autolock lock(mStateLock); mRefreshRateOverlay) {
                mRefreshRateOverlay->changeRefreshRate(timerExpired ? min : current);
                mRefreshRateOverlay->changeRefreshRate(timerExpired ? min : current);
@@ -5366,6 +5369,35 @@ void SurfaceFlinger::kernelTimerChanged(bool expired) {
    }));
    }));
}
}


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
// A simple RAII class to disconnect from an ANativeWindow* when it goes out of scope
class WindowDisconnector {
class WindowDisconnector {
public:
public:
@@ -5992,14 +6024,14 @@ status_t SurfaceFlinger::setDesiredDisplayConfigSpecsInternal(
          currentPolicy.primaryRange.max, currentPolicy.appRequestRange.min,
          currentPolicy.primaryRange.max, currentPolicy.appRequestRange.min,
          currentPolicy.appRequestRange.max);
          currentPolicy.appRequestRange.max);


    // TODO(b/140204874): This hack triggers a notification that something has changed, so
    // TODO(b/140204874): Leave the event in until we do proper testing with all apps that might
    // that listeners that care about a change in allowed configs can get the notification.
    // be depending in this callback.
    // Giving current ActiveConfig so that most other listeners would just drop the event
    const nsecs_t vsyncPeriod =
    const nsecs_t vsyncPeriod =
            mRefreshRateConfigs->getRefreshRateFromConfigId(display->getActiveConfig())
            mRefreshRateConfigs->getRefreshRateFromConfigId(display->getActiveConfig())
                    .getVsyncPeriod();
                    .getVsyncPeriod();
    mScheduler->onPrimaryDisplayConfigChanged(mAppConnectionHandle, display->getId()->value,
    mScheduler->onPrimaryDisplayConfigChanged(mAppConnectionHandle, display->getId()->value,
                                              display->getActiveConfig(), vsyncPeriod);
                                              display->getActiveConfig(), vsyncPeriod);
    toggleKernelIdleTimer();


    auto configId = mScheduler->getPreferredConfigId();
    auto configId = mScheduler->getPreferredConfigId();
    auto& preferredRefreshRate = configId
    auto& preferredRefreshRate = configId
+7 −0
Original line number Original line Diff line number Diff line
@@ -535,6 +535,13 @@ private:
    void repaintEverythingForHWC() override;
    void repaintEverythingForHWC() override;
    // Called when kernel idle timer has expired. Used to update the refresh rate overlay.
    // Called when kernel idle timer has expired. Used to update the refresh rate overlay.
    void kernelTimerChanged(bool expired) override;
    void kernelTimerChanged(bool expired) override;
    // Toggles the kernel idle timer on or off depending the policy decisions around refresh rates.
    void toggleKernelIdleTimer();
    // Keeps track of whether the kernel idle timer is currently enabled, so we don't have to
    // make calls to sys prop each time.
    bool mKernelIdleTimerEnabled = false;
    // Keeps track of whether the kernel timer is supported on the SF side.
    bool mSupportKernelIdleTimer = false;
    /* ------------------------------------------------------------------------
    /* ------------------------------------------------------------------------
     * Message handling
     * Message handling
     */
     */
+28 −0
Original line number Original line Diff line number Diff line
@@ -1420,6 +1420,34 @@ TEST_F(RefreshRateConfigsTest, getBestRefreshRate_KnownFrameRate) {
    }
    }
}
}


TEST_F(RefreshRateConfigsTest, testComparisonOperator) {
    EXPECT_TRUE(mExpected60Config < mExpected90Config);
    EXPECT_FALSE(mExpected60Config < mExpected60Config);
    EXPECT_FALSE(mExpected90Config < mExpected90Config);
}

TEST_F(RefreshRateConfigsTest, testKernelIdleTimerAction) {
    using KernelIdleTimerAction = scheduler::RefreshRateConfigs::KernelIdleTimerAction;

    auto refreshRateConfigs =
            std::make_unique<RefreshRateConfigs>(m60_90Device,
                                                 /*currentConfigId=*/HWC_CONFIG_ID_90);
    // SetPolicy(60, 90), current 90Hz => TurnOn.
    EXPECT_EQ(KernelIdleTimerAction::TurnOn, refreshRateConfigs->getIdleTimerAction());

    // SetPolicy(60, 90), current 60Hz => TurnOn.
    ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_60, {60, 90}}), 0);
    EXPECT_EQ(KernelIdleTimerAction::TurnOn, refreshRateConfigs->getIdleTimerAction());

    // SetPolicy(60, 60), current 60Hz => NoChange, avoid extra calls.
    ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_60, {60, 60}}), 0);
    EXPECT_EQ(KernelIdleTimerAction::NoChange, refreshRateConfigs->getIdleTimerAction());

    // SetPolicy(90, 90), current 90Hz => TurnOff.
    ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_90, {90, 90}}), 0);
    EXPECT_EQ(KernelIdleTimerAction::TurnOff, refreshRateConfigs->getIdleTimerAction());
}

} // namespace
} // namespace
} // namespace scheduler
} // namespace scheduler
} // namespace android
} // namespace android