Loading libs/gui/ISurfaceComposer.cpp +46 −0 Original line number Original line Diff line number Diff line Loading @@ -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; } } }; }; Loading Loading @@ -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); } } Loading libs/gui/include/gui/ISurfaceComposer.h +9 −0 Original line number Original line Diff line number Diff line Loading @@ -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; }; }; // ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- Loading Loading @@ -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. }; }; Loading libs/gui/tests/Surface_test.cpp +2 −0 Original line number Original line Diff line number Diff line Loading @@ -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; } Loading services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp +57 −29 Original line number Original line Diff line number Diff line Loading @@ -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) { Loading @@ -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 { Loading Loading @@ -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); Loading @@ -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 Loading @@ -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(); Loading services/surfaceflinger/Scheduler/RefreshRateConfigs.h +49 −16 Original line number Original line Diff line number Diff line Loading @@ -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" Loading Loading @@ -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); Loading Loading @@ -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; Loading @@ -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 Loading
libs/gui/ISurfaceComposer.cpp +46 −0 Original line number Original line Diff line number Diff line Loading @@ -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; } } }; }; Loading Loading @@ -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); } } Loading
libs/gui/include/gui/ISurfaceComposer.h +9 −0 Original line number Original line Diff line number Diff line Loading @@ -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; }; }; // ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- Loading Loading @@ -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. }; }; Loading
libs/gui/tests/Surface_test.cpp +2 −0 Original line number Original line Diff line number Diff line Loading @@ -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; } Loading
services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp +57 −29 Original line number Original line Diff line number Diff line Loading @@ -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) { Loading @@ -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 { Loading Loading @@ -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); Loading @@ -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 Loading @@ -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(); Loading
services/surfaceflinger/Scheduler/RefreshRateConfigs.h +49 −16 Original line number Original line Diff line number Diff line Loading @@ -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" Loading Loading @@ -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); Loading Loading @@ -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; Loading @@ -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