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

Commit a1d64bb8 authored by Ram Indani's avatar Ram Indani Committed by Automerger Merge Worker
Browse files

Merge "SF: Clear layer history when inconclusive to frequent layer transition"...

Merge "SF: Clear layer history when inconclusive to frequent layer transition" into udc-dev am: a654b399

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



Change-Id: Ic5e607e74be725a47ebac21698bb89050f492bcb
Signed-off-by: default avatarAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
parents 28219554 a654b399
Loading
Loading
Loading
Loading
+19 −13
Original line number Diff line number Diff line
@@ -78,17 +78,16 @@ bool LayerInfo::isFrameTimeValid(const FrameTimeData& frameTime) const {
                                          .count();
}

bool LayerInfo::isFrequent(nsecs_t now) const {
    using fps_approx_ops::operator>=;
LayerInfo::Frequent LayerInfo::isFrequent(nsecs_t now) const {
    // If we know nothing about this layer (e.g. after touch event),
    // we consider it as frequent as it might be the start of an animation.
    if (mFrameTimes.size() < kFrequentLayerWindowSize) {
        return true;
        return {/* isFrequent */ true, /* clearHistory */ false, /* isConclusive */ true};
    }

    // Non-active layers are also infrequent
    if (mLastUpdatedTime < getActiveLayerThreshold(now)) {
        return false;
        return {/* isFrequent */ false, /* clearHistory */ false, /* isConclusive */ true};
    }

    // We check whether we can classify this layer as frequent or infrequent:
@@ -111,12 +110,20 @@ bool LayerInfo::isFrequent(nsecs_t now) const {
    }

    if (isFrequent || isInfrequent) {
        return isFrequent;
        // If the layer was previously inconclusive, we clear
        // the history as indeterminate layers changed to frequent,
        // and we should not look at the stale data.
        return {isFrequent, isFrequent && !mIsFrequencyConclusive, /* isConclusive */ true};
    }

    // If we can't determine whether the layer is frequent or not, we return
    // the last known classification.
    return !mLastRefreshRate.infrequent;
    // the last known classification and mark the layer frequency as inconclusive.
    isFrequent = !mLastRefreshRate.infrequent;

    // If the layer was previously tagged as animating, we clear
    // the history as it is likely the layer just changed its behavior,
    // and we should not look at stale data.
    return {isFrequent, isFrequent && mLastRefreshRate.animating, /* isConclusive */ false};
}

Fps LayerInfo::getFps(nsecs_t now) const {
@@ -273,19 +280,18 @@ LayerInfo::LayerVote LayerInfo::getRefreshRateVote(const RefreshRateSelector& se
        return {LayerHistory::LayerVoteType::Max, Fps()};
    }

    if (!isFrequent(now)) {
    const LayerInfo::Frequent frequent = isFrequent(now);
    mIsFrequencyConclusive = frequent.isConclusive;
    if (!frequent.isFrequent) {
        ATRACE_FORMAT_INSTANT("infrequent");
        ALOGV("%s is infrequent", mName.c_str());
        mLastRefreshRate.infrequent = true;
        // Infrequent layers vote for mininal refresh rate for
        // Infrequent layers vote for minimal refresh rate for
        // battery saving purposes and also to prevent b/135718869.
        return {LayerHistory::LayerVoteType::Min, Fps()};
    }

    // If the layer was previously tagged as animating or infrequent, we clear
    // the history as it is likely the layer just changed its behavior
    // and we should not look at stale data
    if (mLastRefreshRate.animating || mLastRefreshRate.infrequent) {
    if (frequent.clearHistory) {
        clearHistory(now);
    }

+10 −1
Original line number Diff line number Diff line
@@ -181,6 +181,7 @@ public:
        mFrameTimeValidSince = std::chrono::time_point<std::chrono::steady_clock>(timePoint);
        mLastRefreshRate = {};
        mRefreshRateHistory.clear();
        mIsFrequencyConclusive = true;
    }

    void clearHistory(nsecs_t now) {
@@ -251,7 +252,15 @@ private:
        static constexpr float MARGIN_CONSISTENT_FPS = 1.0;
    };

    bool isFrequent(nsecs_t now) const;
    // Represents whether we were able to determine either layer is frequent or infrequent
    bool mIsFrequencyConclusive = true;
    struct Frequent {
        bool isFrequent;
        bool clearHistory;
        // Represents whether we were able to determine isFrequent conclusively
        bool isConclusive;
    };
    Frequent isFrequent(nsecs_t now) const;
    bool isAnimating(nsecs_t now) const;
    bool hasEnoughDataForHeuristic() const;
    std::optional<Fps> calculateRefreshRateIfPossible(const RefreshRateSelector&, nsecs_t now);
+71 −1
Original line number Diff line number Diff line
@@ -84,7 +84,7 @@ protected:
    auto frequentLayerCount(nsecs_t now) const NO_THREAD_SAFETY_ANALYSIS {
        const auto& infos = history().mActiveLayerInfos;
        return std::count_if(infos.begin(), infos.end(), [now](const auto& pair) {
            return pair.second.second->isFrequent(now);
            return pair.second.second->isFrequent(now).isFrequent;
        });
    }

@@ -95,6 +95,13 @@ protected:
        });
    }

    auto clearLayerHistoryCount(nsecs_t now) const NO_THREAD_SAFETY_ANALYSIS {
        const auto& infos = history().mActiveLayerInfos;
        return std::count_if(infos.begin(), infos.end(), [now](const auto& pair) {
            return pair.second.second->isFrequent(now).clearHistory;
        });
    }

    void setDefaultLayerVote(Layer* layer,
                             LayerHistory::LayerVoteType vote) NO_THREAD_SAFETY_ANALYSIS {
        auto [found, layerPair] = history().findLayer(layer->getSequence());
@@ -764,6 +771,7 @@ TEST_F(LayerHistoryTest, frequentLayerBecomingInfrequentAndBack) {
    time += std::chrono::nanoseconds(3s).count();
    history().record(layer->getSequence(), layer->getLayerProps(), time, time,
                     LayerHistory::LayerUpdateType::Buffer);
    EXPECT_EQ(0, clearLayerHistoryCount(time));
    ASSERT_EQ(1, summarizeLayerHistory(time).size());
    EXPECT_EQ(LayerHistory::LayerVoteType::Heuristic, summarizeLayerHistory(time)[0].vote);
    EXPECT_EQ(60_Hz, summarizeLayerHistory(time)[0].desiredRefreshRate);
@@ -778,6 +786,7 @@ TEST_F(LayerHistoryTest, frequentLayerBecomingInfrequentAndBack) {
    time += (MAX_FREQUENT_LAYER_PERIOD_NS + 1ms).count();
    history().record(layer->getSequence(), layer->getLayerProps(), time, time,
                     LayerHistory::LayerUpdateType::Buffer);
    EXPECT_EQ(0, clearLayerHistoryCount(time));
    ASSERT_EQ(1, summarizeLayerHistory(time).size());
    EXPECT_EQ(LayerHistory::LayerVoteType::Min, summarizeLayerHistory(time)[0].vote);
    EXPECT_EQ(1, activeLayerCount());
@@ -787,6 +796,7 @@ TEST_F(LayerHistoryTest, frequentLayerBecomingInfrequentAndBack) {
    // posting another buffer should keep the layer infrequent
    history().record(layer->getSequence(), layer->getLayerProps(), time, time,
                     LayerHistory::LayerUpdateType::Buffer);
    EXPECT_EQ(0, clearLayerHistoryCount(time));
    ASSERT_EQ(1, summarizeLayerHistory(time).size());
    EXPECT_EQ(LayerHistory::LayerVoteType::Min, summarizeLayerHistory(time)[0].vote);
    EXPECT_EQ(1, activeLayerCount());
@@ -798,6 +808,7 @@ TEST_F(LayerHistoryTest, frequentLayerBecomingInfrequentAndBack) {
                     LayerHistory::LayerUpdateType::Buffer);
    history().record(layer->getSequence(), layer->getLayerProps(), time, time,
                     LayerHistory::LayerUpdateType::Buffer);
    EXPECT_EQ(1, clearLayerHistoryCount(time));
    ASSERT_EQ(1, summarizeLayerHistory(time).size());
    EXPECT_EQ(LayerHistory::LayerVoteType::Max, summarizeLayerHistory(time)[0].vote);
    EXPECT_EQ(1, activeLayerCount());
@@ -808,6 +819,7 @@ TEST_F(LayerHistoryTest, frequentLayerBecomingInfrequentAndBack) {
    time += std::chrono::nanoseconds(3s).count();
    history().record(layer->getSequence(), layer->getLayerProps(), time, time,
                     LayerHistory::LayerUpdateType::Buffer);
    EXPECT_EQ(0, clearLayerHistoryCount(time));
    ASSERT_EQ(1, summarizeLayerHistory(time).size());
    EXPECT_EQ(LayerHistory::LayerVoteType::Max, summarizeLayerHistory(time)[0].vote);
    EXPECT_EQ(1, activeLayerCount());
@@ -818,6 +830,64 @@ TEST_F(LayerHistoryTest, frequentLayerBecomingInfrequentAndBack) {
    time += (60_Hz).getPeriodNsecs();
    history().record(layer->getSequence(), layer->getLayerProps(), time, time,
                     LayerHistory::LayerUpdateType::Buffer);
    EXPECT_EQ(0, clearLayerHistoryCount(time));
    ASSERT_EQ(1, summarizeLayerHistory(time).size());
    EXPECT_EQ(LayerHistory::LayerVoteType::Max, summarizeLayerHistory(time)[0].vote);
    EXPECT_EQ(1, activeLayerCount());
    EXPECT_EQ(1, frequentLayerCount(time));
    EXPECT_EQ(0, animatingLayerCount(time));
}

TEST_F(LayerHistoryTest, inconclusiveLayerBecomingFrequent) {
    auto layer = createLayer();

    EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true));
    EXPECT_CALL(*layer, getFrameRateForLayerTree()).WillRepeatedly(Return(Layer::FrameRate()));

    nsecs_t time = systemTime();

    EXPECT_EQ(1, layerCount());
    EXPECT_EQ(0, activeLayerCount());
    EXPECT_EQ(0, frequentLayerCount(time));
    EXPECT_EQ(0, animatingLayerCount(time));

    // Fill up the window with frequent updates
    for (int i = 0; i < FREQUENT_LAYER_WINDOW_SIZE; i++) {
        history().record(layer->getSequence(), layer->getLayerProps(), time, time,
                         LayerHistory::LayerUpdateType::Buffer);
        time += (60_Hz).getPeriodNsecs();

        EXPECT_EQ(1, layerCount());
        ASSERT_EQ(1, summarizeLayerHistory(time).size());
        EXPECT_EQ(LayerHistory::LayerVoteType::Max, summarizeLayerHistory(time)[0].vote);
        EXPECT_EQ(1, activeLayerCount());
        EXPECT_EQ(1, frequentLayerCount(time));
    }

    // posting infrequent buffers after long inactivity should make the layer
    // inconclusive but frequent.
    time += std::chrono::nanoseconds(3s).count();
    history().record(layer->getSequence(), layer->getLayerProps(), time, time,
                     LayerHistory::LayerUpdateType::Buffer);
    time += (MAX_FREQUENT_LAYER_PERIOD_NS + 1ms).count();
    history().record(layer->getSequence(), layer->getLayerProps(), time, time,
                     LayerHistory::LayerUpdateType::Buffer);
    EXPECT_EQ(0, clearLayerHistoryCount(time));
    ASSERT_EQ(1, summarizeLayerHistory(time).size());
    EXPECT_EQ(LayerHistory::LayerVoteType::Heuristic, summarizeLayerHistory(time)[0].vote);
    EXPECT_EQ(1, activeLayerCount());
    EXPECT_EQ(1, frequentLayerCount(time));
    EXPECT_EQ(0, animatingLayerCount(time));

    // posting more buffers should make the layer frequent and switch the refresh rate to max
    // by clearing the history
    history().record(layer->getSequence(), layer->getLayerProps(), time, time,
                     LayerHistory::LayerUpdateType::Buffer);
    history().record(layer->getSequence(), layer->getLayerProps(), time, time,
                     LayerHistory::LayerUpdateType::Buffer);
    history().record(layer->getSequence(), layer->getLayerProps(), time, time,
                     LayerHistory::LayerUpdateType::Buffer);
    EXPECT_EQ(1, clearLayerHistoryCount(time));
    ASSERT_EQ(1, summarizeLayerHistory(time).size());
    EXPECT_EQ(LayerHistory::LayerVoteType::Max, summarizeLayerHistory(time)[0].vote);
    EXPECT_EQ(1, activeLayerCount());