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

Commit 534d4b35 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "SF: Mutable RefreshRateConfigs"

parents 2a829f3c eadf2e71
Loading
Loading
Loading
Loading
+5 −4
Original line number Diff line number Diff line
@@ -233,8 +233,8 @@ void RefreshRateOverlay::setViewport(ui::Size viewport) {
    mFlinger.mTransactionFlags.fetch_or(eTransactionMask);
}

void RefreshRateOverlay::changeRefreshRate(const RefreshRate& refreshRate) {
    mCurrentFps = refreshRate.getFps().getIntValue();
void RefreshRateOverlay::changeRefreshRate(const Fps& fps) {
    mCurrentFps = fps.getIntValue();
    auto buffer = getOrCreateBuffers(*mCurrentFps)[mFrame];
    mLayer->setBuffer(buffer, Fence::NO_FENCE, 0, 0, true, {},
                      mLayer->getHeadFrameNumber(-1 /* expectedPresentTime */),
@@ -258,8 +258,9 @@ void RefreshRateOverlay::onInvalidate() {

void RefreshRateOverlay::reset() {
    mBufferCache.clear();
    mLowFps = mFlinger.mRefreshRateConfigs->getMinRefreshRate().getFps().getIntValue();
    mHighFps = mFlinger.mRefreshRateConfigs->getMaxRefreshRate().getFps().getIntValue();
    const auto range = mFlinger.mRefreshRateConfigs->getSupportedRefreshRateRange();
    mLowFps = range.min.getIntValue();
    mHighFps = range.max.getIntValue();
}

} // namespace android
+2 −4
Original line number Diff line number Diff line
@@ -23,7 +23,7 @@
#include <ui/Size.h>
#include <utils/StrongPointer.h>

#include "Scheduler/RefreshRateConfigs.h"
#include "Fps.h"

namespace android {

@@ -34,14 +34,12 @@ class IGraphicBufferProducer;
class Layer;
class SurfaceFlinger;

using RefreshRate = scheduler::RefreshRateConfigs::RefreshRate;

class RefreshRateOverlay {
public:
    RefreshRateOverlay(SurfaceFlinger&, bool showSpinner);

    void setViewport(ui::Size);
    void changeRefreshRate(const RefreshRate&);
    void changeRefreshRate(const Fps&);
    void onInvalidate();
    void reset();

+59 −39
Original line number Diff line number Diff line
@@ -39,6 +39,26 @@ std::string formatLayerInfo(const RefreshRateConfigs::LayerRequirement& layer, f
                              toString(layer.seamlessness).c_str(),
                              to_string(layer.desiredRefreshRate).c_str());
}

std::vector<Fps> constructKnownFrameRates(
        const std::vector<std::shared_ptr<const HWC2::Display::Config>>& configs) {
    std::vector<Fps> knownFrameRates = {Fps(24.0f), Fps(30.0f), Fps(45.0f), Fps(60.0f), Fps(72.0f)};
    knownFrameRates.reserve(knownFrameRates.size() + configs.size());

    // Add all supported refresh rates to the set
    for (const auto& config : configs) {
        const auto refreshRate = Fps::fromPeriodNsecs(config->getVsyncPeriod());
        knownFrameRates.emplace_back(refreshRate);
    }

    // Sort and remove duplicates
    std::sort(knownFrameRates.begin(), knownFrameRates.end(), Fps::comparesLess);
    knownFrameRates.erase(std::unique(knownFrameRates.begin(), knownFrameRates.end(),
                                      Fps::EqualsWithMargin()),
                          knownFrameRates.end());
    return knownFrameRates;
}

} // namespace

using AllRefreshRatesMapType = RefreshRateConfigs::AllRefreshRatesMapType;
@@ -154,8 +174,8 @@ struct RefreshRateScore {
    float score;
};

const RefreshRate& RefreshRateConfigs::getBestRefreshRate(
        const std::vector<LayerRequirement>& layers, const GlobalSignals& globalSignals,
RefreshRate RefreshRateConfigs::getBestRefreshRate(const std::vector<LayerRequirement>& layers,
                                                   const GlobalSignals& globalSignals,
                                                   GlobalSignals* outSignalsConsidered) const {
    ATRACE_CALL();
    ALOGV("getBestRefreshRate %zu layers", layers.size());
@@ -469,9 +489,20 @@ const RefreshRate* RefreshRateConfigs::getBestRefreshRate(Iter begin, Iter end)
    return bestRefreshRate;
}

const RefreshRate& RefreshRateConfigs::getMinRefreshRateByPolicy() const {
std::optional<Fps> RefreshRateConfigs::onKernelTimerChanged(
        std::optional<HwcConfigIndexType> desiredActiveConfigId, bool timerExpired) const {
    std::lock_guard lock(mLock);
    return getMinRefreshRateByPolicyLocked();

    const auto& current = desiredActiveConfigId ? *mRefreshRates.at(*desiredActiveConfigId)
                                                : *mCurrentRefreshRate;
    const auto& min = *mMinSupportedRefreshRate;

    if (current != min) {
        const auto& refreshRate = timerExpired ? min : current;
        return refreshRate.getFps();
    }

    return {};
}

const RefreshRate& RefreshRateConfigs::getMinRefreshRateByPolicyLocked() const {
@@ -487,7 +518,7 @@ const RefreshRate& RefreshRateConfigs::getMinRefreshRateByPolicyLocked() const {
    return *mPrimaryRefreshRates.front();
}

const RefreshRate& RefreshRateConfigs::getMaxRefreshRateByPolicy() const {
RefreshRate RefreshRateConfigs::getMaxRefreshRateByPolicy() const {
    std::lock_guard lock(mLock);
    return getMaxRefreshRateByPolicyLocked();
}
@@ -506,12 +537,12 @@ const RefreshRate& RefreshRateConfigs::getMaxRefreshRateByPolicyLocked() const {
    return *mPrimaryRefreshRates.back();
}

const RefreshRate& RefreshRateConfigs::getCurrentRefreshRate() const {
RefreshRate RefreshRateConfigs::getCurrentRefreshRate() const {
    std::lock_guard lock(mLock);
    return *mCurrentRefreshRate;
}

const RefreshRate& RefreshRateConfigs::getCurrentRefreshRateByPolicy() const {
RefreshRate RefreshRateConfigs::getCurrentRefreshRateByPolicy() const {
    std::lock_guard lock(mLock);
    return getCurrentRefreshRateByPolicyLocked();
}
@@ -533,16 +564,23 @@ RefreshRateConfigs::RefreshRateConfigs(
        const std::vector<std::shared_ptr<const HWC2::Display::Config>>& configs,
        HwcConfigIndexType currentConfigId)
      : mKnownFrameRates(constructKnownFrameRates(configs)) {
    updateDisplayConfigs(configs, currentConfigId);
}

void RefreshRateConfigs::updateDisplayConfigs(
        const std::vector<std::shared_ptr<const HWC2::Display::Config>>& configs,
        HwcConfigIndexType currentConfigId) {
    std::lock_guard lock(mLock);
    LOG_ALWAYS_FATAL_IF(configs.empty());
    LOG_ALWAYS_FATAL_IF(currentConfigId.value() < 0);
    LOG_ALWAYS_FATAL_IF(currentConfigId.value() >= configs.size());

    mRefreshRates.clear();
    for (auto configId = HwcConfigIndexType(0); configId.value() < configs.size(); configId++) {
        const auto& config = configs.at(static_cast<size_t>(configId.value()));
        const auto fps = Fps::fromPeriodNsecs(config->getVsyncPeriod());
        mRefreshRates.emplace(configId,
                              std::make_unique<RefreshRate>(configId, config,
                                                            Fps::fromPeriodNsecs(
                                                                    config->getVsyncPeriod()),
                              std::make_unique<RefreshRate>(configId, config, fps,
                                                            RefreshRate::ConstructorTag(0)));
        if (configId == currentConfigId) {
            mCurrentRefreshRate = mRefreshRates.at(configId).get();
@@ -550,7 +588,7 @@ RefreshRateConfigs::RefreshRateConfigs(
    }

    std::vector<const RefreshRate*> sortedConfigs;
    getSortedRefreshRateList([](const RefreshRate&) { return true; }, &sortedConfigs);
    getSortedRefreshRateListLocked([](const RefreshRate&) { return true; }, &sortedConfigs);
    mDisplayManagerPolicy.defaultConfig = currentConfigId;
    mMinSupportedRefreshRate = sortedConfigs.front();
    mMaxSupportedRefreshRate = sortedConfigs.back();
@@ -570,7 +608,7 @@ RefreshRateConfigs::RefreshRateConfigs(
    constructAvailableRefreshRates();
}

bool RefreshRateConfigs::isPolicyValid(const Policy& policy) {
bool RefreshRateConfigs::isPolicyValidLocked(const Policy& policy) const {
    // defaultConfig must be a valid config, and within the given refresh rate range.
    auto iter = mRefreshRates.find(policy.defaultConfig);
    if (iter == mRefreshRates.end()) {
@@ -588,7 +626,7 @@ bool RefreshRateConfigs::isPolicyValid(const Policy& policy) {

status_t RefreshRateConfigs::setDisplayManagerPolicy(const Policy& policy) {
    std::lock_guard lock(mLock);
    if (!isPolicyValid(policy)) {
    if (!isPolicyValidLocked(policy)) {
        ALOGE("Invalid refresh rate policy: %s", policy.toString().c_str());
        return BAD_VALUE;
    }
@@ -603,7 +641,7 @@ status_t RefreshRateConfigs::setDisplayManagerPolicy(const Policy& policy) {

status_t RefreshRateConfigs::setOverridePolicy(const std::optional<Policy>& policy) {
    std::lock_guard lock(mLock);
    if (policy && !isPolicyValid(*policy)) {
    if (policy && !isPolicyValidLocked(*policy)) {
        return BAD_VALUE;
    }
    Policy previousPolicy = *getCurrentPolicyLocked();
@@ -639,14 +677,14 @@ bool RefreshRateConfigs::isConfigAllowed(HwcConfigIndexType config) const {
    return false;
}

void RefreshRateConfigs::getSortedRefreshRateList(
void RefreshRateConfigs::getSortedRefreshRateListLocked(
        const std::function<bool(const RefreshRate&)>& shouldAddRefreshRate,
        std::vector<const RefreshRate*>* outRefreshRates) {
    outRefreshRates->clear();
    outRefreshRates->reserve(mRefreshRates.size());
    for (const auto& [type, refreshRate] : mRefreshRates) {
        if (shouldAddRefreshRate(*refreshRate)) {
            ALOGV("getSortedRefreshRateList: config %d added to list policy",
            ALOGV("getSortedRefreshRateListLocked: config %d added to list policy",
                  refreshRate->configId.value());
            outRefreshRates->push_back(refreshRate.get());
        }
@@ -672,8 +710,9 @@ void RefreshRateConfigs::constructAvailableRefreshRates() {
    ALOGV("constructAvailableRefreshRates: %s ", policy->toString().c_str());

    auto filterRefreshRates = [&](Fps min, Fps max, const char* listName,
                                  std::vector<const RefreshRate*>* outRefreshRates) {
        getSortedRefreshRateList(
                                  std::vector<const RefreshRate*>*
                                          outRefreshRates) REQUIRES(mLock) {
        getSortedRefreshRateListLocked(
                [&](const RefreshRate& refreshRate) REQUIRES(mLock) {
                    const auto& hwcConfig = refreshRate.hwcConfig;

@@ -706,25 +745,6 @@ void RefreshRateConfigs::constructAvailableRefreshRates() {
                       &mAppRequestRefreshRates);
}

std::vector<Fps> RefreshRateConfigs::constructKnownFrameRates(
        const std::vector<std::shared_ptr<const HWC2::Display::Config>>& configs) {
    std::vector<Fps> knownFrameRates = {Fps(24.0f), Fps(30.0f), Fps(45.0f), Fps(60.0f), Fps(72.0f)};
    knownFrameRates.reserve(knownFrameRates.size() + configs.size());

    // Add all supported refresh rates to the set
    for (const auto& config : configs) {
        const auto refreshRate = Fps::fromPeriodNsecs(config->getVsyncPeriod());
        knownFrameRates.emplace_back(refreshRate);
    }

    // Sort and remove duplicates
    std::sort(knownFrameRates.begin(), knownFrameRates.end(), Fps::comparesLess);
    knownFrameRates.erase(std::unique(knownFrameRates.begin(), knownFrameRates.end(),
                                      Fps::EqualsWithMargin()),
                          knownFrameRates.end());
    return knownFrameRates;
}

Fps RefreshRateConfigs::findClosestKnownFrameRate(Fps frameRate) const {
    if (frameRate.lessThanOrEqualWithMargin(*mKnownFrameRates.begin())) {
        return *mKnownFrameRates.begin();
@@ -744,7 +764,7 @@ Fps RefreshRateConfigs::findClosestKnownFrameRate(Fps frameRate) const {

RefreshRateConfigs::KernelIdleTimerAction RefreshRateConfigs::getIdleTimerAction() const {
    std::lock_guard lock(mLock);
    const auto& deviceMin = getMinRefreshRate();
    const auto& deviceMin = *mMinSupportedRefreshRate;
    const auto& minByPolicy = getMinRefreshRateByPolicyLocked();
    const auto& maxByPolicy = getMaxRefreshRateByPolicyLocked();

+54 −52
Original line number Diff line number Diff line
@@ -68,8 +68,6 @@ public:
                    std::shared_ptr<const HWC2::Display::Config> config, Fps fps, ConstructorTag)
              : configId(configId), hwcConfig(config), fps(std::move(fps)) {}

        RefreshRate(const RefreshRate&) = delete;

        HwcConfigIndexType getConfigId() const { return configId; }
        nsecs_t getVsyncPeriod() const { return hwcConfig->getVsyncPeriod(); }
        int32_t getConfigGroup() const { return hwcConfig->getConfigGroup(); }
@@ -111,27 +109,26 @@ public:
    using AllRefreshRatesMapType =
            std::unordered_map<HwcConfigIndexType, std::unique_ptr<const RefreshRate>>;

    struct Policy {
    private:
        static constexpr int kAllowGroupSwitchingDefault = false;

    public:
        struct Range {
    struct FpsRange {
        Fps min{0.0f};
        Fps max{std::numeric_limits<float>::max()};

            bool operator==(const Range& other) const {
        bool operator==(const FpsRange& other) const {
            return min.equalsWithMargin(other.min) && max.equalsWithMargin(other.max);
        }

            bool operator!=(const Range& other) const { return !(*this == other); }
        bool operator!=(const FpsRange& other) const { return !(*this == other); }

        std::string toString() const {
                return base::StringPrintf("[%s %s]", to_string(min).c_str(),
                                          to_string(max).c_str());
            return base::StringPrintf("[%s %s]", to_string(min).c_str(), to_string(max).c_str());
        }
    };

    struct Policy {
    private:
        static constexpr int kAllowGroupSwitchingDefault = false;

    public:
        // The default config, used to ensure we only initiate display config switches within the
        // same config group as defaultConfigId's group.
        HwcConfigIndexType defaultConfig;
@@ -140,29 +137,29 @@ public:
        // The primary refresh rate range represents display manager's general guidance on the
        // display configs we'll consider when switching refresh rates. Unless we get an explicit
        // signal from an app, we should stay within this range.
        Range primaryRange;
        FpsRange primaryRange;
        // The app request refresh rate range allows us to consider more display configs when
        // switching refresh rates. Although we should generally stay within the primary range,
        // specific considerations, such as layer frame rate settings specified via the
        // setFrameRate() api, may cause us to go outside the primary range. We never go outside the
        // app request range. The app request range will be greater than or equal to the primary
        // refresh rate range, never smaller.
        Range appRequestRange;
        FpsRange appRequestRange;

        Policy() = default;

        Policy(HwcConfigIndexType defaultConfig, const Range& range)
        Policy(HwcConfigIndexType defaultConfig, const FpsRange& range)
              : Policy(defaultConfig, kAllowGroupSwitchingDefault, range, range) {}

        Policy(HwcConfigIndexType defaultConfig, bool allowGroupSwitching, const Range& range)
        Policy(HwcConfigIndexType defaultConfig, bool allowGroupSwitching, const FpsRange& range)
              : Policy(defaultConfig, allowGroupSwitching, range, range) {}

        Policy(HwcConfigIndexType defaultConfig, const Range& primaryRange,
               const Range& appRequestRange)
        Policy(HwcConfigIndexType defaultConfig, const FpsRange& primaryRange,
               const FpsRange& appRequestRange)
              : Policy(defaultConfig, kAllowGroupSwitchingDefault, primaryRange, appRequestRange) {}

        Policy(HwcConfigIndexType defaultConfig, bool allowGroupSwitching,
               const Range& primaryRange, const Range& appRequestRange)
               const FpsRange& primaryRange, const FpsRange& appRequestRange)
              : defaultConfig(defaultConfig),
                allowGroupSwitching(allowGroupSwitching),
                primaryRange(primaryRange),
@@ -258,35 +255,35 @@ public:
    //   globalSignals - global state of touch and idle
    //   outSignalsConsidered - An output param that tells the caller whether the refresh rate was
    //                          chosen based on touch boost and/or idle timer.
    const RefreshRate& getBestRefreshRate(const std::vector<LayerRequirement>& layers,
    RefreshRate getBestRefreshRate(const std::vector<LayerRequirement>& layers,
                                   const GlobalSignals& globalSignals,
                                   GlobalSignals* outSignalsConsidered = nullptr) const
            EXCLUDES(mLock);

    // Returns the lowest refresh rate supported by the device. This won't change at runtime.
    const RefreshRate& getMinRefreshRate() const { return *mMinSupportedRefreshRate; }

    // Returns the lowest refresh rate according to the current policy. May change at runtime. Only
    // uses the primary range, not the app request range.
    const RefreshRate& getMinRefreshRateByPolicy() const EXCLUDES(mLock);
    FpsRange getSupportedRefreshRateRange() const EXCLUDES(mLock) {
        std::lock_guard lock(mLock);
        return {mMinSupportedRefreshRate->getFps(), mMaxSupportedRefreshRate->getFps()};
    }

    // Returns the highest refresh rate supported by the device. This won't change at runtime.
    const RefreshRate& getMaxRefreshRate() const { return *mMaxSupportedRefreshRate; }
    std::optional<Fps> onKernelTimerChanged(std::optional<HwcConfigIndexType> desiredActiveConfigId,
                                            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.
    const RefreshRate& getMaxRefreshRateByPolicy() const EXCLUDES(mLock);
    RefreshRate getMaxRefreshRateByPolicy() const EXCLUDES(mLock);

    // Returns the current refresh rate
    const RefreshRate& getCurrentRefreshRate() const EXCLUDES(mLock);
    RefreshRate getCurrentRefreshRate() const EXCLUDES(mLock);

    // Returns the current refresh rate, if allowed. Otherwise the default that is allowed by
    // the policy.
    const RefreshRate& getCurrentRefreshRateByPolicy() const;
    RefreshRate getCurrentRefreshRateByPolicy() const;

    // Returns the refresh rate that corresponds to a HwcConfigIndexType. This won't change at
    // Returns the refresh rate that corresponds to a HwcConfigIndexType. This may change at
    // runtime.
    const RefreshRate& getRefreshRateFromConfigId(HwcConfigIndexType configId) const {
    // TODO(b/159590486) An invalid config id may be given here if the dipslay configs have changed.
    RefreshRate getRefreshRateFromConfigId(HwcConfigIndexType configId) const EXCLUDES(mLock) {
        std::lock_guard lock(mLock);
        return *mRefreshRates.at(configId);
    };

@@ -302,10 +299,17 @@ public:
    RefreshRateConfigs(const std::vector<std::shared_ptr<const HWC2::Display::Config>>& configs,
                       HwcConfigIndexType currentConfigId);

    void updateDisplayConfigs(
            const std::vector<std::shared_ptr<const HWC2::Display::Config>>& configs,
            HwcConfigIndexType currentConfig) EXCLUDES(mLock);

    // Returns whether switching configs (refresh rate or resolution) is possible.
    // TODO(b/158780872): Consider HAL support, and skip frame rate detection if the configs only
    // differ in resolution.
    bool canSwitch() const { return mRefreshRates.size() > 1; }
    bool canSwitch() const EXCLUDES(mLock) {
        std::lock_guard lock(mLock);
        return mRefreshRates.size() > 1;
    }

    // Class to enumerate options around toggling the kernel timer on and off. We have an option
    // for no change to avoid extra calls to kernel.
@@ -334,12 +338,10 @@ private:
    friend class RefreshRateConfigsTest;

    void constructAvailableRefreshRates() REQUIRES(mLock);
    static std::vector<Fps> constructKnownFrameRates(
            const std::vector<std::shared_ptr<const HWC2::Display::Config>>& configs);

    void getSortedRefreshRateList(
    void getSortedRefreshRateListLocked(
            const std::function<bool(const RefreshRate&)>& shouldAddRefreshRate,
            std::vector<const RefreshRate*>* outRefreshRates);
            std::vector<const RefreshRate*>* outRefreshRates) REQUIRES(mLock);

    // Returns the refresh rate with the highest score in the collection specified from begin
    // to end. If there are more than one with the same highest refresh rate, the first one is
@@ -364,7 +366,7 @@ private:
    const RefreshRate& getCurrentRefreshRateByPolicyLocked() const REQUIRES(mLock);

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

    // Return the display refresh rate divider to match the layer
    // frame rate, or 0 if the display refresh rate is not a multiple of the
@@ -376,9 +378,9 @@ private:
    float calculateLayerScoreLocked(const LayerRequirement&, const RefreshRate&,
                                    bool isSeamlessSwitch) const REQUIRES(mLock);

    // The list of refresh rates, indexed by display config ID. This must not change after this
    // The list of refresh rates, indexed by display config ID. This may change after this
    // object is initialized.
    AllRefreshRatesMapType mRefreshRates;
    AllRefreshRatesMapType mRefreshRates GUARDED_BY(mLock);

    // The list of refresh rates in the primary range of the current policy, ordered by vsyncPeriod
    // (the first element is the lowest refresh rate).
@@ -398,9 +400,9 @@ private:
    std::optional<Policy> mOverridePolicy GUARDED_BY(mLock);

    // The min and max refresh rates supported by the device.
    // This will not change at runtime.
    const RefreshRate* mMinSupportedRefreshRate;
    const RefreshRate* mMaxSupportedRefreshRate;
    // This may change at runtime.
    const RefreshRate* mMinSupportedRefreshRate GUARDED_BY(mLock);
    const RefreshRate* mMaxSupportedRefreshRate GUARDED_BY(mLock);

    mutable std::mutex mLock;

+2 −2
Original line number Diff line number Diff line
@@ -612,7 +612,7 @@ void Scheduler::chooseRefreshRateForContent() {
        mFeatures.contentRequirements = summary;

        newConfigId = calculateRefreshRateConfigIndexType(&consideredSignals);
        auto& newRefreshRate = mRefreshRateConfigs.getRefreshRateFromConfigId(newConfigId);
        auto newRefreshRate = mRefreshRateConfigs.getRefreshRateFromConfigId(newConfigId);
        frameRateOverridesChanged =
                updateFrameRateOverrides(consideredSignals, newRefreshRate.getFps());

@@ -629,7 +629,7 @@ void Scheduler::chooseRefreshRateForContent() {
        }
    }
    if (frameRateChanged) {
        auto& newRefreshRate = mRefreshRateConfigs.getRefreshRateFromConfigId(newConfigId);
        auto newRefreshRate = mRefreshRateConfigs.getRefreshRateFromConfigId(newConfigId);
        mSchedulerCallback.changeRefreshRate(newRefreshRate,
                                             consideredSignals.idle ? ConfigEvent::None
                                                                    : ConfigEvent::Changed);
Loading