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

Commit fcf9aece authored by Steven Thomas's avatar Steven Thomas Committed by Android (Google) Code Review
Browse files

Merge "Add frame rate flexibility token" into rvc-dev

parents e9c8f5f5 d407190b
Loading
Loading
Loading
Loading
+46 −0
Original line number Original line Diff line number Diff line
@@ -1145,6 +1145,42 @@ public:
            ALOGE("setFrameRate: failed to transact: %s (%d)", strerror(-err), err);
            ALOGE("setFrameRate: failed to transact: %s (%d)", strerror(-err), err);
            return err;
            return err;
        }
        }

        return reply.readInt32();
    }

    virtual status_t acquireFrameRateFlexibilityToken(sp<IBinder>* outToken) {
        if (!outToken) return BAD_VALUE;

        Parcel data, reply;
        status_t err = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
        if (err != NO_ERROR) {
            ALOGE("acquireFrameRateFlexibilityToken: failed writing interface token: %s (%d)",
                  strerror(-err), -err);
            return err;
        }

        err = remote()->transact(BnSurfaceComposer::ACQUIRE_FRAME_RATE_FLEXIBILITY_TOKEN, data,
                                 &reply);
        if (err != NO_ERROR) {
            ALOGE("acquireFrameRateFlexibilityToken: failed to transact: %s (%d)", strerror(-err),
                  err);
            return err;
        }

        err = reply.readInt32();
        if (err != NO_ERROR) {
            ALOGE("acquireFrameRateFlexibilityToken: call failed: %s (%d)", strerror(-err), err);
            return err;
        }

        err = reply.readStrongBinder(outToken);
        if (err != NO_ERROR) {
            ALOGE("acquireFrameRateFlexibilityToken: failed reading binder token: %s (%d)",
                  strerror(-err), err);
            return err;
        }

        return NO_ERROR;
        return NO_ERROR;
    }
    }
};
};
@@ -1945,6 +1981,16 @@ status_t BnSurfaceComposer::onTransact(
            reply->writeInt32(result);
            reply->writeInt32(result);
            return NO_ERROR;
            return NO_ERROR;
        }
        }
        case ACQUIRE_FRAME_RATE_FLEXIBILITY_TOKEN: {
            CHECK_INTERFACE(ISurfaceComposer, data, reply);
            sp<IBinder> token;
            status_t result = acquireFrameRateFlexibilityToken(&token);
            reply->writeInt32(result);
            if (result == NO_ERROR) {
                reply->writeStrongBinder(token);
            }
            return NO_ERROR;
        }
        default: {
        default: {
            return BBinder::onTransact(code, data, reply, flags);
            return BBinder::onTransact(code, data, reply, flags);
        }
        }
+9 −0
Original line number Original line Diff line number Diff line
@@ -508,6 +508,14 @@ public:
     */
     */
    virtual status_t setFrameRate(const sp<IGraphicBufferProducer>& surface, float frameRate,
    virtual status_t setFrameRate(const sp<IGraphicBufferProducer>& surface, float frameRate,
                                  int8_t compatibility) = 0;
                                  int8_t compatibility) = 0;

    /*
     * Acquire a frame rate flexibility token from SurfaceFlinger. While this token is acquired,
     * surface flinger will freely switch between frame rates in any way it sees fit, regardless of
     * the current restrictions applied by DisplayManager. This is useful to get consistent behavior
     * for tests. Release the token by releasing the returned IBinder reference.
     */
    virtual status_t acquireFrameRateFlexibilityToken(sp<IBinder>* outToken) = 0;
};
};


// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
@@ -566,6 +574,7 @@ public:
        GET_GAME_CONTENT_TYPE_SUPPORT,
        GET_GAME_CONTENT_TYPE_SUPPORT,
        SET_GAME_CONTENT_TYPE,
        SET_GAME_CONTENT_TYPE,
        SET_FRAME_RATE,
        SET_FRAME_RATE,
        ACQUIRE_FRAME_RATE_FLEXIBILITY_TOKEN,
        // Always append new enum to the end.
        // Always append new enum to the end.
    };
    };


+2 −0
Original line number Original line Diff line number Diff line
@@ -859,6 +859,8 @@ public:
        return NO_ERROR;
        return NO_ERROR;
    }
    }


    status_t acquireFrameRateFlexibilityToken(sp<IBinder>* /*outToken*/) { return NO_ERROR; }

protected:
protected:
    IBinder* onAsBinder() override { return nullptr; }
    IBinder* onAsBinder() override { return nullptr; }


