Make shouldBeSeamless an enum
We change theboolean shouldBeSemaless to an enum with
three values. This introduces a third value "Default" which
indicates that the layer doesn't have a preference for
seamlessness. This is the default value for Surfaces which
haven't called setFrameRate, or have called setFrameRate(0).
Bug: 161776961
Test: presubmit
Change-Id: I157e332e82e95badc928d6a8135e657cd6984db4
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index b6b754b..ab0d3df 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -1687,9 +1687,9 @@
crop.bottom);
if (layerState.frameRate.rate != 0 ||
layerState.frameRate.type != FrameRateCompatibility::Default) {
- StringAppendF(&result, "% 6.2ffps %15s seamless=%d", layerState.frameRate.rate,
+ StringAppendF(&result, "% 6.2ffps %15s seamless=%s", layerState.frameRate.rate,
frameRateCompatibilityString(layerState.frameRate.type).c_str(),
- layerState.frameRate.shouldBeSeamless);
+ toString(layerState.frameRate.seamlessness).c_str());
} else {
StringAppendF(&result, " ");
}
@@ -2754,7 +2754,7 @@
std::ostream& operator<<(std::ostream& stream, const Layer::FrameRate& rate) {
return stream << "{rate=" << rate.rate
<< " type=" << Layer::frameRateCompatibilityString(rate.type)
- << " shouldBeSeamless=" << rate.shouldBeSeamless << "}";
+ << " seamlessness=" << toString(rate.seamlessness) << "}";
}
}; // namespace android
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 8d67ce5..75d68a1 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -49,7 +49,9 @@
#include "LayerVector.h"
#include "MonitoredProducer.h"
#include "RenderArea.h"
+#include "Scheduler/Seamlessness.h"
#include "SurfaceFlinger.h"
+#include "SurfaceTracing.h"
#include "TransactionCompletedThread.h"
using namespace android::surfaceflinger;
@@ -151,17 +153,21 @@
// Encapsulates the frame rate and compatibility of the layer. This information will be used
// when the display refresh rate is determined.
struct FrameRate {
+ using Seamlessness = scheduler::Seamlessness;
+
float rate;
FrameRateCompatibility type;
- bool shouldBeSeamless;
+ Seamlessness seamlessness;
- FrameRate() : rate(0), type(FrameRateCompatibility::Default), shouldBeSeamless(true) {}
+ FrameRate()
+ : rate(0),
+ type(FrameRateCompatibility::Default),
+ seamlessness(Seamlessness::Default) {}
FrameRate(float rate, FrameRateCompatibility type, bool shouldBeSeamless = true)
- : rate(rate), type(type), shouldBeSeamless(shouldBeSeamless) {}
+ : rate(rate), type(type), seamlessness(getSeamlessness(rate, shouldBeSeamless)) {}
bool operator==(const FrameRate& other) const {
- return rate == other.rate && type == other.type &&
- shouldBeSeamless == other.shouldBeSeamless;
+ return rate == other.rate && type == other.type && seamlessness == other.seamlessness;
}
bool operator!=(const FrameRate& other) const { return !(*this == other); }
@@ -169,6 +175,19 @@
// Convert an ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_* value to a
// Layer::FrameRateCompatibility. Logs fatal if the compatibility value is invalid.
static FrameRateCompatibility convertCompatibility(int8_t compatibility);
+
+ private:
+ static Seamlessness getSeamlessness(float rate, bool shouldBeSeamless) {
+ if (rate == 0.0f) {
+ // Refresh rate of 0 is a special value which should reset the vote to
+ // its default value.
+ return Seamlessness::Default;
+ } else if (shouldBeSeamless) {
+ return Seamlessness::OnlySeamless;
+ } else {
+ return Seamlessness::SeamedAndSeamless;
+ }
+ }
};
struct State {
diff --git a/services/surfaceflinger/Scheduler/LayerHistory.cpp b/services/surfaceflinger/Scheduler/LayerHistory.cpp
index 28af930..359ee26 100644
--- a/services/surfaceflinger/Scheduler/LayerHistory.cpp
+++ b/services/surfaceflinger/Scheduler/LayerHistory.cpp
@@ -129,8 +129,7 @@
RefreshRateConfigs::LayerRequirement{.name = layer->getName(),
.vote = voteType,
.desiredRefreshRate = frameRate.rate,
- .shouldBeSeamless =
- frameRate.shouldBeSeamless,
+ .seamlessness = frameRate.seamlessness,
.weight = 1.0f,
.focused = layerFocused});
} else if (recent) {
@@ -139,7 +138,8 @@
.vote = LayerVoteType::Heuristic,
.desiredRefreshRate =
info->getRefreshRate(now),
- .shouldBeSeamless = true,
+ .seamlessness =
+ Seamlessness::OnlySeamless,
.weight = 1.0f,
.focused = layerFocused});
}
diff --git a/services/surfaceflinger/Scheduler/LayerHistoryV2.cpp b/services/surfaceflinger/Scheduler/LayerHistoryV2.cpp
index a63ccc1..e919d1b 100644
--- a/services/surfaceflinger/Scheduler/LayerHistoryV2.cpp
+++ b/services/surfaceflinger/Scheduler/LayerHistoryV2.cpp
@@ -144,8 +144,8 @@
const float layerArea = transformed.getWidth() * transformed.getHeight();
float weight = mDisplayArea ? layerArea / mDisplayArea : 0.0f;
- summary.push_back({strong->getName(), vote.type, vote.fps, vote.shouldBeSeamless, weight,
- layerFocused});
+ summary.push_back(
+ {strong->getName(), vote.type, vote.fps, vote.seamlessness, weight, layerFocused});
if (CC_UNLIKELY(mTraceEnabled)) {
trace(layer, *info, vote.type, static_cast<int>(std::round(vote.fps)));
@@ -179,7 +179,7 @@
if (frameRate.rate > 0 || voteType == LayerVoteType::NoVote) {
const auto type = layer->isVisible() ? voteType : LayerVoteType::NoVote;
- info->setLayerVote({type, frameRate.rate, frameRate.shouldBeSeamless});
+ info->setLayerVote({type, frameRate.rate, frameRate.seamlessness});
} else {
info->resetLayerVote();
}
diff --git a/services/surfaceflinger/Scheduler/LayerInfoV2.h b/services/surfaceflinger/Scheduler/LayerInfoV2.h
index 2305bc3..f94f4ab 100644
--- a/services/surfaceflinger/Scheduler/LayerInfoV2.h
+++ b/services/surfaceflinger/Scheduler/LayerInfoV2.h
@@ -23,6 +23,7 @@
#include "LayerHistory.h"
#include "RefreshRateConfigs.h"
+#include "Scheduler/Seamlessness.h"
#include "SchedulerUtils.h"
namespace android {
@@ -60,7 +61,7 @@
struct LayerVote {
LayerHistory::LayerVoteType type = LayerHistory::LayerVoteType::Heuristic;
float fps = 0.0f;
- bool shouldBeSeamless = true;
+ Seamlessness seamlessness = Seamlessness::Default;
};
static void setTraceEnabled(bool enabled) { sTraceEnabled = enabled; }
@@ -91,7 +92,7 @@
void setDefaultLayerVote(LayerHistory::LayerVoteType type) { mDefaultVote = type; }
// Resets the layer vote to its default.
- void resetLayerVote() { mLayerVote = {mDefaultVote, 0.0f, true}; }
+ void resetLayerVote() { mLayerVote = {mDefaultVote, 0.0f, Seamlessness::Default}; }
LayerVote getRefreshRateVote(nsecs_t now);
diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
index b872d7a..4ebab3e 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
+++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
@@ -27,6 +27,14 @@
#define LOG_TAG "RefreshRateConfigs"
namespace android::scheduler {
+namespace {
+std::string formatLayerInfo(const RefreshRateConfigs::LayerRequirement& layer, float weight) {
+ return base::StringPrintf("%s (type=%s, weight=%.2f seamlessness=%s) %.2fHz",
+ layer.name.c_str(),
+ RefreshRateConfigs::layerVoteTypeString(layer.vote).c_str(), weight,
+ toString(layer.seamlessness).c_str(), layer.desiredRefreshRate);
+}
+} // namespace
using AllRefreshRatesMapType = RefreshRateConfigs::AllRefreshRatesMapType;
using RefreshRate = RefreshRateConfigs::RefreshRate;
@@ -170,7 +178,7 @@
maxExplicitWeight = std::max(maxExplicitWeight, layer.weight);
}
- if (!layer.shouldBeSeamless) {
+ if (layer.seamlessness == Seamlessness::SeamedAndSeamless) {
seamedLayers++;
}
}
@@ -229,27 +237,38 @@
auto weight = layer.weight;
for (auto i = 0u; i < scores.size(); i++) {
- // If there are no layers with shouldBeSeamless=false and the current
- // config group is different from the default one, this means a layer with
- // shouldBeSeamless=false has just disappeared and we should switch back to
- // the default config group.
- const bool isSeamlessSwitch = seamedLayers > 0
- ? scores[i].first->getConfigGroup() == mCurrentRefreshRate->getConfigGroup()
- : scores[i].first->getConfigGroup() == defaultConfig->getConfigGroup();
+ const bool isSeamlessSwitch =
+ scores[i].first->getConfigGroup() == mCurrentRefreshRate->getConfigGroup();
- if (layer.shouldBeSeamless && !isSeamlessSwitch) {
- ALOGV("%s (weight %.2f) ignores %s (group=%d) to avoid non-seamless switch."
- "Current config = %s",
- layer.name.c_str(), weight, scores[i].first->name.c_str(),
- scores[i].first->getConfigGroup(), mCurrentRefreshRate->toString().c_str());
+ if (layer.seamlessness == Seamlessness::OnlySeamless && !isSeamlessSwitch) {
+ ALOGV("%s ignores %s to avoid non-seamless switch. Current config = %s",
+ formatLayerInfo(layer, weight).c_str(), scores[i].first->toString().c_str(),
+ mCurrentRefreshRate->toString().c_str());
continue;
}
- if (!layer.shouldBeSeamless && !isSeamlessSwitch && !layer.focused) {
- ALOGV("%s (weight %.2f) ignores %s (group=%d) because it's not focused"
- " and the switch is going to be seamed. Current config = %s",
- layer.name.c_str(), weight, scores[i].first->name.c_str(),
- scores[i].first->getConfigGroup(), mCurrentRefreshRate->toString().c_str());
+ if (layer.seamlessness == Seamlessness::SeamedAndSeamless && !isSeamlessSwitch &&
+ !layer.focused) {
+ ALOGV("%s ignores %s because it's not focused and the switch is going to be seamed."
+ " Current config = %s",
+ formatLayerInfo(layer, weight).c_str(), scores[i].first->toString().c_str(),
+ mCurrentRefreshRate->toString().c_str());
+ continue;
+ }
+
+ // Layers with default seamlessness vote for the current config group if
+ // there are layers with seamlessness=SeamedAndSeamless and for the default
+ // config group otherwise. In second case, if the current config group is different
+ // from the default, this means a layer with seamlessness=SeamedAndSeamless has just
+ // disappeared.
+ const bool isInPolicyForDefault = seamedLayers > 0
+ ? scores[i].first->getConfigGroup() == mCurrentRefreshRate->getConfigGroup()
+ : scores[i].first->getConfigGroup() == defaultConfig->getConfigGroup();
+
+ if (layer.seamlessness == Seamlessness::Default && !isInPolicyForDefault &&
+ !layer.focused) {
+ ALOGV("%s ignores %s. Current config = %s", formatLayerInfo(layer, weight).c_str(),
+ scores[i].first->toString().c_str(), mCurrentRefreshRate->toString().c_str());
continue;
}
@@ -267,7 +286,7 @@
const auto ratio = scores[i].first->fps / scores.back().first->fps;
// use ratio^2 to get a lower score the more we get further from peak
const auto layerScore = ratio * ratio;
- ALOGV("%s (Max, weight %.2f) gives %s score of %.2f", layer.name.c_str(), weight,
+ ALOGV("%s gives %s score of %.2f", formatLayerInfo(layer, weight).c_str(),
scores[i].first->name.c_str(), layerScore);
scores[i].second += weight * layerScore;
continue;
@@ -290,9 +309,8 @@
static_cast<float>(actualLayerPeriod));
}();
- ALOGV("%s (ExplicitDefault, weight %.2f) %.2fHz gives %s score of %.2f",
- layer.name.c_str(), weight, 1e9f / layerPeriod, scores[i].first->name.c_str(),
- layerScore);
+ ALOGV("%s gives %s score of %.2f", formatLayerInfo(layer, weight).c_str(),
+ scores[i].first->name.c_str(), layerScore);
scores[i].second += weight * layerScore;
continue;
}
@@ -332,8 +350,7 @@
// Slightly prefer seamless switches.
constexpr float kSeamedSwitchPenalty = 0.95f;
const float seamlessness = isSeamlessSwitch ? 1.0f : kSeamedSwitchPenalty;
- ALOGV("%s (%s, weight %.2f) %.2fHz gives %s score of %.2f", layer.name.c_str(),
- layerVoteTypeString(layer.vote).c_str(), weight, 1e9f / layerPeriod,
+ ALOGV("%s gives %s score of %.2f", formatLayerInfo(layer, weight).c_str(),
scores[i].first->name.c_str(), layerScore);
scores[i].second += weight * layerScore * seamlessness;
continue;
diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
index 3159352..2ef8f0c 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
+++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
@@ -26,6 +26,7 @@
#include "DisplayHardware/HWComposer.h"
#include "HwcStrongTypes.h"
#include "Scheduler/SchedulerUtils.h"
+#include "Scheduler/Seamlessness.h"
#include "Scheduler/StrongTyping.h"
namespace android::scheduler {
@@ -219,7 +220,7 @@
// Layer's desired refresh rate, if applicable.
float desiredRefreshRate = 0.0f;
// If a seamless mode switch is required.
- bool shouldBeSeamless = true;
+ Seamlessness seamlessness = Seamlessness::Default;
// Layer's weight in the range of [0, 1]. The higher the weight the more impact this layer
// would have on choosing the refresh rate.
float weight = 0.0f;
diff --git a/services/surfaceflinger/Scheduler/Seamlessness.h b/services/surfaceflinger/Scheduler/Seamlessness.h
new file mode 100644
index 0000000..3e42a4d
--- /dev/null
+++ b/services/surfaceflinger/Scheduler/Seamlessness.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <cstring>
+#include <ostream>
+
+namespace android {
+namespace scheduler {
+
+// The seamlessness requirement of a Layer.
+enum class Seamlessness {
+ // Indicates a requirement for a seamless mode switch.
+ OnlySeamless,
+ // Indicates that both seamless and seamed mode switches are allowed.
+ SeamedAndSeamless,
+ // Indicates no preference for seamlessness. For such layers the system will
+ // prefer seamless switches, but also non-seamless switches to the group of the
+ // default config are allowed.
+ Default
+};
+
+inline std::string toString(Seamlessness seamlessness) {
+ switch (seamlessness) {
+ case Seamlessness::OnlySeamless:
+ return "OnlySeamless";
+ case Seamlessness::SeamedAndSeamless:
+ return "SeamedAndSeamless";
+ case Seamlessness::Default:
+ return "Default";
+ }
+}
+
+// Used by gtest
+inline std::ostream& operator<<(std::ostream& os, Seamlessness val) {
+ return os << toString(val);
+}
+
+} // namespace scheduler
+} // namespace android
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 604a83a..dbfa881 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -606,8 +606,7 @@
return *mCompositionEngine.get();
}
-void SurfaceFlinger::bootFinished()
-{
+void SurfaceFlinger::bootFinished() {
if (mBootFinished == true) {
ALOGE("Extra call to bootFinished");
return;
@@ -2105,8 +2104,7 @@
getBE().mCompositorTiming.presentLatency = snappedCompositeToPresentLatency;
}
-void SurfaceFlinger::postComposition()
-{
+void SurfaceFlinger::postComposition() {
ATRACE_CALL();
ALOGV("postComposition");
@@ -2295,8 +2293,7 @@
}
}
-void SurfaceFlinger::handleTransaction(uint32_t transactionFlags)
-{
+void SurfaceFlinger::handleTransaction(uint32_t transactionFlags) {
ATRACE_CALL();
// here we keep a copy of the drawing state (that is the state that's
@@ -2658,8 +2655,7 @@
mDrawingState.displays = mCurrentState.displays;
}
-void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags)
-{
+void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) {
const nsecs_t expectedPresentTime = mExpectedPresentTime.load();
// Notify all layers of available frames
@@ -3010,8 +3006,7 @@
}
}
-bool SurfaceFlinger::handlePageFlip()
-{
+bool SurfaceFlinger::handlePageFlip() {
ATRACE_CALL();
ALOGV("handlePageFlip");
@@ -3091,8 +3086,7 @@
return !mLayersWithQueuedFrames.empty() && newDataLatched;
}
-void SurfaceFlinger::invalidateHwcGeometry()
-{
+void SurfaceFlinger::invalidateHwcGeometry() {
mGeometryInvalid = true;
}
@@ -4072,8 +4066,7 @@
setTransactionFlags(eTransactionNeeded);
}
-void SurfaceFlinger::onHandleDestroyed(sp<Layer>& layer)
-{
+void SurfaceFlinger::onHandleDestroyed(sp<Layer>& layer) {
Mutex::Autolock lock(mStateLock);
// If a layer has a parent, we allow it to out-live it's handle
// with the idea that the parent holds a reference and will eventually
diff --git a/services/surfaceflinger/tests/unittests/LayerHistoryTestV2.cpp b/services/surfaceflinger/tests/unittests/LayerHistoryTestV2.cpp
index 3b50321..7bfec9a 100644
--- a/services/surfaceflinger/tests/unittests/LayerHistoryTestV2.cpp
+++ b/services/surfaceflinger/tests/unittests/LayerHistoryTestV2.cpp
@@ -73,12 +73,11 @@
[now](const auto& pair) { return pair.second->isAnimating(now); });
}
- void setLayerInfoVote(Layer* layer,
- LayerHistory::LayerVoteType vote) NO_THREAD_SAFETY_ANALYSIS {
+ void setDefaultLayerVote(Layer* layer,
+ LayerHistory::LayerVoteType vote) NO_THREAD_SAFETY_ANALYSIS {
for (auto& [weak, info] : history().mLayerInfos) {
if (auto strong = weak.promote(); strong && strong.get() == layer) {
info->setDefaultLayerVote(vote);
- info->setLayerVote({vote, 0, false});
return;
}
}
@@ -209,7 +208,7 @@
EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true));
EXPECT_CALL(*layer, getFrameRateForLayerTree()).WillRepeatedly(Return(Layer::FrameRate()));
- setLayerInfoVote(layer.get(), LayerHistory::LayerVoteType::NoVote);
+ setDefaultLayerVote(layer.get(), LayerHistory::LayerVoteType::NoVote);
EXPECT_EQ(1, layerCount());
EXPECT_EQ(0, activeLayerCount());
@@ -236,7 +235,7 @@
EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true));
EXPECT_CALL(*layer, getFrameRateForLayerTree()).WillRepeatedly(Return(Layer::FrameRate()));
- setLayerInfoVote(layer.get(), LayerHistory::LayerVoteType::Min);
+ setDefaultLayerVote(layer.get(), LayerHistory::LayerVoteType::Min);
EXPECT_EQ(1, layerCount());
EXPECT_EQ(0, activeLayerCount());
@@ -264,7 +263,7 @@
EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true));
EXPECT_CALL(*layer, getFrameRateForLayerTree()).WillRepeatedly(Return(Layer::FrameRate()));
- setLayerInfoVote(layer.get(), LayerHistory::LayerVoteType::Max);
+ setDefaultLayerVote(layer.get(), LayerHistory::LayerVoteType::Max);
EXPECT_EQ(1, layerCount());
EXPECT_EQ(0, activeLayerCount());
@@ -310,7 +309,7 @@
EXPECT_EQ(1, frequentLayerCount(time));
// layer became inactive, but the vote stays
- setLayerInfoVote(layer.get(), LayerHistory::LayerVoteType::Heuristic);
+ setDefaultLayerVote(layer.get(), LayerHistory::LayerVoteType::Heuristic);
time += MAX_ACTIVE_LAYER_PERIOD_NS.count();
ASSERT_EQ(1, history().summarize(time).size());
EXPECT_EQ(LayerHistory::LayerVoteType::ExplicitDefault, history().summarize(time)[0].vote);
@@ -343,7 +342,7 @@
EXPECT_EQ(1, frequentLayerCount(time));
// layer became inactive, but the vote stays
- setLayerInfoVote(layer.get(), LayerHistory::LayerVoteType::Heuristic);
+ setDefaultLayerVote(layer.get(), LayerHistory::LayerVoteType::Heuristic);
time += MAX_ACTIVE_LAYER_PERIOD_NS.count();
ASSERT_EQ(1, history().summarize(time).size());
EXPECT_EQ(LayerHistory::LayerVoteType::ExplicitExactOrMultiple,
diff --git a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp
index df76110..5a92d0a 100644
--- a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp
+++ b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp
@@ -310,7 +310,7 @@
/*currentConfigId=*/HWC_CONFIG_ID_60);
const auto makeLayerRequirements = [](float refreshRate) -> std::vector<LayerRequirement> {
- return {{"testLayer", LayerVoteType::Heuristic, refreshRate, /*shouldBeSeamless*/ true,
+ return {{"testLayer", LayerVoteType::Heuristic, refreshRate, Seamlessness::OnlySeamless,
/*weight*/ 1.0f, /*focused*/ false}};
};
@@ -1263,7 +1263,7 @@
auto& layer = layers[0];
layer.vote = LayerVoteType::ExplicitDefault;
layer.desiredRefreshRate = 90.0f;
- layer.shouldBeSeamless = false;
+ layer.seamlessness = Seamlessness::SeamedAndSeamless;
layer.name = "90Hz ExplicitDefault";
layer.focused = true;
@@ -1280,32 +1280,49 @@
.getConfigId());
// Verify that we won't change the group if seamless switch is required.
- layer.shouldBeSeamless = true;
+ layer.seamlessness = Seamlessness::OnlySeamless;
ASSERT_EQ(HWC_CONFIG_ID_60,
refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})
.getConfigId());
- // At this point the default config in the DisplayManager policy with be 60Hz.
- // Verify that if the current config is in another group and there are no layers with
- // shouldBeSeamless=false we'll go back to the default group.
+ // Verify that we won't do a seamless switch if we request the same mode as the default
refreshRateConfigs->setCurrentConfigId(HWC_CONFIG_ID_90);
layer.desiredRefreshRate = 60.0f;
layer.name = "60Hz ExplicitDefault";
- layer.shouldBeSeamless = true;
+ layer.seamlessness = Seamlessness::OnlySeamless;
+ ASSERT_EQ(HWC_CONFIG_ID_90,
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})
+ .getConfigId());
+
+ // Verify that if the current config is in another group and there are no layers with
+ // seamlessness=SeamedAndSeamless we'll go back to the default group.
+ layer.desiredRefreshRate = 60.0f;
+ layer.name = "60Hz ExplicitDefault";
+ layer.seamlessness = Seamlessness::Default;
ASSERT_EQ(HWC_CONFIG_ID_60,
refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})
.getConfigId());
- // If there's a layer with shouldBeSeamless=false, another layer with shouldBeSeamless=true
- // can't change the config group.
+ // If there's a layer with seamlessness=SeamedAndSeamless, another layer with
+ // seamlessness=OnlySeamless can't change the config group.
refreshRateConfigs->setCurrentConfigId(HWC_CONFIG_ID_90);
- auto layer2 = LayerRequirement{.weight = 0.5f};
+ layer.seamlessness = Seamlessness::OnlySeamless;
+
+ layers.push_back(LayerRequirement{.weight = 0.5f});
+ auto& layer2 = layers[layers.size() - 1];
layer2.vote = LayerVoteType::ExplicitDefault;
layer2.desiredRefreshRate = 90.0f;
layer2.name = "90Hz ExplicitDefault";
- layer2.shouldBeSeamless = false;
+ layer2.seamlessness = Seamlessness::SeamedAndSeamless;
layer2.focused = false;
- layers.push_back(layer2);
+
+ ASSERT_EQ(HWC_CONFIG_ID_90,
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})
+ .getConfigId());
+
+ // If there's a layer with seamlessness=SeamedAndSeamless, another layer with
+ // seamlessness=Default can't change the config group.
+ layers[0].seamlessness = Seamlessness::Default;
ASSERT_EQ(HWC_CONFIG_ID_90,
refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})
.getConfigId());
@@ -1326,7 +1343,7 @@
auto& layer = layers[0];
layer.vote = LayerVoteType::ExplicitExactOrMultiple;
layer.desiredRefreshRate = 60.0f;
- layer.shouldBeSeamless = false;
+ layer.seamlessness = Seamlessness::SeamedAndSeamless;
layer.name = "60Hz ExplicitExactOrMultiple";
layer.focused = true;
@@ -1355,13 +1372,13 @@
LayerRequirement>{LayerRequirement{.name = "60Hz ExplicitDefault",
.vote = LayerVoteType::ExplicitDefault,
.desiredRefreshRate = 60.0f,
- .shouldBeSeamless = false,
+ .seamlessness = Seamlessness::SeamedAndSeamless,
.weight = 0.5f,
.focused = false},
LayerRequirement{.name = "25Hz ExplicitExactOrMultiple",
.vote = LayerVoteType::ExplicitExactOrMultiple,
.desiredRefreshRate = 25.0f,
- .shouldBeSeamless = true,
+ .seamlessness = Seamlessness::OnlySeamless,
.weight = 1.0f,
.focused = true}};
auto& seamedLayer = layers[0];