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

Commit 89089c9a authored by Ady Abraham's avatar Ady Abraham
Browse files

SurfaceFlinger: always consider layers with setFrameRate

If an app called to setFrameRate on a layer, consider it when choosing
the refresh rate, even if the layer has posted buffers.

Bug: 152411921
Test: adb shell /data/nativetest64/libsurfaceflinger_unittest/libsurfaceflinger_unittest
Change-Id: I01f139b34cee01255693ed274225e79d83b0f894
parent 9305a384
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -1384,6 +1384,9 @@ bool Layer::setFrameRate(FrameRate frameRate) {
        return false;
    }

    // Activate the layer in Scheduler's LayerHistory
    mFlinger->mScheduler->recordLayerHistory(this, systemTime());

    mCurrentState.sequence++;
    mCurrentState.frameRate = frameRate;
    mCurrentState.modified = true;
+19 −22
Original line number Diff line number Diff line
@@ -40,9 +40,11 @@ namespace android::scheduler::impl {
namespace {

bool isLayerActive(const Layer& layer, const LayerInfoV2& info, nsecs_t threshold) {
    // Layers with an explicit vote are always kept active
    if (layer.getFrameRateForLayerTree().rate > 0) {
        return layer.isVisible();
        return true;
    }

    return layer.isVisible() && info.getLastUpdatedTime() >= threshold;
}

@@ -127,8 +129,6 @@ LayerHistoryV2::Summary LayerHistoryV2::summarize(nsecs_t now) {
        //  an additional parameter.
        ALOGV("Layer has priority: %d", strong->getFrameRateSelectionPriority());

        const bool recent = info->isRecentlyActive(now);
        if (recent) {
        const auto [type, refreshRate] = info->getRefreshRate(now);
        // Skip NoVote layer as those don't have any requirements
        if (type == LayerHistory::LayerVoteType::NoVote) {
@@ -148,9 +148,6 @@ LayerHistoryV2::Summary LayerHistoryV2::summarize(nsecs_t now) {
        if (CC_UNLIKELY(mTraceEnabled)) {
            trace(layer, type, static_cast<int>(std::round(refreshRate)));
        }
        } else if (CC_UNLIKELY(mTraceEnabled)) {
            trace(layer, LayerHistory::LayerVoteType::NoVote, 0);
        }
    }

    return summary;
@@ -177,7 +174,7 @@ void LayerHistoryV2::partitionLayers(nsecs_t now) {
                        return LayerVoteType::NoVote;
                }
            }();
            if (frameRate.rate > 0 || voteType == LayerVoteType::NoVote) {
            if (layer->isVisible() && (frameRate.rate > 0 || voteType == LayerVoteType::NoVote)) {
                info->setLayerVote(voteType, frameRate.rate);
            } else {
                info->resetLayerVote();
+0 −9
Original line number Diff line number Diff line
@@ -45,15 +45,6 @@ void LayerInfoV2::setLastPresentTime(nsecs_t lastPresentTime, nsecs_t now) {
    }
}

// Returns whether the earliest present time is within the active threshold.
bool LayerInfoV2::isRecentlyActive(nsecs_t now) const {
    if (mFrameTimes.empty()) {
        return false;
    }

    return mFrameTimes.back().queueTime >= getActiveLayerThreshold(now);
}

bool LayerInfoV2::isFrameTimeValid(const FrameTimeData& frameTime) const {
    return frameTime.queueTime >= std::chrono::duration_cast<std::chrono::nanoseconds>(
                                          mFrameTimeValidSince.time_since_epoch())
+0 −2
Original line number Diff line number Diff line
@@ -64,8 +64,6 @@ public:
    // updated time, the updated time is the present time.
    void setLastPresentTime(nsecs_t lastPresentTime, nsecs_t now);

    bool isRecentlyActive(nsecs_t now) const;

    // Sets an explicit layer vote. This usually comes directly from the application via
    // ANativeWindow_setFrameRate API
    void setLayerVote(LayerHistory::LayerVoteType type, float fps) { mLayerVote = {type, fps}; }
+9 −8
Original line number Diff line number Diff line
@@ -270,12 +270,12 @@ TEST_F(LayerHistoryTestV2, oneLayerExplicitVote) {
    EXPECT_EQ(1, activeLayerCount());
    EXPECT_EQ(1, frequentLayerCount(time));

    // layer became inactive
    // layer became inactive, but the vote stays
    setLayerInfoVote(layer.get(), LayerHistory::LayerVoteType::Heuristic);
    time += MAX_ACTIVE_LAYER_PERIOD_NS.count();
    ASSERT_TRUE(history().summarize(time).empty());
    // TODO: activeLayerCount() should be 0 but it is 1 since getFrameRateForLayerTree() returns a
    // value > 0
    ASSERT_EQ(1, history().summarize(time).size());
    EXPECT_EQ(LayerHistory::LayerVoteType::ExplicitDefault, history().summarize(time)[0].vote);
    EXPECT_FLOAT_EQ(73.4f, history().summarize(time)[0].desiredRefreshRate);
    EXPECT_EQ(1, activeLayerCount());
    EXPECT_EQ(0, frequentLayerCount(time));
}
@@ -303,12 +303,13 @@ TEST_F(LayerHistoryTestV2, oneLayerExplicitExactVote) {
    EXPECT_EQ(1, activeLayerCount());
    EXPECT_EQ(1, frequentLayerCount(time));

    // layer became inactive
    // layer became inactive, but the vote stays
    setLayerInfoVote(layer.get(), LayerHistory::LayerVoteType::Heuristic);
    time += MAX_ACTIVE_LAYER_PERIOD_NS.count();
    ASSERT_TRUE(history().summarize(time).empty());
    // TODO: activeLayerCount() should be 0 but it is 1 since getFrameRateForLayerTree() returns a
    // value > 0
    ASSERT_EQ(1, history().summarize(time).size());
    EXPECT_EQ(LayerHistory::LayerVoteType::ExplicitExactOrMultiple,
              history().summarize(time)[0].vote);
    EXPECT_FLOAT_EQ(73.4f, history().summarize(time)[0].desiredRefreshRate);
    EXPECT_EQ(1, activeLayerCount());
    EXPECT_EQ(0, frequentLayerCount(time));
}