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

Commit ad083c40 authored by Ana Krulec's avatar Ana Krulec
Browse files

SF: Don't bump to PERFORMANCE refresh rate with infrequent updates

Testing scenario:
1. Set brightness around 50%-55%, set dark theme.
2. Open Chrome.
3. Click search bar.
4. Can see the cursor show up.
Notice the flickering of the screen.

Explanation:
Kernel idle timer detects inactivity after 100ms, and turns the refresh rate to 60Hz.
When a cursor update happens (every 500ms), SF receives a new frame, notifies kernel,
the refresh rate bumps to 90Hz. After 100ms the kernel again decreases the refresh rate to 60Hz.

Desired goals:
Stop the flickering (eg. changing between 60-90Hz too often).
Continue having low battery impact.

Solution in this AG:
Add logic to SF to detect infrequent updates (for all layers). Description of the algorithm:
1) Store the timestamp of the last two buffers.
2) If the first buffer is older than 250 ms, detect inactivity, go into DEFAULT refresh rate.
3) EXIT: on touch event, layer requests 2 or more frames in less than 250ms.
NOTE: if the application is explicitly requesting 90Hz, SF does not override that. Idle kernel
still kicks in, and the flickering happens.

tested on Chrome v74 Beta, and messaging app.

Test: manual, b/135009095
Bug: 135718869
Change-Id: I72d8cd48b3ec900989afcf0fab1cdc3046b87274
parent 57e20651
Loading
Loading
Loading
Loading
+3 −1
Original line number Original line Diff line number Diff line
@@ -46,11 +46,13 @@ LayerHistory::LayerHistory() {
LayerHistory::~LayerHistory() = default;
LayerHistory::~LayerHistory() = default;


std::unique_ptr<LayerHistory::LayerHandle> LayerHistory::createLayer(const std::string name,
std::unique_ptr<LayerHistory::LayerHandle> LayerHistory::createLayer(const std::string name,
                                                                     float minRefreshRate,
                                                                     float maxRefreshRate) {
                                                                     float maxRefreshRate) {
    const int64_t id = sNextId++;
    const int64_t id = sNextId++;


    std::lock_guard lock(mLock);
    std::lock_guard lock(mLock);
    mInactiveLayerInfos.emplace(id, std::make_shared<LayerInfo>(name, maxRefreshRate));
    mInactiveLayerInfos.emplace(id,
                                std::make_shared<LayerInfo>(name, minRefreshRate, maxRefreshRate));
    return std::make_unique<LayerHistory::LayerHandle>(*this, id);
    return std::make_unique<LayerHistory::LayerHandle>(*this, id);
}
}


+2 −1
Original line number Original line Diff line number Diff line
@@ -53,7 +53,8 @@ public:
    ~LayerHistory();
    ~LayerHistory();


    // When the layer is first created, register it.
    // When the layer is first created, register it.
    std::unique_ptr<LayerHandle> createLayer(const std::string name, float maxRefreshRate);
    std::unique_ptr<LayerHandle> createLayer(const std::string name, float minRefreshRate,
                                             float maxRefreshRate);


    // Method for inserting layers and their requested present time into the unordered map.
    // Method for inserting layers and their requested present time into the unordered map.
    void insert(const std::unique_ptr<LayerHandle>& layerHandle, nsecs_t presentTime, bool isHdr);
    void insert(const std::unique_ptr<LayerHandle>& layerHandle, nsecs_t presentTime, bool isHdr);
+3 −2
Original line number Original line Diff line number Diff line
@@ -24,9 +24,10 @@
namespace android {
namespace android {
namespace scheduler {
namespace scheduler {


LayerInfo::LayerInfo(const std::string name, float maxRefreshRate)
LayerInfo::LayerInfo(const std::string name, float minRefreshRate, float maxRefreshRate)
      : mName(name),
      : mName(name),
        mMinRefreshDuration(1e9f / maxRefreshRate),
        mMinRefreshDuration(1e9f / maxRefreshRate),
        mLowActivityRefreshDuration(1e9f / minRefreshRate),
        mRefreshRateHistory(mMinRefreshDuration) {}
        mRefreshRateHistory(mMinRefreshDuration) {}


LayerInfo::~LayerInfo() = default;
LayerInfo::~LayerInfo() = default;
@@ -47,7 +48,7 @@ void LayerInfo::setLastPresentTime(nsecs_t lastPresentTime) {
    const nsecs_t timeDiff = lastPresentTime - mLastPresentTime;
    const nsecs_t timeDiff = lastPresentTime - mLastPresentTime;
    mLastPresentTime = lastPresentTime;
    mLastPresentTime = lastPresentTime;
    // Ignore time diff that are too high - those are stale values
    // Ignore time diff that are too high - those are stale values
    if (timeDiff > TIME_EPSILON_NS.count()) return;
    if (timeDiff > OBSOLETE_TIME_EPSILON_NS.count()) return;
    const nsecs_t refreshDuration = (timeDiff > 0) ? timeDiff : mMinRefreshDuration;
    const nsecs_t refreshDuration = (timeDiff > 0) ? timeDiff : mMinRefreshDuration;
    mRefreshRateHistory.insertRefreshRate(refreshDuration);
    mRefreshRateHistory.insertRefreshRate(refreshDuration);
}
}
+28 −3
Original line number Original line Diff line number Diff line
@@ -96,8 +96,9 @@ class LayerInfo {
                return false;
                return false;
            }
            }


            // The last update should not be older than TIME_EPSILON_NS nanoseconds.
            // The last update should not be older than OBSOLETE_TIME_EPSILON_NS nanoseconds.
            const int64_t obsoleteEpsilon = systemTime() - scheduler::TIME_EPSILON_NS.count();
            const int64_t obsoleteEpsilon =
                    systemTime() - scheduler::OBSOLETE_TIME_EPSILON_NS.count();
            if (mElements.at(mElements.size() - 1) < obsoleteEpsilon) {
            if (mElements.at(mElements.size() - 1) < obsoleteEpsilon) {
                return false;
                return false;
            }
            }
@@ -105,6 +106,25 @@ class LayerInfo {
            return true;
            return true;
        }
        }


        bool isLowActivityLayer() const {
            // We want to make sure that we received more than two frames from the layer
            // in order to check low activity.
            if (mElements.size() < 2) {
                return false;
            }

            const int64_t obsoleteEpsilon =
                    systemTime() - scheduler::LOW_ACTIVITY_EPSILON_NS.count();
            // Check the frame before last to determine whether there is low activity.
            // If that frame is older than LOW_ACTIVITY_EPSILON_NS, the layer is sending
            // infrequent updates.
            if (mElements.at(mElements.size() - 2) < obsoleteEpsilon) {
                return true;
            }

            return false;
        }

        void clearHistory() { mElements.clear(); }
        void clearHistory() { mElements.clear(); }


    private:
    private:
@@ -114,7 +134,7 @@ class LayerInfo {
    };
    };


public:
public:
    LayerInfo(const std::string name, float maxRefreshRate);
    LayerInfo(const std::string name, float minRefreshRate, float maxRefreshRate);
    ~LayerInfo();
    ~LayerInfo();


    LayerInfo(const LayerInfo&) = delete;
    LayerInfo(const LayerInfo&) = delete;
@@ -144,6 +164,10 @@ public:
    // Calculate the average refresh rate.
    // Calculate the average refresh rate.
    float getDesiredRefreshRate() const {
    float getDesiredRefreshRate() const {
        std::lock_guard lock(mLock);
        std::lock_guard lock(mLock);

        if (mPresentTimeHistory.isLowActivityLayer()) {
            return 1e9f / mLowActivityRefreshDuration;
        }
        return mRefreshRateHistory.getRefreshRateAvg();
        return mRefreshRateHistory.getRefreshRateAvg();
    }
    }


@@ -175,6 +199,7 @@ public:
private:
private:
    const std::string mName;
    const std::string mName;
    const nsecs_t mMinRefreshDuration;
    const nsecs_t mMinRefreshDuration;
    const nsecs_t mLowActivityRefreshDuration;
    mutable std::mutex mLock;
    mutable std::mutex mLock;
    nsecs_t mLastUpdatedTime GUARDED_BY(mLock) = 0;
    nsecs_t mLastUpdatedTime GUARDED_BY(mLock) = 0;
    nsecs_t mLastPresentTime GUARDED_BY(mLock) = 0;
    nsecs_t mLastPresentTime GUARDED_BY(mLock) = 0;
+5 −2
Original line number Original line Diff line number Diff line
@@ -330,8 +330,11 @@ std::unique_ptr<scheduler::LayerHistory::LayerHandle> Scheduler::registerLayer(
            : RefreshRateType::PERFORMANCE;
            : RefreshRateType::PERFORMANCE;


    const auto refreshRate = mRefreshRateConfigs.getRefreshRate(refreshRateType);
    const auto refreshRate = mRefreshRateConfigs.getRefreshRate(refreshRateType);
    const uint32_t fps = (refreshRate) ? refreshRate->fps : 0;
    const uint32_t performanceFps = (refreshRate) ? refreshRate->fps : 0;
    return mLayerHistory.createLayer(name, fps);

    const auto defaultRefreshRate = mRefreshRateConfigs.getRefreshRate(RefreshRateType::DEFAULT);
    const uint32_t defaultFps = (defaultRefreshRate) ? defaultRefreshRate->fps : 0;
    return mLayerHistory.createLayer(name, defaultFps, performanceFps);
}
}


void Scheduler::addLayerPresentTimeAndHDR(
void Scheduler::addLayerPresentTimeAndHDR(
Loading