Merge "Fix latching of final buffer when moving off-screen and destroying" into sc-dev
diff --git a/libs/gui/BLASTBufferQueue.cpp b/libs/gui/BLASTBufferQueue.cpp
index 364c939..e15e11c 100644
--- a/libs/gui/BLASTBufferQueue.cpp
+++ b/libs/gui/BLASTBufferQueue.cpp
@@ -151,7 +151,7 @@
1, false);
static int32_t id = 0;
auto consumerName = mName + "(BLAST Consumer)" + std::to_string(id);
- mPendingBufferTrace = "PendingBuffer - " + mName + "BLAST#" + std::to_string(id);
+ mQueuedBufferTrace = "QueuedBuffer - " + mName + "BLAST#" + std::to_string(id);
id++;
mBufferItemConsumer->setName(String8(consumerName.c_str()));
mBufferItemConsumer->setFrameAvailableListener(this);
@@ -361,16 +361,15 @@
graphicBufferId);
return;
}
-
+ mNumAcquired--;
mBufferItemConsumer->releaseBuffer(it->second, releaseBuffer.releaseFence);
mSubmitted.erase(it);
+ processNextBufferLocked(false /* useNextTransaction */);
}
ATRACE_INT("PendingRelease", mPendingRelease.size());
-
- mNumAcquired--;
- ATRACE_INT(mPendingBufferTrace.c_str(), mNumFrameAvailable + mNumAcquired);
- processNextBufferLocked(false /* useNextTransaction */);
+ ATRACE_INT(mQueuedBufferTrace.c_str(),
+ mNumFrameAvailable + mNumAcquired - mPendingRelease.size());
mCallbackCV.notify_all();
}
@@ -538,7 +537,8 @@
}
// add to shadow queue
mNumFrameAvailable++;
- ATRACE_INT(mPendingBufferTrace.c_str(), mNumFrameAvailable + mNumAcquired);
+ ATRACE_INT(mQueuedBufferTrace.c_str(),
+ mNumFrameAvailable + mNumAcquired - mPendingRelease.size());
BQA_LOGV("onFrameAvailable framenumber=%" PRIu64 " nextTransactionSet=%s", item.mFrameNumber,
toString(nextTransactionSet));
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index c69435d..fd78309 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -182,12 +182,12 @@
void TransactionCompletedListener::addJankListener(const sp<JankDataListener>& listener,
sp<SurfaceControl> surfaceControl) {
- std::scoped_lock<std::recursive_mutex> lock(mJankListenerMutex);
+ std::lock_guard<std::mutex> lock(mMutex);
mJankListeners.insert({surfaceControl->getHandle(), listener});
}
void TransactionCompletedListener::removeJankListener(const sp<JankDataListener>& listener) {
- std::scoped_lock<std::recursive_mutex> lock(mJankListenerMutex);
+ std::lock_guard<std::mutex> lock(mMutex);
for (auto it = mJankListeners.begin(); it != mJankListeners.end();) {
if (it->second == listener) {
it = mJankListeners.erase(it);
@@ -242,6 +242,7 @@
void TransactionCompletedListener::onTransactionCompleted(ListenerStats listenerStats) {
std::unordered_map<CallbackId, CallbackTranslation, CallbackIdHash> callbacksMap;
+ std::multimap<sp<IBinder>, sp<JankDataListener>> jankListenersMap;
{
std::lock_guard<std::mutex> lock(mMutex);
@@ -257,6 +258,7 @@
* sp<SurfaceControl> that could possibly exist for the callbacks.
*/
callbacksMap = mCallbacks;
+ jankListenersMap = mJankListeners;
for (const auto& transactionStats : listenerStats.transactionStats) {
for (auto& callbackId : transactionStats.callbackIds) {
mCallbacks.erase(callbackId);
@@ -352,12 +354,7 @@
}
if (surfaceStats.jankData.empty()) continue;
-
- // Acquire jank listener lock such that we guarantee that after calling unregister,
- // there won't be any further callback.
- std::scoped_lock<std::recursive_mutex> lock(mJankListenerMutex);
- auto copy = mJankListeners;
- auto jankRange = copy.equal_range(surfaceStats.surfaceControl);
+ auto jankRange = jankListenersMap.equal_range(surfaceStats.surfaceControl);
for (auto it = jankRange.first; it != jankRange.second; it++) {
it->second->onJankDataAvailable(surfaceStats.jankData);
}
diff --git a/libs/gui/include/gui/BLASTBufferQueue.h b/libs/gui/include/gui/BLASTBufferQueue.h
index cb0e65e..26c7285 100644
--- a/libs/gui/include/gui/BLASTBufferQueue.h
+++ b/libs/gui/include/gui/BLASTBufferQueue.h
@@ -125,7 +125,11 @@
static PixelFormat convertBufferFormat(PixelFormat& format);
std::string mName;
- std::string mPendingBufferTrace;
+ // Represents the queued buffer count from buffer queue,
+ // pre-BLAST. This is mNumFrameAvailable (buffers that queued to blast) +
+ // mNumAcquired (buffers that queued to SF) mPendingRelease.size() (buffers that are held by
+ // blast). This counter is read by android studio profiler.
+ std::string mQueuedBufferTrace;
sp<SurfaceControl> mSurfaceControl;
std::mutex mMutex;
diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
index fa91bfa..13994fd 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -653,9 +653,6 @@
std::mutex mMutex;
// This lock needs to be recursive so we can unregister a callback from within that callback.
- std::recursive_mutex mJankListenerMutex;
-
- // This lock needs to be recursive so we can unregister a callback from within that callback.
std::recursive_mutex mSurfaceStatsListenerMutex;
bool mListening GUARDED_BY(mMutex) = false;
@@ -680,10 +677,7 @@
std::unordered_map<CallbackId, CallbackTranslation, CallbackIdHash> mCallbacks
GUARDED_BY(mMutex);
-
- // This is protected by mJankListenerMutex, but GUARDED_BY isn't supported for
- // std::recursive_mutex
- std::multimap<sp<IBinder>, sp<JankDataListener>> mJankListeners;
+ std::multimap<sp<IBinder>, sp<JankDataListener>> mJankListeners GUARDED_BY(mMutex);
std::unordered_map<uint64_t /* graphicsBufferId */, ReleaseBufferCallback>
mReleaseBufferCallbacks GUARDED_BY(mMutex);
diff --git a/libs/renderengine/skia/Cache.cpp b/libs/renderengine/skia/Cache.cpp
index b3975b0..725f57b 100644
--- a/libs/renderengine/skia/Cache.cpp
+++ b/libs/renderengine/skia/Cache.cpp
@@ -72,6 +72,8 @@
// have color correction added, and important that it be srgb, so the *vertex* shader
// doesn't have color correction added.
.sourceDataspace = kDestDataSpace,
+ // setting this is mandatory for shadows and blurs
+ .skipContentDraw = true,
};
auto layers = std::vector<const LayerSettings*>{&layer};
@@ -173,9 +175,12 @@
.boundaries = rect,
},
.alpha = 1,
+ // setting this is mandatory for shadows and blurs
+ .skipContentDraw = true,
};
auto layers = std::vector<const LayerSettings*>{&layer};
+ // Different blur code is invoked for radii less and greater than 30 pixels
for (int radius : {9, 60}) {
layer.backgroundBlurRadius = radius;
renderengine->drawLayers(display, layers, dstTexture, kUseFrameBufferCache,
@@ -290,10 +295,13 @@
ExternalTexture::Usage::READABLE |
ExternalTexture::Usage::WRITEABLE);
+ // 6 shaders
drawSolidLayers(renderengine, display, dstTexture);
+ // 8 shaders
drawShadowLayers(renderengine, display, srcTexture);
if (renderengine->supportsBackgroundBlur()) {
+ // 2 shaders
drawBlurLayers(renderengine, display, dstTexture);
}
diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp
index 2281721..726fe8e 100644
--- a/services/sensorservice/SensorService.cpp
+++ b/services/sensorservice/SensorService.cpp
@@ -2161,8 +2161,9 @@
bool SensorService::isRateCappedBasedOnPermission(const String16& opPackageName) {
int targetSdk = getTargetSdkVersion(opPackageName);
- bool hasSamplingRatePermission = PermissionCache::checkCallingPermission(
- sAccessHighSensorSamplingRatePermission);
+ bool hasSamplingRatePermission = checkPermission(sAccessHighSensorSamplingRatePermission,
+ IPCThreadState::self()->getCallingPid(),
+ IPCThreadState::self()->getCallingUid());
if (targetSdk < __ANDROID_API_S__ ||
(targetSdk >= __ANDROID_API_S__ && hasSamplingRatePermission)) {
return false;
diff --git a/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp b/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp
index acc7ed2..22d9dc6 100644
--- a/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp
@@ -378,10 +378,14 @@
if (mLayers.size() == 1) {
base::StringAppendF(&result, " Layer [%s]\n", mLayers[0].getName().c_str());
base::StringAppendF(&result, " Buffer %p", mLayers[0].getBuffer().get());
+ base::StringAppendF(&result, " Protected [%s]",
+ mLayers[0].getState()->isProtected() ? "true" : "false");
} else {
result.append(" Cached set of:");
for (const Layer& layer : mLayers) {
base::StringAppendF(&result, "\n Layer [%s]", layer.getName().c_str());
+ base::StringAppendF(&result, "\n Protected [%s]",
+ layer.getState()->isProtected() ? "true" : "false");
}
}
diff --git a/services/surfaceflinger/CompositionEngine/src/planner/Flattener.cpp b/services/surfaceflinger/CompositionEngine/src/planner/Flattener.cpp
index 2bcaf60..153cee3 100644
--- a/services/surfaceflinger/CompositionEngine/src/planner/Flattener.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/planner/Flattener.cpp
@@ -420,7 +420,7 @@
const bool layerIsInactive = now - currentSet->getLastUpdate() > mActiveLayerTimeout;
const bool layerHasBlur = currentSet->hasBlurBehind();
if (layerIsInactive && (firstLayer || runHasFirstLayer || !layerHasBlur) &&
- !currentSet->hasHdrLayers() && !currentSet->hasProtectedLayers()) {
+ !currentSet->hasHdrLayers()) {
if (isPartOfRun) {
builder.append(currentSet->getLayerCount());
} else {
@@ -491,6 +491,14 @@
return;
}
+ for (const CachedSet& layer : mLayers) {
+ // TODO (b/191997217): make it less aggressive, and sync with findCandidateRuns
+ if (layer.hasProtectedLayers()) {
+ ATRACE_NAME("layer->hasProtectedLayers()");
+ return;
+ }
+ }
+
std::vector<Run> runs = findCandidateRuns(now);
std::optional<Run> bestRun = findBestRun(runs);
diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
index 0eb16e2..0334d70 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
+++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
@@ -107,9 +107,39 @@
return {quotient, remainder};
}
+bool RefreshRateConfigs::isVoteAllowed(const LayerRequirement& layer,
+ const RefreshRate& refreshRate) const {
+ switch (layer.vote) {
+ case LayerVoteType::ExplicitExactOrMultiple:
+ case LayerVoteType::Heuristic:
+ if (mConfig.frameRateMultipleThreshold != 0 &&
+ refreshRate.fps.greaterThanOrEqualWithMargin(
+ Fps(mConfig.frameRateMultipleThreshold)) &&
+ layer.desiredRefreshRate.lessThanWithMargin(
+ Fps(mConfig.frameRateMultipleThreshold / 2))) {
+ // Don't vote high refresh rates past the threshold for layers with a low desired
+ // refresh rate. For example, desired 24 fps with 120 Hz threshold means no vote for
+ // 120 Hz, but desired 60 fps should have a vote.
+ return false;
+ }
+ break;
+ case LayerVoteType::ExplicitDefault:
+ case LayerVoteType::ExplicitExact:
+ case LayerVoteType::Max:
+ case LayerVoteType::Min:
+ case LayerVoteType::NoVote:
+ break;
+ }
+ return true;
+}
+
float RefreshRateConfigs::calculateLayerScoreLocked(const LayerRequirement& layer,
const RefreshRate& refreshRate,
bool isSeamlessSwitch) const {
+ if (!isVoteAllowed(layer, refreshRate)) {
+ return 0;
+ }
+
// Slightly prefer seamless switches.
constexpr float kSeamedSwitchPenalty = 0.95f;
const float seamlessness = isSeamlessSwitch ? 1.0f : kSeamedSwitchPenalty;
@@ -331,8 +361,9 @@
const auto& defaultMode = mRefreshRates.at(policy->defaultMode);
for (const auto& layer : layers) {
- ALOGV("Calculating score for %s (%s, weight %.2f)", layer.name.c_str(),
- layerVoteTypeString(layer.vote).c_str(), layer.weight);
+ ALOGV("Calculating score for %s (%s, weight %.2f, desired %.2f) ", layer.name.c_str(),
+ layerVoteTypeString(layer.vote).c_str(), layer.weight,
+ layer.desiredRefreshRate.getValue());
if (layer.vote == LayerVoteType::NoVote || layer.vote == LayerVoteType::Min) {
continue;
}
@@ -646,9 +677,8 @@
}
RefreshRateConfigs::RefreshRateConfigs(const DisplayModes& modes, DisplayModeId currentModeId,
- bool enableFrameRateOverride)
- : mKnownFrameRates(constructKnownFrameRates(modes)),
- mEnableFrameRateOverride(enableFrameRateOverride) {
+ Config config)
+ : mKnownFrameRates(constructKnownFrameRates(modes)), mConfig(config) {
updateDisplayModes(modes, currentModeId);
}
@@ -685,7 +715,7 @@
mMaxSupportedRefreshRate = sortedModes.back();
mSupportsFrameRateOverride = false;
- if (mEnableFrameRateOverride) {
+ if (mConfig.enableFrameRateOverride) {
for (const auto& mode1 : sortedModes) {
for (const auto& mode2 : sortedModes) {
if (getFrameRateDivider(mode1->getFps(), mode2->getFps()) >= 2) {
@@ -859,6 +889,7 @@
const auto& deviceMin = *mMinSupportedRefreshRate;
const auto& minByPolicy = getMinRefreshRateByPolicyLocked();
const auto& maxByPolicy = getMaxRefreshRateByPolicyLocked();
+ const auto& currentPolicy = getCurrentPolicyLocked();
// Kernel idle timer will set the refresh rate to the device min. If DisplayManager says that
// the min allowed refresh rate is higher than the device min, we do not want to enable the
@@ -867,6 +898,10 @@
return RefreshRateConfigs::KernelIdleTimerAction::TurnOff;
}
if (minByPolicy == maxByPolicy) {
+ // when min primary range in display manager policy is below device min turn on the timer.
+ if (currentPolicy->primaryRange.min.lessThanWithMargin(deviceMin.getFps())) {
+ return RefreshRateConfigs::KernelIdleTimerAction::TurnOn;
+ }
return RefreshRateConfigs::KernelIdleTimerAction::TurnOff;
}
// Turn on the timer in all other cases.
diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
index 6cd0f42..dfd1395 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
+++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
@@ -53,7 +53,7 @@
public:
// Margin used when matching refresh rates to the content desired ones.
static constexpr nsecs_t MARGIN_FOR_PERIOD_CALCULATION =
- std::chrono::nanoseconds(800us).count();
+ std::chrono::nanoseconds(800us).count();
class RefreshRate {
private:
@@ -302,8 +302,19 @@
// Returns a known frame rate that is the closest to frameRate
Fps findClosestKnownFrameRate(Fps frameRate) const;
+ // Configuration flags.
+ struct Config {
+ bool enableFrameRateOverride = false;
+
+ // Specifies the upper refresh rate threshold (inclusive) for layer vote types of multiple
+ // or heuristic, such that refresh rates higher than this value will not be voted for. 0 if
+ // no threshold is set.
+ int frameRateMultipleThreshold = 0;
+ };
+
RefreshRateConfigs(const DisplayModes& modes, DisplayModeId currentModeId,
- bool enableFrameRateOverride = false);
+ Config config = {.enableFrameRateOverride = false,
+ .frameRateMultipleThreshold = 0});
void updateDisplayModes(const DisplayModes& mode, DisplayModeId currentModeId) EXCLUDES(mLock);
@@ -315,8 +326,7 @@
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.
+ // Class to enumerate options around toggling the kernel timer on and off.
enum class KernelIdleTimerAction {
TurnOff, // Turn off the idle timer.
TurnOn // Turn on the idle timer.
@@ -387,6 +397,9 @@
const Policy* getCurrentPolicyLocked() const REQUIRES(mLock);
bool isPolicyValidLocked(const Policy& policy) const REQUIRES(mLock);
+ // Returns whether the layer is allowed to vote for the given refresh rate.
+ bool isVoteAllowed(const LayerRequirement&, const RefreshRate&) const;
+
// 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&, const RefreshRate&,
@@ -424,7 +437,7 @@
// from based on the closest value.
const std::vector<Fps> mKnownFrameRates;
- const bool mEnableFrameRateOverride;
+ const Config mConfig;
bool mSupportsFrameRateOverride;
struct GetBestRefreshRateInvocation {
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index f346465..e2f3ebb 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -3118,10 +3118,15 @@
return;
}
const auto displayId = displayState.physical->id;
- mRefreshRateConfigs = std::make_unique<
- scheduler::RefreshRateConfigs>(displayState.physical->supportedModes,
- displayState.physical->activeMode->getId(),
- android::sysprop::enable_frame_rate_override(false));
+ scheduler::RefreshRateConfigs::Config config =
+ {.enableFrameRateOverride = android::sysprop::enable_frame_rate_override(false),
+ .frameRateMultipleThreshold =
+ base::GetIntProperty("debug.sf.frame_rate_multiple_threshold", 0)};
+ mRefreshRateConfigs =
+ std::make_unique<scheduler::RefreshRateConfigs>(displayState.physical->supportedModes,
+ displayState.physical->activeMode
+ ->getId(),
+ config);
const auto currRefreshRate = displayState.physical->activeMode->getFps();
mRefreshRateStats = std::make_unique<scheduler::RefreshRateStats>(*mTimeStats, currRefreshRate,
hal::PowerMode::OFF);
diff --git a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp
index d4b229f..3423bd5 100644
--- a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp
+++ b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp
@@ -165,6 +165,7 @@
RefreshRate::ConstructorTag(0)};
RefreshRate mExpected120Config = {HWC_CONFIG_ID_120, mConfig120, Fps(120),
RefreshRate::ConstructorTag(0)};
+
private:
DisplayModePtr createDisplayMode(DisplayModeId modeId, int32_t group, int64_t vsyncPeriod,
ui::Size resolution = ui::Size());
@@ -487,6 +488,52 @@
refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
}
+TEST_F(RefreshRateConfigsTest, getBestRefreshRate_multipleThreshold_60_90) {
+ RefreshRateConfigs::Config config = {.frameRateMultipleThreshold = 90};
+ auto refreshRateConfigs =
+ std::make_unique<RefreshRateConfigs>(m60_90Device,
+ /*currentConfigId=*/HWC_CONFIG_ID_60, config);
+
+ auto layers = std::vector<LayerRequirement>{LayerRequirement{.weight = 1.0f}};
+ auto& lr = layers[0];
+
+ lr.vote = LayerVoteType::Min;
+ lr.name = "Min";
+ EXPECT_EQ(mExpected60Config,
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
+
+ lr.vote = LayerVoteType::Max;
+ lr.name = "Max";
+ EXPECT_EQ(mExpected90Config,
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
+
+ lr.desiredRefreshRate = Fps(90.0f);
+ lr.vote = LayerVoteType::Heuristic;
+ lr.name = "90Hz Heuristic";
+ EXPECT_EQ(mExpected90Config,
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
+
+ lr.desiredRefreshRate = Fps(60.0f);
+ lr.name = "60Hz Heuristic";
+ EXPECT_EQ(mExpected60Config,
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
+
+ lr.desiredRefreshRate = Fps(45.0f);
+ lr.name = "45Hz Heuristic";
+ EXPECT_EQ(mExpected90Config,
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
+
+ lr.desiredRefreshRate = Fps(30.0f);
+ lr.name = "30Hz Heuristic";
+ EXPECT_EQ(mExpected60Config,
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
+
+ lr.desiredRefreshRate = Fps(24.0f);
+ lr.name = "24Hz Heuristic";
+ EXPECT_EQ(mExpected60Config,
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
+}
+
TEST_F(RefreshRateConfigsTest, getBestRefreshRate_60_72_90) {
auto refreshRateConfigs =
std::make_unique<RefreshRateConfigs>(m60_72_90Device,
@@ -649,6 +696,99 @@
refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
}
+TEST_F(RefreshRateConfigsTest, getBestRefreshRate_30_60_90_120_DifferentTypes_multipleThreshold) {
+ RefreshRateConfigs::Config config = {.frameRateMultipleThreshold = 120};
+ auto refreshRateConfigs =
+ std::make_unique<RefreshRateConfigs>(m30_60_72_90_120Device,
+ /*currentConfigId=*/HWC_CONFIG_ID_60, config);
+
+ auto layers = std::vector<LayerRequirement>{LayerRequirement{.weight = 1.0f},
+ LayerRequirement{.weight = 1.0f}};
+ auto& lr1 = layers[0];
+ auto& lr2 = layers[1];
+
+ lr1.desiredRefreshRate = Fps(24.0f);
+ lr1.vote = LayerVoteType::ExplicitDefault;
+ lr1.name = "24Hz ExplicitDefault";
+ lr2.desiredRefreshRate = Fps(60.0f);
+ lr2.vote = LayerVoteType::Heuristic;
+ lr2.name = "60Hz Heuristic";
+ EXPECT_EQ(mExpected120Config,
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
+
+ lr1.desiredRefreshRate = Fps(24.0f);
+ lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
+ lr1.name = "24Hz ExplicitExactOrMultiple";
+ lr2.desiredRefreshRate = Fps(60.0f);
+ lr2.vote = LayerVoteType::Heuristic;
+ lr2.name = "60Hz Heuristic";
+ EXPECT_EQ(mExpected60Config,
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
+
+ lr1.desiredRefreshRate = Fps(24.0f);
+ lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
+ lr1.name = "24Hz ExplicitExactOrMultiple";
+ lr2.desiredRefreshRate = Fps(60.0f);
+ lr2.vote = LayerVoteType::ExplicitDefault;
+ lr2.name = "60Hz ExplicitDefault";
+ EXPECT_EQ(mExpected72Config,
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
+
+ lr1.desiredRefreshRate = Fps(24.0f);
+ lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
+ lr1.name = "24Hz ExplicitExactOrMultiple";
+ lr2.desiredRefreshRate = Fps(90.0f);
+ lr2.vote = LayerVoteType::Heuristic;
+ lr2.name = "90Hz Heuristic";
+ EXPECT_EQ(mExpected90Config,
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
+
+ lr1.desiredRefreshRate = Fps(24.0f);
+ lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
+ lr1.name = "24Hz ExplicitExactOrMultiple";
+ lr2.desiredRefreshRate = Fps(90.0f);
+ lr2.vote = LayerVoteType::ExplicitDefault;
+ lr2.name = "90Hz Heuristic";
+ EXPECT_EQ(mExpected72Config,
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
+
+ lr1.desiredRefreshRate = Fps(24.0f);
+ lr1.vote = LayerVoteType::ExplicitDefault;
+ lr1.name = "24Hz ExplicitDefault";
+ lr2.desiredRefreshRate = Fps(90.0f);
+ lr2.vote = LayerVoteType::Heuristic;
+ lr2.name = "90Hz Heuristic";
+ EXPECT_EQ(mExpected90Config,
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
+
+ lr1.desiredRefreshRate = Fps(24.0f);
+ lr1.vote = LayerVoteType::Heuristic;
+ lr1.name = "24Hz Heuristic";
+ lr2.desiredRefreshRate = Fps(90.0f);
+ lr2.vote = LayerVoteType::ExplicitDefault;
+ lr2.name = "90Hz ExplicitDefault";
+ EXPECT_EQ(mExpected72Config,
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
+
+ lr1.desiredRefreshRate = Fps(24.0f);
+ lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
+ lr1.name = "24Hz ExplicitExactOrMultiple";
+ lr2.desiredRefreshRate = Fps(90.0f);
+ lr2.vote = LayerVoteType::ExplicitDefault;
+ lr2.name = "90Hz ExplicitDefault";
+ EXPECT_EQ(mExpected72Config,
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
+
+ lr1.desiredRefreshRate = Fps(24.0f);
+ lr1.vote = LayerVoteType::ExplicitDefault;
+ lr1.name = "24Hz ExplicitDefault";
+ lr2.desiredRefreshRate = Fps(90.0f);
+ lr2.vote = LayerVoteType::ExplicitExactOrMultiple;
+ lr2.name = "90Hz ExplicitExactOrMultiple";
+ EXPECT_EQ(mExpected90Config,
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
+}
+
TEST_F(RefreshRateConfigsTest, getBestRefreshRate_30_60) {
auto refreshRateConfigs =
std::make_unique<RefreshRateConfigs>(m30_60Device,
@@ -819,6 +959,24 @@
}
}
+TEST_F(RefreshRateConfigsTest, getBestRefreshRate_24FpsVideo_multipleThreshold_60_120) {
+ RefreshRateConfigs::Config config = {.frameRateMultipleThreshold = 120};
+ auto refreshRateConfigs =
+ std::make_unique<RefreshRateConfigs>(m60_120Device,
+ /*currentConfigId=*/HWC_CONFIG_ID_60, config);
+
+ auto layers = std::vector<LayerRequirement>{LayerRequirement{.weight = 1.0f}};
+ auto& lr = layers[0];
+
+ lr.vote = LayerVoteType::ExplicitExactOrMultiple;
+ for (float fps = 23.0f; fps < 25.0f; fps += 0.1f) {
+ lr.desiredRefreshRate = Fps(fps);
+ const auto& refreshRate =
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false});
+ EXPECT_EQ(mExpected60Config, refreshRate) << fps << "Hz chooses " << refreshRate.getName();
+ }
+}
+
TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_getBestRefreshRate_Explicit) {
auto refreshRateConfigs =
std::make_unique<RefreshRateConfigs>(m60_90Device,
@@ -1732,10 +1890,10 @@
}
TEST_F(RefreshRateConfigsTest, getBestRefreshRate_ExplicitExactEnableFrameRateOverride) {
+ RefreshRateConfigs::Config config = {.enableFrameRateOverride = true};
auto refreshRateConfigs =
std::make_unique<RefreshRateConfigs>(m30_60_72_90_120Device,
- /*currentConfigId=*/HWC_CONFIG_ID_60,
- /*enableFrameRateOverride=*/true);
+ /*currentConfigId=*/HWC_CONFIG_ID_60, config);
auto layers = std::vector<LayerRequirement>{LayerRequirement{.weight = 1.0f},
LayerRequirement{.weight = 0.5f}};
@@ -1846,10 +2004,10 @@
}
TEST_F(RefreshRateConfigsTest, getBestRefreshRate_ExplicitExactTouchBoost) {
+ RefreshRateConfigs::Config config = {.enableFrameRateOverride = true};
auto refreshRateConfigs =
std::make_unique<RefreshRateConfigs>(m60_120Device,
- /*currentConfigId=*/HWC_CONFIG_ID_60,
- /*enableFrameRateOverride=*/true);
+ /*currentConfigId=*/HWC_CONFIG_ID_60, config);
auto layers = std::vector<LayerRequirement>{LayerRequirement{.weight = 1.0f},
LayerRequirement{.weight = 0.5f}};
@@ -1908,6 +2066,35 @@
EXPECT_EQ(KernelIdleTimerAction::TurnOff, refreshRateConfigs->getIdleTimerAction());
}
+TEST_F(RefreshRateConfigsTest, testKernelIdleTimerActionFor120Hz) {
+ using KernelIdleTimerAction = scheduler::RefreshRateConfigs::KernelIdleTimerAction;
+
+ // Tests with 120Hz
+ auto refreshRateConfigs =
+ std::make_unique<RefreshRateConfigs>(m60_120Device,
+ /*currentConfigId=*/HWC_CONFIG_ID_120);
+ // SetPolicy(0, 60), current 60Hz => TurnOn.
+ ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_60, {Fps(0), Fps(60)}}),
+ 0);
+ EXPECT_EQ(KernelIdleTimerAction::TurnOn, refreshRateConfigs->getIdleTimerAction());
+
+ // SetPolicy(60, 60), current 60Hz => TurnOff.
+ ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_60, {Fps(60), Fps(60)}}),
+ 0);
+ EXPECT_EQ(KernelIdleTimerAction::TurnOff, refreshRateConfigs->getIdleTimerAction());
+
+ // SetPolicy(60, 120), current 60Hz => TurnOn.
+ ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_60, {Fps(60), Fps(120)}}),
+ 0);
+ EXPECT_EQ(KernelIdleTimerAction::TurnOn, refreshRateConfigs->getIdleTimerAction());
+
+ // SetPolicy(120, 120), current 120Hz => TurnOff.
+ ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy(
+ {HWC_CONFIG_ID_120, {Fps(120), Fps(120)}}),
+ 0);
+ EXPECT_EQ(KernelIdleTimerAction::TurnOff, refreshRateConfigs->getIdleTimerAction());
+}
+
TEST_F(RefreshRateConfigsTest, getFrameRateDivider) {
auto refreshRateConfigs =
std::make_unique<RefreshRateConfigs>(m30_60_72_90_120Device,
@@ -1950,10 +2137,10 @@
}
TEST_F(RefreshRateConfigsTest, getFrameRateOverrides_60on120) {
+ RefreshRateConfigs::Config config = {.enableFrameRateOverride = true};
auto refreshRateConfigs =
std::make_unique<RefreshRateConfigs>(m30_60_72_90_120Device, /*currentConfigId=*/
- HWC_CONFIG_ID_120,
- /*enableFrameRateOverride=*/true);
+ HWC_CONFIG_ID_120, config);
auto layers = std::vector<LayerRequirement>{LayerRequirement{.weight = 1.0f}};
layers[0].name = "Test layer";
@@ -1995,10 +2182,10 @@
}
TEST_F(RefreshRateConfigsTest, getFrameRateOverrides_twoUids) {
+ RefreshRateConfigs::Config config = {.enableFrameRateOverride = true};
auto refreshRateConfigs =
std::make_unique<RefreshRateConfigs>(m30_60_72_90_120Device, /*currentConfigId=*/
- HWC_CONFIG_ID_120,
- /*enableFrameRateOverride=*/true);
+ HWC_CONFIG_ID_120, config);
auto layers = std::vector<LayerRequirement>{
LayerRequirement{.ownerUid = 1234, .weight = 1.0f},
@@ -2035,10 +2222,10 @@
}
TEST_F(RefreshRateConfigsTest, getFrameRateOverrides_touch) {
+ RefreshRateConfigs::Config config = {.enableFrameRateOverride = true};
auto refreshRateConfigs =
std::make_unique<RefreshRateConfigs>(m30_60_72_90_120Device, /*currentConfigId=*/
- HWC_CONFIG_ID_120,
- /*enableFrameRateOverride=*/true);
+ HWC_CONFIG_ID_120, config);
auto layers = std::vector<LayerRequirement>{
LayerRequirement{.ownerUid = 1234, .weight = 1.0f},