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

Commit 1196e96c authored by Ram Indani's avatar Ram Indani Committed by Android (Google) Code Review
Browse files

Merge "[MD] Return list of scored refresh rates based on overallscore."

parents 75fd4b82 d72ba16b
Loading
Loading
Loading
Loading
+130 −92
Original line number Diff line number Diff line
@@ -48,24 +48,6 @@ struct RefreshRateScore {
    } fixedRateBelowThresholdLayersScore;
};

template <typename Iterator>
const DisplayModePtr& getMaxScoreRefreshRate(Iterator begin, Iterator end) {
    const auto it =
            std::max_element(begin, end, [](RefreshRateScore max, RefreshRateScore current) {
                const auto& [modeIt, overallScore, _] = current;

                std::string name = to_string(modeIt->second->getFps());
                ALOGV("%s scores %.2f", name.c_str(), overallScore);

                ATRACE_INT(name.c_str(), static_cast<int>(std::round(overallScore * 100)));

                constexpr float kEpsilon = 0.0001f;
                return overallScore > max.overallScore * (1 + kEpsilon);
            });

    return it->modeIt->second;
}

constexpr RefreshRateConfigs::GlobalSignals kNoSignals;

std::string formatLayerInfo(const RefreshRateConfigs::LayerRequirement& layer, float weight) {
@@ -137,6 +119,34 @@ bool canModesSupportFrameRateOverride(const std::vector<DisplayModeIterator>& so

} // namespace

struct RefreshRateConfigs::RefreshRateScoreComparator {
    bool operator()(const RefreshRateScore& lhs, const RefreshRateScore& rhs) const {
        const auto& [modeIt, overallScore, _] = lhs;

        std::string name = to_string(modeIt->second->getFps());
        ALOGV("%s sorting scores %.2f", name.c_str(), overallScore);

        ATRACE_INT(name.c_str(), static_cast<int>(std::round(overallScore * 100)));

        constexpr float kEpsilon = 0.0001f;
        if (std::abs(overallScore - rhs.overallScore) > kEpsilon) {
            return overallScore > rhs.overallScore;
        }

        // If overallScore tie we will pick the higher refresh rate if
        // high refresh rate is the priority else the lower refresh rate.
        if (refreshRateOrder == RefreshRateOrder::Descending) {
            using fps_approx_ops::operator>;
            return modeIt->second->getFps() > rhs.modeIt->second->getFps();
        } else {
            using fps_approx_ops::operator<;
            return modeIt->second->getFps() < rhs.modeIt->second->getFps();
        }
    }

    const RefreshRateOrder refreshRateOrder;
};

std::string RefreshRateConfigs::Policy::toString() const {
    return base::StringPrintf("{defaultModeId=%d, allowGroupSwitching=%s"
                              ", primaryRange=%s, appRequestRange=%s}",
@@ -218,6 +228,13 @@ float RefreshRateConfigs::calculateNonExactMatchingLayerScoreLocked(const LayerR
    return 0;
}

float RefreshRateConfigs::calculateRefreshRateScoreForFps(Fps refreshRate) const {
    const float ratio =
            refreshRate.getValue() / mAppRequestRefreshRates.back()->second->getFps().getValue();
    // Use ratio^2 to get a lower score the more we get further from peak
    return ratio * ratio;
}

float RefreshRateConfigs::calculateLayerScoreLocked(const LayerRequirement& layer, Fps refreshRate,
                                                    bool isSeamlessSwitch) const {
    // Slightly prefer seamless switches.
@@ -226,10 +243,7 @@ float RefreshRateConfigs::calculateLayerScoreLocked(const LayerRequirement& laye

    // If the layer wants Max, give higher score to the higher refresh rate
    if (layer.vote == LayerVoteType::Max) {
        const auto& maxRefreshRate = mAppRequestRefreshRates.back()->second;
        const auto ratio = refreshRate.getValue() / maxRefreshRate->getFps().getValue();
        // use ratio^2 to get a lower score the more we get further from peak
        return ratio * ratio;
        return calculateRefreshRateScoreForFps(refreshRate);
    }

    if (layer.vote == LayerVoteType::ExplicitExact) {
@@ -258,24 +272,24 @@ float RefreshRateConfigs::calculateLayerScoreLocked(const LayerRequirement& laye
            kNonExactMatchingPenalty;
}

auto RefreshRateConfigs::getBestRefreshRate(const std::vector<LayerRequirement>& layers,
auto RefreshRateConfigs::getRankedRefreshRates(const std::vector<LayerRequirement>& layers,
                                               GlobalSignals signals) const
        -> std::pair<DisplayModePtr, GlobalSignals> {
        -> std::pair<std::vector<RefreshRateRanking>, GlobalSignals> {
    std::lock_guard lock(mLock);

    if (mGetBestRefreshRateCache &&
        mGetBestRefreshRateCache->arguments == std::make_pair(layers, signals)) {
        return mGetBestRefreshRateCache->result;
    if (mGetRankedRefreshRatesCache &&
        mGetRankedRefreshRatesCache->arguments == std::make_pair(layers, signals)) {
        return mGetRankedRefreshRatesCache->result;
    }

    const auto result = getBestRefreshRateLocked(layers, signals);
    mGetBestRefreshRateCache = GetBestRefreshRateCache{{layers, signals}, result};
    const auto result = getRankedRefreshRatesLocked(layers, signals);
    mGetRankedRefreshRatesCache = GetRankedRefreshRatesCache{{layers, signals}, result};
    return result;
}

auto RefreshRateConfigs::getBestRefreshRateLocked(const std::vector<LayerRequirement>& layers,
auto RefreshRateConfigs::getRankedRefreshRatesLocked(const std::vector<LayerRequirement>& layers,
                                                     GlobalSignals signals) const
        -> std::pair<DisplayModePtr, GlobalSignals> {
        -> std::pair<std::vector<RefreshRateRanking>, GlobalSignals> {
    using namespace fps_approx_ops;
    ATRACE_CALL();
    ALOGV("%s: %zu layers", __func__, layers.size());
@@ -285,8 +299,8 @@ auto RefreshRateConfigs::getBestRefreshRateLocked(const std::vector<LayerRequire
    // Keep the display at max refresh rate for the duration of powering on the display.
    if (signals.powerOnImminent) {
        ALOGV("Power On Imminent");
        const auto& max = getMaxRefreshRateByPolicyLocked(activeMode.getGroup());
        return {max, GlobalSignals{.powerOnImminent = true}};
        return {getRefreshRatesByPolicyLocked(activeMode.getGroup(), RefreshRateOrder::Descending),
                GlobalSignals{.powerOnImminent = true}};
    }

    int noVoteLayers = 0;
@@ -295,7 +309,6 @@ auto RefreshRateConfigs::getBestRefreshRateLocked(const std::vector<LayerRequire
    int explicitDefaultVoteLayers = 0;
    int explicitExactOrMultipleVoteLayers = 0;
    int explicitExact = 0;
    float maxExplicitWeight = 0;
    int seamedFocusedLayers = 0;

    for (const auto& layer : layers) {
@@ -311,15 +324,12 @@ auto RefreshRateConfigs::getBestRefreshRateLocked(const std::vector<LayerRequire
                break;
            case LayerVoteType::ExplicitDefault:
                explicitDefaultVoteLayers++;
                maxExplicitWeight = std::max(maxExplicitWeight, layer.weight);
                break;
            case LayerVoteType::ExplicitExactOrMultiple:
                explicitExactOrMultipleVoteLayers++;
                maxExplicitWeight = std::max(maxExplicitWeight, layer.weight);
                break;
            case LayerVoteType::ExplicitExact:
                explicitExact++;
                maxExplicitWeight = std::max(maxExplicitWeight, layer.weight);
                break;
            case LayerVoteType::Heuristic:
                break;
@@ -348,9 +358,9 @@ auto RefreshRateConfigs::getBestRefreshRateLocked(const std::vector<LayerRequire
    // Consider the touch event if there are no Explicit* layers. Otherwise wait until after we've
    // selected a refresh rate to see if we should apply touch boost.
    if (signals.touch && !hasExplicitVoteLayers) {
        const DisplayModePtr& max = getMaxRefreshRateByPolicyLocked(anchorGroup);
        ALOGV("TouchBoost - choose %s", to_string(max->getFps()).c_str());
        return {max, GlobalSignals{.touch = true}};
        ALOGV("Touch Boost");
        return {getRefreshRatesByPolicyLocked(anchorGroup, RefreshRateOrder::Descending),
                GlobalSignals{.touch = true}};
    }

    // If the primary range consists of a single refresh rate then we can only
@@ -360,22 +370,22 @@ auto RefreshRateConfigs::getBestRefreshRateLocked(const std::vector<LayerRequire
            isApproxEqual(policy->primaryRange.min, policy->primaryRange.max);

    if (!signals.touch && signals.idle && !(primaryRangeIsSingleRate && hasExplicitVoteLayers)) {
        const DisplayModePtr& min = getMinRefreshRateByPolicyLocked();
        ALOGV("Idle - choose %s", to_string(min->getFps()).c_str());
        return {min, GlobalSignals{.idle = true}};
        ALOGV("Idle");
        return {getRefreshRatesByPolicyLocked(activeMode.getGroup(), RefreshRateOrder::Ascending),
                GlobalSignals{.idle = true}};
    }

    if (layers.empty() || noVoteLayers == layers.size()) {
        const DisplayModePtr& max = getMaxRefreshRateByPolicyLocked(anchorGroup);
        ALOGV("no layers with votes - choose %s", to_string(max->getFps()).c_str());
        return {max, kNoSignals};
        ALOGV("No layers with votes");
        return {getRefreshRatesByPolicyLocked(anchorGroup, RefreshRateOrder::Descending),
                kNoSignals};
    }

    // Only if all layers want Min we should return Min
    if (noVoteLayers + minVoteLayers == layers.size()) {
        const DisplayModePtr& min = getMinRefreshRateByPolicyLocked();
        ALOGV("all layers Min - choose %s", to_string(min->getFps()).c_str());
        return {min, kNoSignals};
        ALOGV("All layers Min");
        return {getRefreshRatesByPolicyLocked(activeMode.getGroup(), RefreshRateOrder::Ascending),
                kNoSignals};
    }

    // Find the best refresh rate based on score
@@ -522,22 +532,29 @@ auto RefreshRateConfigs::getBestRefreshRateLocked(const std::vector<LayerRequire
    }

    // Now that we scored all the refresh rates we need to pick the one that got the highest
    // overallScore. In case of a tie we will pick the higher refresh rate if any of the layers
    // wanted Max, or the lower otherwise.
    const DisplayModePtr& bestRefreshRate = maxVoteLayers > 0
            ? getMaxScoreRefreshRate(scores.rbegin(), scores.rend())
            : getMaxScoreRefreshRate(scores.begin(), scores.end());
    // overallScore. Sort the scores based on their overallScore in descending order of priority.
    const RefreshRateOrder refreshRateOrder =
            maxVoteLayers > 0 ? RefreshRateOrder::Descending : RefreshRateOrder::Ascending;
    std::sort(scores.begin(), scores.end(),
              RefreshRateScoreComparator{.refreshRateOrder = refreshRateOrder});
    std::vector<RefreshRateRanking> rankedRefreshRates;
    rankedRefreshRates.reserve(scores.size());

    std::transform(scores.begin(), scores.end(), back_inserter(rankedRefreshRates),
                   [](const RefreshRateScore& score) {
                       return RefreshRateRanking{score.modeIt->second, score.overallScore};
                   });

    if (primaryRangeIsSingleRate) {
        // If we never scored any layers, then choose the rate from the primary
        // range instead of picking a random score from the app range.
        if (std::all_of(scores.begin(), scores.end(),
                        [](RefreshRateScore score) { return score.overallScore == 0; })) {
            const DisplayModePtr& max = getMaxRefreshRateByPolicyLocked(anchorGroup);
            ALOGV("layers not scored - choose %s", to_string(max->getFps()).c_str());
            return {max, kNoSignals};
            ALOGV("Layers not scored");
            return {getRefreshRatesByPolicyLocked(anchorGroup, RefreshRateOrder::Descending),
                    kNoSignals};
        } else {
            return {bestRefreshRate, kNoSignals};
            return {rankedRefreshRates, kNoSignals};
        }
    }

@@ -545,8 +562,6 @@ auto RefreshRateConfigs::getBestRefreshRateLocked(const std::vector<LayerRequire
    // interactive (as opposed to ExplicitExactOrMultiple) and therefore if those posted an explicit
    // vote we should not change it if we get a touch event. Only apply touch boost if it will
    // actually increase the refresh rate over the normal selection.
    const DisplayModePtr& touchRefreshRate = getMaxRefreshRateByPolicyLocked(anchorGroup);

    const bool touchBoostForExplicitExact = [&] {
        if (mSupportsFrameRateOverrideByContent) {
            // Enable touch boost if there are other layers besides exact
@@ -557,15 +572,18 @@ auto RefreshRateConfigs::getBestRefreshRateLocked(const std::vector<LayerRequire
        }
    }();

    const auto& touchRefreshRates =
            getRefreshRatesByPolicyLocked(anchorGroup, RefreshRateOrder::Descending);
    using fps_approx_ops::operator<;

    if (signals.touch && explicitDefaultVoteLayers == 0 && touchBoostForExplicitExact &&
        bestRefreshRate->getFps() < touchRefreshRate->getFps()) {
        ALOGV("TouchBoost - choose %s", to_string(touchRefreshRate->getFps()).c_str());
        return {touchRefreshRate, GlobalSignals{.touch = true}};
        scores.front().modeIt->second->getFps() <
                touchRefreshRates.front().displayModePtr->getFps()) {
        ALOGV("Touch Boost");
        return {touchRefreshRates, GlobalSignals{.touch = true}};
    }

    return {bestRefreshRate, kNoSignals};
    return {rankedRefreshRates, kNoSignals};
}

std::unordered_map<uid_t, std::vector<const RefreshRateConfigs::LayerRequirement*>>
@@ -670,11 +688,13 @@ RefreshRateConfigs::UidToFrameRateOverride RefreshRateConfigs::getFrameRateOverr
            continue;
        }

        // Now that we scored all the refresh rates we need to pick the one that got the highest
        // score.
        // Now that we scored all the refresh rates we need to pick the lowest refresh rate
        // that got the highest score.
        const DisplayModePtr& bestRefreshRate =
                getMaxScoreRefreshRate(scores.begin(), scores.end());

                std::min_element(scores.begin(), scores.end(),
                                 RefreshRateScoreComparator{.refreshRateOrder =
                                                                    RefreshRateOrder::Ascending})
                        ->modeIt->second;
        frameRateOverrides.emplace(uid, bestRefreshRate->getFps());
    }

@@ -715,16 +735,6 @@ const DisplayModePtr& RefreshRateConfigs::getMinRefreshRateByPolicyLocked() cons
    return mPrimaryRefreshRates.front()->second;
}

DisplayModePtr RefreshRateConfigs::getMaxRefreshRateByPolicy() const {
    std::lock_guard lock(mLock);
    return getMaxRefreshRateByPolicyLocked();
}

const DisplayModePtr& RefreshRateConfigs::getMaxRefreshRateByPolicyLocked() const {
    const int anchorGroup = getActiveModeItLocked()->second->getGroup();
    return getMaxRefreshRateByPolicyLocked(anchorGroup);
}

const DisplayModePtr& RefreshRateConfigs::getMaxRefreshRateByPolicyLocked(int anchorGroup) const {
    for (auto it = mPrimaryRefreshRates.rbegin(); it != mPrimaryRefreshRates.rend(); ++it) {
        const auto& mode = (*it)->second;
@@ -733,14 +743,41 @@ const DisplayModePtr& RefreshRateConfigs::getMaxRefreshRateByPolicyLocked(int an
        }
    }

    const auto& activeMode = *getActiveModeItLocked()->second;
    ALOGE("Can't find max refresh rate by policy with the same mode group as the current mode %s",
          to_string(activeMode).c_str());
    ALOGE("Can't find max refresh rate by policy with the same group %d", anchorGroup);

    // Default to the highest refresh rate.
    return mPrimaryRefreshRates.back()->second;
}

std::vector<RefreshRateRanking> RefreshRateConfigs::getRefreshRatesByPolicyLocked(
        std::optional<int> anchorGroupOpt, RefreshRateOrder refreshRateOrder) const {
    std::vector<RefreshRateRanking> rankings;
    const auto makeRanking = [&](const DisplayModeIterator it) REQUIRES(mLock) {
        const auto& mode = it->second;
        const bool inverseScore = (refreshRateOrder == RefreshRateOrder::Ascending);
        const float score = calculateRefreshRateScoreForFps(mode->getFps());
        if (!anchorGroupOpt || mode->getGroup() == anchorGroupOpt) {
            rankings.push_back(RefreshRateRanking{mode, inverseScore ? 1.0f / score : score});
        }
    };

    if (refreshRateOrder == RefreshRateOrder::Ascending) {
        std::for_each(mPrimaryRefreshRates.begin(), mPrimaryRefreshRates.end(), makeRanking);
    } else {
        std::for_each(mPrimaryRefreshRates.rbegin(), mPrimaryRefreshRates.rend(), makeRanking);
    }

    if (!rankings.empty() || !anchorGroupOpt) {
        return rankings;
    }

    ALOGW("Can't find %s refresh rate by policy with the same mode group"
          " as the mode group %d",
          refreshRateOrder == RefreshRateOrder::Ascending ? "min" : "max", anchorGroupOpt.value());

    return getRefreshRatesByPolicyLocked(/*anchorGroupOpt*/ std::nullopt, refreshRateOrder);
}

DisplayModePtr RefreshRateConfigs::getActiveModePtr() const {
    std::lock_guard lock(mLock);
    return getActiveModeItLocked()->second;
@@ -760,9 +797,9 @@ DisplayModeIterator RefreshRateConfigs::getActiveModeItLocked() const {
void RefreshRateConfigs::setActiveModeId(DisplayModeId modeId) {
    std::lock_guard lock(mLock);

    // Invalidate the cached invocation to getBestRefreshRate. This forces
    // the refresh rate to be recomputed on the next call to getBestRefreshRate.
    mGetBestRefreshRateCache.reset();
    // Invalidate the cached invocation to getRankedRefreshRates. This forces
    // the refresh rate to be recomputed on the next call to getRankedRefreshRates.
    mGetRankedRefreshRatesCache.reset();

    mActiveModeIt = mDisplayModes.find(modeId);
    LOG_ALWAYS_FATAL_IF(mActiveModeIt == mDisplayModes.end());
@@ -797,9 +834,9 @@ void RefreshRateConfigs::initializeIdleTimer() {
void RefreshRateConfigs::updateDisplayModes(DisplayModes modes, DisplayModeId activeModeId) {
    std::lock_guard lock(mLock);

    // Invalidate the cached invocation to getBestRefreshRate. This forces
    // the refresh rate to be recomputed on the next call to getBestRefreshRate.
    mGetBestRefreshRateCache.reset();
    // Invalidate the cached invocation to getRankedRefreshRates. This forces
    // the refresh rate to be recomputed on the next call to getRankedRefreshRates.
    mGetRankedRefreshRatesCache.reset();

    mDisplayModes = std::move(modes);
    mActiveModeIt = mDisplayModes.find(activeModeId);
@@ -843,7 +880,7 @@ status_t RefreshRateConfigs::setDisplayManagerPolicy(const Policy& policy) {
        ALOGE("Invalid refresh rate policy: %s", policy.toString().c_str());
        return BAD_VALUE;
    }
    mGetBestRefreshRateCache.reset();
    mGetRankedRefreshRatesCache.reset();
    Policy previousPolicy = *getCurrentPolicyLocked();
    mDisplayManagerPolicy = policy;
    if (*getCurrentPolicyLocked() == previousPolicy) {
@@ -858,7 +895,7 @@ status_t RefreshRateConfigs::setOverridePolicy(const std::optional<Policy>& poli
    if (policy && !isPolicyValidLocked(*policy)) {
        return BAD_VALUE;
    }
    mGetBestRefreshRateCache.reset();
    mGetRankedRefreshRatesCache.reset();
    Policy previousPolicy = *getCurrentPolicyLocked();
    mOverridePolicy = policy;
    if (*getCurrentPolicyLocked() == previousPolicy) {
@@ -958,7 +995,8 @@ RefreshRateConfigs::KernelIdleTimerAction RefreshRateConfigs::getIdleTimerAction
        return KernelIdleTimerAction::TurnOff;
    }

    const DisplayModePtr& maxByPolicy = getMaxRefreshRateByPolicyLocked();
    const DisplayModePtr& maxByPolicy =
            getMaxRefreshRateByPolicyLocked(getActiveModeItLocked()->second->getGroup());
    if (minByPolicy == maxByPolicy) {
        // Turn on the timer when the min of the primary range is below the device min.
        if (const Policy* currentPolicy = getCurrentPolicyLocked();
+28 −12
Original line number Diff line number Diff line
@@ -44,6 +44,15 @@ inline DisplayModeEvent operator|(DisplayModeEvent lhs, DisplayModeEvent rhs) {
    return static_cast<DisplayModeEvent>(static_cast<T>(lhs) | static_cast<T>(rhs));
}

struct RefreshRateRanking {
    DisplayModePtr displayModePtr;
    float score = 0.0f;

    bool operator==(const RefreshRateRanking& ranking) const {
        return displayModePtr == ranking.displayModePtr && score == ranking.score;
    }
};

using FrameRateOverride = DisplayEventReceiver::Event::FrameRateOverride;

/**
@@ -195,9 +204,9 @@ public:
        }
    };

    // Returns the refresh rate that best fits the given layers, and whether the refresh rate was
    // chosen based on touch boost and/or idle timer.
    std::pair<DisplayModePtr, GlobalSignals> getBestRefreshRate(
    // Returns the list in the descending order of refresh rates desired
    // based on their overall score, and the GlobalSignals that were considered.
    std::pair<std::vector<RefreshRateRanking>, GlobalSignals> getRankedRefreshRates(
            const std::vector<LayerRequirement>&, GlobalSignals) const EXCLUDES(mLock);

    FpsRange getSupportedRefreshRateRange() const EXCLUDES(mLock) {
@@ -208,10 +217,6 @@ public:
    std::optional<Fps> onKernelTimerChanged(std::optional<DisplayModeId> desiredActiveModeId,
                                            bool timerExpired) const EXCLUDES(mLock);

    // Returns the highest refresh rate according to the current policy. May change at runtime. Only
    // uses the primary range, not the app request range.
    DisplayModePtr getMaxRefreshRateByPolicy() const EXCLUDES(mLock);

    void setActiveModeId(DisplayModeId) EXCLUDES(mLock) REQUIRES(kMainThreadContext);

    // See mActiveModeIt for thread safety.
@@ -343,7 +348,7 @@ private:
    // See mActiveModeIt for thread safety.
    DisplayModeIterator getActiveModeItLocked() const REQUIRES(mLock);

    std::pair<DisplayModePtr, GlobalSignals> getBestRefreshRateLocked(
    std::pair<std::vector<RefreshRateRanking>, GlobalSignals> getRankedRefreshRatesLocked(
            const std::vector<LayerRequirement>&, GlobalSignals) const REQUIRES(mLock);

    // Returns number of display frames and remainder when dividing the layer refresh period by
@@ -356,12 +361,23 @@ private:

    // Returns the highest refresh rate according to the current policy. May change at runtime. Only
    // uses the primary range, not the app request range.
    const DisplayModePtr& getMaxRefreshRateByPolicyLocked() const REQUIRES(mLock);
    const DisplayModePtr& getMaxRefreshRateByPolicyLocked(int anchorGroup) const REQUIRES(mLock);

    struct RefreshRateScoreComparator;

    enum class RefreshRateOrder { Ascending, Descending };

    // Returns the rankings in RefreshRateOrder. May change at runtime.
    // Only uses the primary range, not the app request range.
    std::vector<RefreshRateRanking> getRefreshRatesByPolicyLocked(std::optional<int> anchorGroupOpt,
                                                                  RefreshRateOrder) const
            REQUIRES(mLock);

    const Policy* getCurrentPolicyLocked() const REQUIRES(mLock);
    bool isPolicyValidLocked(const Policy& policy) const REQUIRES(mLock);

    // Returns the refresh rate score as a ratio to max refresh rate, which has a score of 1.
    float calculateRefreshRateScoreForFps(Fps refreshRate) const REQUIRES(mLock);
    // calculates a score for a layer. Used to determine the display refresh rate
    // and the frame rate override for certains applications.
    float calculateLayerScoreLocked(const LayerRequirement&, Fps refreshRate,
@@ -410,11 +426,11 @@ private:
    const Config mConfig;
    bool mSupportsFrameRateOverrideByContent;

    struct GetBestRefreshRateCache {
    struct GetRankedRefreshRatesCache {
        std::pair<std::vector<LayerRequirement>, GlobalSignals> arguments;
        std::pair<DisplayModePtr, GlobalSignals> result;
        std::pair<std::vector<RefreshRateRanking>, GlobalSignals> result;
    };
    mutable std::optional<GetBestRefreshRateCache> mGetBestRefreshRateCache GUARDED_BY(mLock);
    mutable std::optional<GetRankedRefreshRatesCache> mGetRankedRefreshRatesCache GUARDED_BY(mLock);

    // Declare mIdleTimer last to ensure its thread joins before the mutex/callbacks are destroyed.
    std::mutex mIdleTimerCallbacksMutex;
+7 −4
Original line number Diff line number Diff line
@@ -674,7 +674,9 @@ auto Scheduler::applyPolicy(S Policy::*statePtr, T&& newState) -> GlobalSignals
        if (currentState == newState) return {};
        currentState = std::forward<T>(newState);

        std::tie(newMode, consideredSignals) = chooseDisplayMode();
        const auto [rankings, signals] = getRankedDisplayModes();
        newMode = rankings.front().displayModePtr;
        consideredSignals = signals;
        frameRateOverridesChanged = updateFrameRateOverrides(consideredSignals, newMode->getFps());

        if (mPolicy.mode == newMode) {
@@ -699,7 +701,8 @@ auto Scheduler::applyPolicy(S Policy::*statePtr, T&& newState) -> GlobalSignals
    return consideredSignals;
}

auto Scheduler::chooseDisplayMode() -> std::pair<DisplayModePtr, GlobalSignals> {
auto Scheduler::getRankedDisplayModes()
        -> std::pair<std::vector<RefreshRateRanking>, GlobalSignals> {
    ATRACE_CALL();

    const auto configs = holdRefreshRateConfigs();
@@ -712,14 +715,14 @@ auto Scheduler::chooseDisplayMode() -> std::pair<DisplayModePtr, GlobalSignals>
                                .idle = mPolicy.idleTimer == TimerState::Expired,
                                .powerOnImminent = powerOnImminent};

    return configs->getBestRefreshRate(mPolicy.contentRequirements, signals);
    return configs->getRankedRefreshRates(mPolicy.contentRequirements, signals);
}

DisplayModePtr Scheduler::getPreferredDisplayMode() {
    std::lock_guard<std::mutex> lock(mPolicyLock);
    // Make sure the stored mode is up to date.
    if (mPolicy.mode) {
        mPolicy.mode = chooseDisplayMode().first;
        mPolicy.mode = getRankedDisplayModes().first.front().displayModePtr;
    }
    return mPolicy.mode;
}
+4 −2
Original line number Diff line number Diff line
@@ -269,8 +269,10 @@ private:
    template <typename S, typename T>
    GlobalSignals applyPolicy(S Policy::*, T&&) EXCLUDES(mPolicyLock);

    // Returns the display mode that fulfills the policy, and the signals that were considered.
    std::pair<DisplayModePtr, GlobalSignals> chooseDisplayMode() REQUIRES(mPolicyLock);
    // Returns the list of display modes in descending order of their priority that fulfills the
    // policy, and the signals that were considered.
    std::pair<std::vector<RefreshRateRanking>, GlobalSignals> getRankedDisplayModes()
            REQUIRES(mPolicyLock);

    bool updateFrameRateOverrides(GlobalSignals, Fps displayRefreshRate) REQUIRES(mPolicyLock);

+1 −1
Original line number Diff line number Diff line
@@ -350,7 +350,7 @@ void SchedulerFuzzer::fuzzRefreshRateConfigs() {
    const RefreshRateConfigs::GlobalSignals globalSignals = {.touch = false, .idle = false};
    std::vector<LayerRequirement> layers = {{.weight = mFdp.ConsumeFloatingPoint<float>()}};

    refreshRateConfigs.getBestRefreshRate(layers, globalSignals);
    refreshRateConfigs.getRankedRefreshRates(layers, globalSignals);

    layers[0].name = mFdp.ConsumeRandomLengthString(kRandomStringLength);
    layers[0].ownerUid = mFdp.ConsumeIntegral<uint16_t>();
Loading