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

Commit 6f8787ad authored by android-build-team Robot's avatar android-build-team Robot
Browse files

Snap for 6522252 from 68904ad9 to rvc-release

Change-Id: I89579d7f59b64bdbf7cd04c7c2bce2618154bb7e
parents dcd86e71 68904ad9
Loading
Loading
Loading
Loading
+9 −2
Original line number Diff line number Diff line
@@ -1353,8 +1353,15 @@ void Layer::updateTreeHasFrameRateVote() {
    // First traverse the tree and count how many layers has votes
    int layersWithVote = 0;
    traverseTree([&layersWithVote](Layer* layer) {
        if (layer->mCurrentState.frameRate.rate > 0 ||
            layer->mCurrentState.frameRate.type == FrameRateCompatibility::NoVote) {
        const auto layerVotedWithDefaultCompatibility = layer->mCurrentState.frameRate.rate > 0 &&
                layer->mCurrentState.frameRate.type == FrameRateCompatibility::Default;
        const auto layerVotedWithNoVote =
                layer->mCurrentState.frameRate.type == FrameRateCompatibility::NoVote;

        // We do not count layers that are ExactOrMultiple for the same reason
        // we are allowing touch boost for those layers. See
        // RefreshRateConfigs::getBestRefreshRate for more details.
        if (layerVotedWithDefaultCompatibility || layerVotedWithNoVote) {
            layersWithVote++;
        }
    });
+9 −0
Original line number Diff line number Diff line
@@ -52,6 +52,8 @@ public:
    // Sets the display size. Client is responsible for synchronization.
    virtual void setDisplayArea(uint32_t displayArea) = 0;

    virtual void setConfigChangePending(bool pending) = 0;

    // Marks the layer as active, and records the given state to its history.
    virtual void record(Layer*, nsecs_t presentTime, nsecs_t now) = 0;

@@ -78,6 +80,8 @@ public:

    void setDisplayArea(uint32_t /*displayArea*/) override {}

    void setConfigChangePending(bool /*pending*/) override {}

    // Marks the layer as active, and records the given state to its history.
    void record(Layer*, nsecs_t presentTime, nsecs_t now) override;

@@ -134,6 +138,8 @@ public:
    // Sets the display size. Client is responsible for synchronization.
    void setDisplayArea(uint32_t displayArea) override { mDisplayArea = displayArea; }

    void setConfigChangePending(bool pending) override { mConfigChangePending = pending; }

    // Marks the layer as active, and records the given state to its history.
    void record(Layer*, nsecs_t presentTime, nsecs_t now) override;

@@ -178,6 +184,9 @@ private:

    // Whether to use priority sent from WindowManager to determine the relevancy of the layer.
    const bool mUseFrameRatePriority;

    // Whether a config change is in progress or not
    std::atomic<bool> mConfigChangePending = false;
};

} // namespace impl
+1 −1
Original line number Diff line number Diff line
@@ -103,7 +103,7 @@ void LayerHistoryV2::record(Layer* layer, nsecs_t presentTime, nsecs_t now) {
    LOG_FATAL_IF(it == mLayerInfos.end(), "%s: unknown layer %p", __FUNCTION__, layer);

    const auto& info = it->second;
    info->setLastPresentTime(presentTime, now);
    info->setLastPresentTime(presentTime, now, mConfigChangePending);

    // Activate layer if inactive.
    if (const auto end = activeLayers().end(); it >= end) {
+65 −36
Original line number Diff line number Diff line
@@ -34,12 +34,15 @@ LayerInfoV2::LayerInfoV2(const std::string& name, nsecs_t highRefreshRatePeriod,
        mDefaultVote(defaultVote),
        mLayerVote({defaultVote, 0.0f}) {}

void LayerInfoV2::setLastPresentTime(nsecs_t lastPresentTime, nsecs_t now) {
void LayerInfoV2::setLastPresentTime(nsecs_t lastPresentTime, nsecs_t now,
                                     bool pendingConfigChange) {
    lastPresentTime = std::max(lastPresentTime, static_cast<nsecs_t>(0));

    mLastUpdatedTime = std::max(lastPresentTime, now);

    FrameTimeData frameTime = {.presetTime = lastPresentTime, .queueTime = mLastUpdatedTime};
    FrameTimeData frameTime = {.presetTime = lastPresentTime,
                               .queueTime = mLastUpdatedTime,
                               .pendingConfigChange = pendingConfigChange};

    mFrameTimes.push_back(frameTime);
    if (mFrameTimes.size() > HISTORY_SIZE) {
@@ -47,23 +50,28 @@ void LayerInfoV2::setLastPresentTime(nsecs_t lastPresentTime, nsecs_t now) {
    }
}

bool LayerInfoV2::isFrequent(nsecs_t now) const {
bool LayerInfoV2::isFrequent(nsecs_t now) {
    mLastReportedIsFrequent = [&] {
        for (auto it = mFrameTimes.crbegin(); it != mFrameTimes.crend(); ++it) {
            if (now - it->queueTime >= MAX_FREQUENT_LAYER_PERIOD_NS.count()) {
            ALOGV("%s infrequent (last frame is %.2fms ago", mName.c_str(),
                ALOGV("%s infrequent (last frame is %.2fms ago)", mName.c_str(),
                      (now - mFrameTimes.back().queueTime) / 1e6f);
                return false;
            }

            const auto numFrames = std::distance(mFrameTimes.crbegin(), it + 1);
            if (numFrames >= FREQUENT_LAYER_WINDOW_SIZE) {
            ALOGV("%s frequent (burst of %zu frames", mName.c_str(), numFrames);
                ALOGV("%s frequent (burst of %zu frames)", mName.c_str(), numFrames);
                return true;
            }
        }

    ALOGV("%s infrequent (not enough frames %zu)", mName.c_str(), mFrameTimes.size());
    return false;
        ALOGV("%s %sfrequent (not enough frames %zu)", mName.c_str(),
              mLastReportedIsFrequent ? "" : "in", mFrameTimes.size());
        return mLastReportedIsFrequent;
    }();

    return mLastReportedIsFrequent;
}

bool LayerInfoV2::hasEnoughDataForHeuristic() const {
@@ -80,21 +88,20 @@ bool LayerInfoV2::hasEnoughDataForHeuristic() const {
    return true;
}

std::optional<float> LayerInfoV2::calculateRefreshRateIfPossible() {
    static constexpr float MARGIN = 1.0f; // 1Hz

    if (!hasEnoughDataForHeuristic()) {
        ALOGV("Not enough data");
        return std::nullopt;
    }

    // Calculate the refresh rate by finding the average delta between frames
std::pair<nsecs_t, bool> LayerInfoV2::calculateAverageFrameTime() const {
    nsecs_t totalPresentTimeDeltas = 0;
    nsecs_t totalQueueTimeDeltas = 0;
    auto missingPresentTime = false;
    bool missingPresentTime = false;
    int numFrames = 0;
    for (auto it = mFrameTimes.begin(); it != mFrameTimes.end() - 1; ++it) {
        // Ignore frames captured during a config change
        if (it->pendingConfigChange || (it + 1)->pendingConfigChange) {
            continue;
        }

        totalQueueTimeDeltas +=
                std::max(((it + 1)->queueTime - it->queueTime), mHighRefreshRatePeriod);
        numFrames++;

        if (it->presetTime == 0 || (it + 1)->presetTime == 0) {
            missingPresentTime = true;
@@ -105,11 +112,6 @@ std::optional<float> LayerInfoV2::calculateRefreshRateIfPossible() {
                std::max(((it + 1)->presetTime - it->presetTime), mHighRefreshRatePeriod);
    }

    // If there are no presentation timestamps provided we can't calculate the refresh rate
    if (missingPresentTime && mLastReportedRefreshRate == 0) {
        return std::nullopt;
    }

    // Calculate the average frame time based on presentation timestamps. If those
    // doesn't exist, we look at the time the buffer was queued only. We can do that only if
    // we calculated a refresh rate based on presentation timestamps in the past. The reason
@@ -117,13 +119,18 @@ std::optional<float> LayerInfoV2::calculateRefreshRateIfPossible() {
    // when implementing render ahead for specific refresh rates. When hwui no longer provides
    // presentation timestamps we look at the queue time to see if the current refresh rate still
    // matches the content.
    const float averageFrameTime =
    const auto averageFrameTime =
            static_cast<float>(missingPresentTime ? totalQueueTimeDeltas : totalPresentTimeDeltas) /
            (mFrameTimes.size() - 1);
            numFrames;
    return {static_cast<nsecs_t>(averageFrameTime), missingPresentTime};
}

    // Now once we calculated the refresh rate we need to make sure that all the frames we captured
    // are evenly distributed and we don't calculate the average across some burst of frames.
bool LayerInfoV2::isRefreshRateStable(nsecs_t averageFrameTime, bool missingPresentTime) const {
    for (auto it = mFrameTimes.begin(); it != mFrameTimes.end() - 1; ++it) {
        // Ignore frames captured during a config change
        if (it->pendingConfigChange || (it + 1)->pendingConfigChange) {
            continue;
        }
        const auto presentTimeDeltas = [&] {
            const auto delta = missingPresentTime ? (it + 1)->queueTime - it->queueTime
                                                  : (it + 1)->presetTime - it->presetTime;
@@ -131,8 +138,30 @@ std::optional<float> LayerInfoV2::calculateRefreshRateIfPossible() {
        }();

        if (std::abs(presentTimeDeltas - averageFrameTime) > 2 * averageFrameTime) {
            return false;
        }
    }

    return true;
}

std::optional<float> LayerInfoV2::calculateRefreshRateIfPossible() {
    static constexpr float MARGIN = 1.0f; // 1Hz

    if (!hasEnoughDataForHeuristic()) {
        ALOGV("Not enough data");
        return std::nullopt;
    }

    const auto [averageFrameTime, missingPresentTime] = calculateAverageFrameTime();

    // If there are no presentation timestamps provided we can't calculate the refresh rate
    if (missingPresentTime && mLastReportedRefreshRate == 0) {
        return std::nullopt;
    }

    if (!isRefreshRateStable(averageFrameTime, missingPresentTime)) {
        return std::nullopt;
    }

    const auto refreshRate = 1e9f / averageFrameTime;
+13 −5
Original line number Diff line number Diff line
@@ -47,9 +47,7 @@ class LayerInfoV2 {
    // is within a threshold. If a layer is infrequent, its average refresh rate is disregarded in
    // favor of a low refresh rate.
    static constexpr size_t FREQUENT_LAYER_WINDOW_SIZE = 3;
    static constexpr float MIN_FPS_FOR_FREQUENT_LAYER = 10.0f;
    static constexpr auto MAX_FREQUENT_LAYER_PERIOD_NS =
            std::chrono::nanoseconds(static_cast<nsecs_t>(1e9f / MIN_FPS_FOR_FREQUENT_LAYER)) + 1ms;
    static constexpr std::chrono::nanoseconds MAX_FREQUENT_LAYER_PERIOD_NS = 150ms;

    friend class LayerHistoryTestV2;

@@ -63,7 +61,7 @@ public:
    // Records the last requested present time. It also stores information about when
    // the layer was last updated. If the present time is farther in the future than the
    // updated time, the updated time is the present time.
    void setLastPresentTime(nsecs_t lastPresentTime, nsecs_t now);
    void setLastPresentTime(nsecs_t lastPresentTime, nsecs_t now, bool pendingConfigChange);

    // Sets an explicit layer vote. This usually comes directly from the application via
    // ANativeWindow_setFrameRate API
@@ -93,11 +91,14 @@ private:
    struct FrameTimeData {
        nsecs_t presetTime; // desiredPresentTime, if provided
        nsecs_t queueTime;  // buffer queue time
        bool pendingConfigChange;
    };

    bool isFrequent(nsecs_t now) const;
    bool isFrequent(nsecs_t now);
    bool hasEnoughDataForHeuristic() const;
    std::optional<float> calculateRefreshRateIfPossible();
    std::pair<nsecs_t, bool> calculateAverageFrameTime() const;
    bool isRefreshRateStable(nsecs_t averageFrameTime, bool missingPresentTime) const;

    const std::string mName;

@@ -109,6 +110,13 @@ private:

    float mLastReportedRefreshRate = 0.0f;

    // Used to determine whether a layer should be considered frequent or
    // not when we don't have enough frames. This member will not be cleared
    // as part of clearHistory() to remember whether this layer was frequent
    // or not before we processed touch boost (or anything else that would
    // clear layer history).
    bool mLastReportedIsFrequent = true;

    // Holds information about the layer vote
    struct {
        LayerHistory::LayerVoteType type;
Loading