+57 −29
Original line number Original line Diff line number Diff line
@@ -301,7 +301,7 @@ const RefreshRate& RefreshRateConfigs::getCurrentRefreshRateByPolicyLocked() con
                  mCurrentRefreshRate) != mAvailableRefreshRates.end()) {
                  mCurrentRefreshRate) != mAvailableRefreshRates.end()) {
        return *mCurrentRefreshRate;
        return *mCurrentRefreshRate;
    }
    }
    return *mRefreshRates.at(mDefaultConfig);
    return *mRefreshRates.at(getCurrentPolicyLocked()->defaultConfig);
}
}


void RefreshRateConfigs::setCurrentConfigId(HwcConfigIndexType configId) {
void RefreshRateConfigs::setCurrentConfigId(HwcConfigIndexType configId) {
@@ -326,38 +326,59 @@ RefreshRateConfigs::RefreshRateConfigs(
    init(inputConfigs, currentConfigId);
    init(inputConfigs, currentConfigId);
}
}


status_t RefreshRateConfigs::setPolicy(HwcConfigIndexType defaultConfigId, float minRefreshRate,
bool RefreshRateConfigs::isPolicyValid(const Policy& policy) {
                                       float maxRefreshRate, bool* outPolicyChanged) {
    // defaultConfig must be a valid config, and within the given refresh rate range.
    auto iter = mRefreshRates.find(policy.defaultConfig);
    if (iter == mRefreshRates.end()) {
        return false;
    }
    const RefreshRate& refreshRate = *iter->second;
    if (!refreshRate.inPolicy(policy.minRefreshRate, policy.maxRefreshRate)) {
        return false;
    }
    return true;
}

status_t RefreshRateConfigs::setDisplayManagerPolicy(const Policy& policy) {
    std::lock_guard lock(mLock);
    std::lock_guard lock(mLock);
    bool policyChanged = defaultConfigId != mDefaultConfig ||
    if (!isPolicyValid(policy)) {
            minRefreshRate != mMinRefreshRateFps || maxRefreshRate != mMaxRefreshRateFps;
        return BAD_VALUE;
    if (outPolicyChanged) {
        *outPolicyChanged = policyChanged;
    }
    }
    if (!policyChanged) {
    Policy previousPolicy = *getCurrentPolicyLocked();
    mDisplayManagerPolicy = policy;
    if (*getCurrentPolicyLocked() == previousPolicy) {
        return CURRENT_POLICY_UNCHANGED;
    }
    constructAvailableRefreshRates();
    return NO_ERROR;
    return NO_ERROR;
}
}
    // defaultConfigId must be a valid config ID, and within the given refresh rate range.

    if (mRefreshRates.count(defaultConfigId) == 0) {
status_t RefreshRateConfigs::setOverridePolicy(const std::optional<Policy>& policy) {
    std::lock_guard lock(mLock);
    if (policy && !isPolicyValid(*policy)) {
        return BAD_VALUE;
        return BAD_VALUE;
    }
    }
    const RefreshRate& refreshRate = *mRefreshRates.at(defaultConfigId);
    Policy previousPolicy = *getCurrentPolicyLocked();
    if (!refreshRate.inPolicy(minRefreshRate, maxRefreshRate)) {
    mOverridePolicy = policy;
        return BAD_VALUE;
    if (*getCurrentPolicyLocked() == previousPolicy) {
        return CURRENT_POLICY_UNCHANGED;
    }
    }
    mDefaultConfig = defaultConfigId;
    mMinRefreshRateFps = minRefreshRate;
    mMaxRefreshRateFps = maxRefreshRate;
    constructAvailableRefreshRates();
    constructAvailableRefreshRates();
    return NO_ERROR;
    return NO_ERROR;
}
}


void RefreshRateConfigs::getPolicy(HwcConfigIndexType* defaultConfigId, float* minRefreshRate,
const RefreshRateConfigs::Policy* RefreshRateConfigs::getCurrentPolicyLocked() const {
                                   float* maxRefreshRate) const {
    return mOverridePolicy ? &mOverridePolicy.value() : &mDisplayManagerPolicy;
}

RefreshRateConfigs::Policy RefreshRateConfigs::getCurrentPolicy() const {
    std::lock_guard lock(mLock);
    std::lock_guard lock(mLock);
    *defaultConfigId = mDefaultConfig;
    return *getCurrentPolicyLocked();
    *minRefreshRate = mMinRefreshRateFps;
}
    *maxRefreshRate = mMaxRefreshRateFps;

RefreshRateConfigs::Policy RefreshRateConfigs::getDisplayManagerPolicy() const {
    std::lock_guard lock(mLock);
    return mDisplayManagerPolicy;
}
}


bool RefreshRateConfigs::isConfigAllowed(HwcConfigIndexType config) const {
bool RefreshRateConfigs::isConfigAllowed(HwcConfigIndexType config) const {
@@ -385,19 +406,25 @@ void RefreshRateConfigs::getSortedRefreshRateList(


    std::sort(outRefreshRates->begin(), outRefreshRates->end(),
    std::sort(outRefreshRates->begin(), outRefreshRates->end(),
              [](const auto refreshRate1, const auto refreshRate2) {
              [](const auto refreshRate1, const auto refreshRate2) {
                  if (refreshRate1->vsyncPeriod != refreshRate2->vsyncPeriod) {
                      return refreshRate1->vsyncPeriod > refreshRate2->vsyncPeriod;
                      return refreshRate1->vsyncPeriod > refreshRate2->vsyncPeriod;
                  } else {
                      return refreshRate1->configGroup > refreshRate2->configGroup;
                  }
              });
              });
}
}


void RefreshRateConfigs::constructAvailableRefreshRates() {
void RefreshRateConfigs::constructAvailableRefreshRates() {
    // Filter configs based on current policy and sort based on vsync period
    // Filter configs based on current policy and sort based on vsync period
    HwcConfigGroupType group = mRefreshRates.at(mDefaultConfig)->configGroup;
    const Policy* policy = getCurrentPolicyLocked();
    HwcConfigGroupType group = mRefreshRates.at(policy->defaultConfig)->configGroup;
    ALOGV("constructAvailableRefreshRates: default %d group %d min %.2f max %.2f",
    ALOGV("constructAvailableRefreshRates: default %d group %d min %.2f max %.2f",
          mDefaultConfig.value(), group.value(), mMinRefreshRateFps, mMaxRefreshRateFps);
          policy->defaultConfig.value(), group.value(), policy->minRefreshRate,
          policy->maxRefreshRate);
    getSortedRefreshRateList(
    getSortedRefreshRateList(
            [&](const RefreshRate& refreshRate) REQUIRES(mLock) {
            [&](const RefreshRate& refreshRate) REQUIRES(mLock) {
                return refreshRate.configGroup == group &&
                return (policy->allowGroupSwitching || refreshRate.configGroup == group) &&
                        refreshRate.inPolicy(mMinRefreshRateFps, mMaxRefreshRateFps);
                        refreshRate.inPolicy(policy->minRefreshRate, policy->maxRefreshRate);
            },
            },
            &mAvailableRefreshRates);
            &mAvailableRefreshRates);


@@ -409,7 +436,8 @@ void RefreshRateConfigs::constructAvailableRefreshRates() {
    ALOGV("Available refresh rates: %s", availableRefreshRates.c_str());
    ALOGV("Available refresh rates: %s", availableRefreshRates.c_str());
    LOG_ALWAYS_FATAL_IF(mAvailableRefreshRates.empty(),
    LOG_ALWAYS_FATAL_IF(mAvailableRefreshRates.empty(),
                        "No compatible display configs for default=%d min=%.0f max=%.0f",
                        "No compatible display configs for default=%d min=%.0f max=%.0f",
                        mDefaultConfig.value(), mMinRefreshRateFps, mMaxRefreshRateFps);
                        policy->defaultConfig.value(), policy->minRefreshRate,
                        policy->maxRefreshRate);
}
}


// NO_THREAD_SAFETY_ANALYSIS since this is called from the constructor
// NO_THREAD_SAFETY_ANALYSIS since this is called from the constructor
@@ -432,7 +460,7 @@ void RefreshRateConfigs::init(const std::vector<InputConfig>& configs,


    std::vector<const RefreshRate*> sortedConfigs;
    std::vector<const RefreshRate*> sortedConfigs;
    getSortedRefreshRateList([](const RefreshRate&) { return true; }, &sortedConfigs);
    getSortedRefreshRateList([](const RefreshRate&) { return true; }, &sortedConfigs);
    mDefaultConfig = currentHwcConfig;
    mDisplayManagerPolicy.defaultConfig = currentHwcConfig;
    mMinSupportedRefreshRate = sortedConfigs.front();
    mMinSupportedRefreshRate = sortedConfigs.front();
    mMaxSupportedRefreshRate = sortedConfigs.back();
    mMaxSupportedRefreshRate = sortedConfigs.back();
    constructAvailableRefreshRates();
    constructAvailableRefreshRates();
+49 −16
Original line number Original line Diff line number Diff line
@@ -20,6 +20,7 @@


#include <algorithm>
#include <algorithm>
#include <numeric>
#include <numeric>
#include <optional>
#include <type_traits>
#include <type_traits>


#include "DisplayHardware/HWComposer.h"
#include "DisplayHardware/HWComposer.h"
@@ -90,14 +91,47 @@ public:
    using AllRefreshRatesMapType =
    using AllRefreshRatesMapType =
            std::unordered_map<HwcConfigIndexType, std::unique_ptr<const RefreshRate>>;
            std::unordered_map<HwcConfigIndexType, std::unique_ptr<const RefreshRate>>;


    // Sets the current policy to choose refresh rates. Returns NO_ERROR if the requested policy is
    struct Policy {
    // valid, or a negative error value otherwise. policyChanged, if non-null, will be set to true
        // The default config, used to ensure we only initiate display config switches within the
    // if the new policy is different from the old policy.
        // same config group as defaultConfigId's group.
    status_t setPolicy(HwcConfigIndexType defaultConfigId, float minRefreshRate,
        HwcConfigIndexType defaultConfig;
                       float maxRefreshRate, bool* policyChanged) EXCLUDES(mLock);
        // The min and max FPS allowed by the policy.
    // Gets the current policy.
        float minRefreshRate = 0;
    void getPolicy(HwcConfigIndexType* defaultConfigId, float* minRefreshRate,
        float maxRefreshRate = std::numeric_limits<float>::max();
                   float* maxRefreshRate) const EXCLUDES(mLock);
        // Whether or not we switch config groups to get the best frame rate. Only used by tests.
        bool allowGroupSwitching = false;

        bool operator==(const Policy& other) const {
            return defaultConfig == other.defaultConfig && minRefreshRate == other.minRefreshRate &&
                    maxRefreshRate == other.maxRefreshRate &&
                    allowGroupSwitching == other.allowGroupSwitching;
        }

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

    // Return code set*Policy() to indicate the current policy is unchanged.
    static constexpr int CURRENT_POLICY_UNCHANGED = 1;

    // We maintain the display manager policy and the override policy separately. The override
    // policy is used by CTS tests to get a consistent device state for testing. While the override
    // policy is set, it takes precedence over the display manager policy. Once the override policy
    // is cleared, we revert to using the display manager policy.

    // Sets the display manager policy to choose refresh rates. The return value will be:
    //   - A negative value if the policy is invalid or another error occurred.
    //   - NO_ERROR if the policy was successfully updated, and the current policy is different from
    //     what it was before the call.
    //   - CURRENT_POLICY_UNCHANGED if the policy was successfully updated, but the current policy
    //     is the same as it was before the call.
    status_t setDisplayManagerPolicy(const Policy& policy) EXCLUDES(mLock);
    // Sets the override policy. See setDisplayManagerPolicy() for the meaning of the return value.
    status_t setOverridePolicy(const std::optional<Policy>& policy) EXCLUDES(mLock);
    // Gets the current policy, which will be the override policy if active, and the display manager
    // policy otherwise.
    Policy getCurrentPolicy() const EXCLUDES(mLock);
    // Gets the display manager policy, regardless of whether an override policy is active.
    Policy getDisplayManagerPolicy() const EXCLUDES(mLock);


    // Returns true if config is allowed by the current policy.
    // Returns true if config is allowed by the current policy.
    bool isConfigAllowed(HwcConfigIndexType config) const EXCLUDES(mLock);
    bool isConfigAllowed(HwcConfigIndexType config) const EXCLUDES(mLock);
@@ -208,6 +242,9 @@ private:
    // the policy.
    // the policy.
    const RefreshRate& getCurrentRefreshRateByPolicyLocked() const REQUIRES(mLock);
    const RefreshRate& getCurrentRefreshRateByPolicyLocked() const REQUIRES(mLock);


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

    // 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 must not change after this
    // object is initialized.
    // object is initialized.
    AllRefreshRatesMapType mRefreshRates;
    AllRefreshRatesMapType mRefreshRates;
@@ -220,14 +257,10 @@ private:
    // the main thread, and read by the Scheduler (and other objects) on other threads.
    // the main thread, and read by the Scheduler (and other objects) on other threads.
    const RefreshRate* mCurrentRefreshRate GUARDED_BY(mLock);
    const RefreshRate* mCurrentRefreshRate GUARDED_BY(mLock);


    // The default config. This will change at runtime. This is set by SurfaceFlinger on
    // The policy values will change at runtime. They're set by SurfaceFlinger on the main thread,
    // the main thread, and read by the Scheduler (and other objects) on other threads.
    // and read by the Scheduler (and other objects) on other threads.
    HwcConfigIndexType mDefaultConfig GUARDED_BY(mLock);
    Policy mDisplayManagerPolicy GUARDED_BY(mLock);

    std::optional<Policy> mOverridePolicy GUARDED_BY(mLock);
    // The min and max FPS allowed by the policy. This will change at runtime and set by
    // SurfaceFlinger on the main thread.
    float mMinRefreshRateFps GUARDED_BY(mLock) = 0;
    float mMaxRefreshRateFps GUARDED_BY(mLock) = std::numeric_limits<float>::max();


    // The min and max refresh rates supported by the device.
    // The min and max refresh rates supported by the device.
    // This will not change at runtime.
    // This will not change at runtime.
Loading