Merge "arc: Reintroduce the output file option" into rvc-dev
diff --git a/opengl/libs/EGL/egl_platform_entries.cpp b/opengl/libs/EGL/egl_platform_entries.cpp
index 99283be..aa24e8e 100644
--- a/opengl/libs/EGL/egl_platform_entries.cpp
+++ b/opengl/libs/EGL/egl_platform_entries.cpp
@@ -96,7 +96,7 @@
"EGL_EXT_surface_CTA861_3_metadata "
;
-// Whitelist of extensions exposed to applications if implemented in the vendor driver.
+// Allowed list of extensions exposed to applications if implemented in the vendor driver.
char const * const gExtensionString =
"EGL_KHR_image " // mandatory
"EGL_KHR_image_base " // mandatory
diff --git a/services/sensorservice/SensorDeviceUtils.h b/services/sensorservice/SensorDeviceUtils.h
index d7e621c..c232f0b 100644
--- a/services/sensorservice/SensorDeviceUtils.h
+++ b/services/sensorservice/SensorDeviceUtils.h
@@ -36,7 +36,7 @@
// Increase the value of the sensor's nominal resolution to ensure that
// sensor accuracy improvements, like runtime calibration, are not masked
// during requantization.
- double incRes = 0.25 * resolution;
+ double incRes = 0.125 * resolution;
*value = round(static_cast<double>(*value) / incRes) * incRes;
}
diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
index dbdffec..a3f1b52 100644
--- a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
+++ b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
@@ -1676,6 +1676,7 @@
if (found == mReturnData.end()) {
outClientTargetProperty->pixelFormat = PixelFormat::RGBA_8888;
outClientTargetProperty->dataspace = Dataspace::UNKNOWN;
+ return;
}
ReturnData& data = found->second;
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp
index 8ac0561..08559bd 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp
@@ -894,6 +894,10 @@
mComposer.setLayerPerFrameMetadata(mDisplayId, mId, perFrameMetadatas));
if (validTypes & HdrMetadata::HDR10PLUS) {
+ if (CC_UNLIKELY(mHdrMetadata.hdr10plus.size() == 0)) {
+ return Error::BAD_PARAMETER;
+ }
+
std::vector<Hwc2::PerFrameMetadataBlob> perFrameMetadataBlobs;
perFrameMetadataBlobs.push_back(
{Hwc2::PerFrameMetadataKey::HDR10_PLUS_SEI, mHdrMetadata.hdr10plus});
diff --git a/services/surfaceflinger/Scheduler/LayerHistory.h b/services/surfaceflinger/Scheduler/LayerHistory.h
index acd76b0..228b8a0 100644
--- a/services/surfaceflinger/Scheduler/LayerHistory.h
+++ b/services/surfaceflinger/Scheduler/LayerHistory.h
@@ -136,7 +136,7 @@
class LayerHistoryV2 : public android::scheduler::LayerHistory {
public:
- LayerHistoryV2();
+ LayerHistoryV2(const scheduler::RefreshRateConfigs&);
virtual ~LayerHistoryV2();
// Layers are unregistered when the weak reference expires.
diff --git a/services/surfaceflinger/Scheduler/LayerHistoryV2.cpp b/services/surfaceflinger/Scheduler/LayerHistoryV2.cpp
index 316000c..ee612b0 100644
--- a/services/surfaceflinger/Scheduler/LayerHistoryV2.cpp
+++ b/services/surfaceflinger/Scheduler/LayerHistoryV2.cpp
@@ -58,37 +58,32 @@
return atoi(value);
}
-void trace(const wp<Layer>& weak, LayerHistory::LayerVoteType type, int fps) {
+void trace(const wp<Layer>& weak, const LayerInfoV2& info, LayerHistory::LayerVoteType type,
+ int fps) {
const auto layer = weak.promote();
if (!layer) return;
- const auto makeTag = [layer](LayerHistory::LayerVoteType vote) {
- return "LFPS " + RefreshRateConfigs::layerVoteTypeString(vote) + " " + layer->getName();
+ const auto traceType = [&](LayerHistory::LayerVoteType checkedType, int value) {
+ ATRACE_INT(info.getTraceTag(checkedType), type == checkedType ? value : 0);
};
- const auto noVoteTag = makeTag(LayerHistory::LayerVoteType::NoVote);
- const auto heuristicVoteTag = makeTag(LayerHistory::LayerVoteType::Heuristic);
- const auto explicitDefaultVoteTag = makeTag(LayerHistory::LayerVoteType::ExplicitDefault);
- const auto explicitExactOrMultipleVoteTag =
- makeTag(LayerHistory::LayerVoteType::ExplicitExactOrMultiple);
- const auto minVoteTag = makeTag(LayerHistory::LayerVoteType::Min);
- const auto maxVoteTag = makeTag(LayerHistory::LayerVoteType::Max);
-
- ATRACE_INT(noVoteTag.c_str(), type == LayerHistory::LayerVoteType::NoVote ? 1 : 0);
- ATRACE_INT(heuristicVoteTag.c_str(), type == LayerHistory::LayerVoteType::Heuristic ? fps : 0);
- ATRACE_INT(explicitDefaultVoteTag.c_str(),
- type == LayerHistory::LayerVoteType::ExplicitDefault ? fps : 0);
- ATRACE_INT(explicitExactOrMultipleVoteTag.c_str(),
- type == LayerHistory::LayerVoteType::ExplicitExactOrMultiple ? fps : 0);
- ATRACE_INT(minVoteTag.c_str(), type == LayerHistory::LayerVoteType::Min ? 1 : 0);
- ATRACE_INT(maxVoteTag.c_str(), type == LayerHistory::LayerVoteType::Max ? 1 : 0);
+ traceType(LayerHistory::LayerVoteType::NoVote, 1);
+ traceType(LayerHistory::LayerVoteType::Heuristic, fps);
+ traceType(LayerHistory::LayerVoteType::ExplicitDefault, fps);
+ traceType(LayerHistory::LayerVoteType::ExplicitExactOrMultiple, fps);
+ traceType(LayerHistory::LayerVoteType::Min, 1);
+ traceType(LayerHistory::LayerVoteType::Max, 1);
ALOGD("%s: %s @ %d Hz", __FUNCTION__, layer->getName().c_str(), fps);
}
} // namespace
-LayerHistoryV2::LayerHistoryV2()
- : mTraceEnabled(traceEnabled()), mUseFrameRatePriority(useFrameRatePriority()) {}
+LayerHistoryV2::LayerHistoryV2(const scheduler::RefreshRateConfigs& refreshRateConfigs)
+ : mTraceEnabled(traceEnabled()), mUseFrameRatePriority(useFrameRatePriority()) {
+ LayerInfoV2::setTraceEnabled(mTraceEnabled);
+ LayerInfoV2::setRefreshRateConfigs(refreshRateConfigs);
+}
+
LayerHistoryV2::~LayerHistoryV2() = default;
void LayerHistoryV2::registerLayer(Layer* layer, float /*lowRefreshRate*/, float highRefreshRate,
@@ -151,7 +146,7 @@
summary.push_back({strong->getName(), type, refreshRate, weight});
if (CC_UNLIKELY(mTraceEnabled)) {
- trace(layer, type, static_cast<int>(std::round(refreshRate)));
+ trace(layer, *info, type, static_cast<int>(std::round(refreshRate)));
}
}
@@ -190,7 +185,7 @@
}
if (CC_UNLIKELY(mTraceEnabled)) {
- trace(weak, LayerHistory::LayerVoteType::NoVote, 0);
+ trace(weak, *info, LayerHistory::LayerVoteType::NoVote, 0);
}
info->onLayerInactive(now);
@@ -217,4 +212,5 @@
info->clearHistory(systemTime());
}
}
+
} // namespace android::scheduler::impl
diff --git a/services/surfaceflinger/Scheduler/LayerInfo.h b/services/surfaceflinger/Scheduler/LayerInfo.h
index cb81ca2..820624b 100644
--- a/services/surfaceflinger/Scheduler/LayerInfo.h
+++ b/services/surfaceflinger/Scheduler/LayerInfo.h
@@ -98,9 +98,9 @@
return false;
}
- // The layer had to publish at least HISTORY_SIZE or HISTORY_TIME of updates
+ // The layer had to publish at least HISTORY_SIZE or HISTORY_DURATION of updates
if (mElements.size() < HISTORY_SIZE &&
- mElements.back() - mElements.front() < HISTORY_TIME.count()) {
+ mElements.back() - mElements.front() < HISTORY_DURATION.count()) {
return false;
}
@@ -124,7 +124,7 @@
private:
std::deque<nsecs_t> mElements;
- static constexpr std::chrono::nanoseconds HISTORY_TIME = 1s;
+ static constexpr std::chrono::nanoseconds HISTORY_DURATION = 1s;
};
friend class LayerHistoryTest;
diff --git a/services/surfaceflinger/Scheduler/LayerInfoV2.cpp b/services/surfaceflinger/Scheduler/LayerInfoV2.cpp
index 82da007..44f20d0 100644
--- a/services/surfaceflinger/Scheduler/LayerInfoV2.cpp
+++ b/services/surfaceflinger/Scheduler/LayerInfoV2.cpp
@@ -15,24 +15,31 @@
*/
// #define LOG_NDEBUG 0
+#define ATRACE_TAG ATRACE_TAG_GRAPHICS
#include "LayerInfoV2.h"
#include <algorithm>
#include <utility>
+#include <cutils/compiler.h>
+#include <cutils/trace.h>
+
#undef LOG_TAG
#define LOG_TAG "LayerInfoV2"
-#define ATRACE_TAG ATRACE_TAG_GRAPHICS
namespace android::scheduler {
+const RefreshRateConfigs* LayerInfoV2::sRefreshRateConfigs = nullptr;
+bool LayerInfoV2::sTraceEnabled = false;
+
LayerInfoV2::LayerInfoV2(const std::string& name, nsecs_t highRefreshRatePeriod,
LayerHistory::LayerVoteType defaultVote)
: mName(name),
mHighRefreshRatePeriod(highRefreshRatePeriod),
mDefaultVote(defaultVote),
- mLayerVote({defaultVote, 0.0f}) {}
+ mLayerVote({defaultVote, 0.0f}),
+ mRefreshRateHistory(name) {}
void LayerInfoV2::setLastPresentTime(nsecs_t lastPresentTime, nsecs_t now,
LayerUpdateType updateType, bool pendingConfigChange) {
@@ -92,24 +99,28 @@
}
bool LayerInfoV2::hasEnoughDataForHeuristic() const {
- // The layer had to publish at least HISTORY_SIZE or HISTORY_TIME of updates
+ // The layer had to publish at least HISTORY_SIZE or HISTORY_DURATION of updates
if (mFrameTimes.size() < 2) {
+ ALOGV("fewer than 2 frames recorded: %zu", mFrameTimes.size());
return false;
}
if (!isFrameTimeValid(mFrameTimes.front())) {
+ ALOGV("stale frames still captured");
return false;
}
- if (mFrameTimes.size() < HISTORY_SIZE &&
- mFrameTimes.back().queueTime - mFrameTimes.front().queueTime < HISTORY_TIME.count()) {
+ const auto totalDuration = mFrameTimes.back().queueTime - mFrameTimes.front().queueTime;
+ if (mFrameTimes.size() < HISTORY_SIZE && totalDuration < HISTORY_DURATION.count()) {
+ ALOGV("not enough frames captured: %zu | %.2f seconds", mFrameTimes.size(),
+ totalDuration / 1e9f);
return false;
}
return true;
}
-std::pair<nsecs_t, bool> LayerInfoV2::calculateAverageFrameTime() const {
+std::optional<nsecs_t> LayerInfoV2::calculateAverageFrameTime() const {
nsecs_t totalPresentTimeDeltas = 0;
nsecs_t totalQueueTimeDeltas = 0;
bool missingPresentTime = false;
@@ -117,15 +128,20 @@
for (auto it = mFrameTimes.begin(); it != mFrameTimes.end() - 1; ++it) {
// Ignore frames captured during a config change
if (it->pendingConfigChange || (it + 1)->pendingConfigChange) {
- continue;
+ return std::nullopt;
}
totalQueueTimeDeltas +=
std::max(((it + 1)->queueTime - it->queueTime), mHighRefreshRatePeriod);
numFrames++;
- if (it->presetTime == 0 || (it + 1)->presetTime == 0) {
+ if (!missingPresentTime && (it->presetTime == 0 || (it + 1)->presetTime == 0)) {
missingPresentTime = true;
+ // If there are no presentation timestamps and we haven't calculated
+ // one in the past then we can't calculate the refresh rate
+ if (mLastRefreshRate.reported == 0) {
+ return std::nullopt;
+ }
continue;
}
@@ -140,58 +156,46 @@
// when implementing render ahead for specific refresh rates. When hwui no longer provides
// presentation timestamps we look at the queue time to see if the current refresh rate still
// matches the content.
+
const auto averageFrameTime =
static_cast<float>(missingPresentTime ? totalQueueTimeDeltas : totalPresentTimeDeltas) /
numFrames;
- return {static_cast<nsecs_t>(averageFrameTime), missingPresentTime};
+ return static_cast<nsecs_t>(averageFrameTime);
}
-bool LayerInfoV2::isRefreshRateStable(nsecs_t averageFrameTime, bool missingPresentTime) const {
- for (auto it = mFrameTimes.begin(); it != mFrameTimes.end() - 1; ++it) {
- // Ignore frames captured during a config change
- if (it->pendingConfigChange || (it + 1)->pendingConfigChange) {
- continue;
- }
- const auto presentTimeDeltas = [&] {
- const auto delta = missingPresentTime ? (it + 1)->queueTime - it->queueTime
- : (it + 1)->presetTime - it->presetTime;
- return std::max(delta, mHighRefreshRatePeriod);
- }();
-
- if (std::abs(presentTimeDeltas - averageFrameTime) > 2 * averageFrameTime) {
- return false;
- }
- }
-
- return true;
-}
-
-std::optional<float> LayerInfoV2::calculateRefreshRateIfPossible() {
+std::optional<float> LayerInfoV2::calculateRefreshRateIfPossible(nsecs_t now) {
static constexpr float MARGIN = 1.0f; // 1Hz
-
if (!hasEnoughDataForHeuristic()) {
ALOGV("Not enough data");
return std::nullopt;
}
- const auto [averageFrameTime, missingPresentTime] = calculateAverageFrameTime();
+ const auto averageFrameTime = calculateAverageFrameTime();
+ if (averageFrameTime.has_value()) {
+ const auto refreshRate = 1e9f / *averageFrameTime;
+ const bool refreshRateConsistent = mRefreshRateHistory.add(refreshRate, now);
+ if (refreshRateConsistent) {
+ const auto knownRefreshRate =
+ sRefreshRateConfigs->findClosestKnownFrameRate(refreshRate);
- // If there are no presentation timestamps provided we can't calculate the refresh rate
- if (missingPresentTime && mLastReportedRefreshRate == 0) {
- return std::nullopt;
+ // To avoid oscillation, use the last calculated refresh rate if it is
+ // close enough
+ if (std::abs(mLastRefreshRate.calculated - refreshRate) > MARGIN &&
+ mLastRefreshRate.reported != knownRefreshRate) {
+ mLastRefreshRate.calculated = refreshRate;
+ mLastRefreshRate.reported = knownRefreshRate;
+ }
+
+ ALOGV("%s %.2fHz rounded to nearest known frame rate %.2fHz", mName.c_str(),
+ refreshRate, mLastRefreshRate.reported);
+ } else {
+ ALOGV("%s Not stable (%.2fHz) returning last known frame rate %.2fHz", mName.c_str(),
+ refreshRate, mLastRefreshRate.reported);
+ }
}
- if (!isRefreshRateStable(averageFrameTime, missingPresentTime)) {
- return std::nullopt;
- }
-
- const auto refreshRate = 1e9f / averageFrameTime;
- if (std::abs(refreshRate - mLastReportedRefreshRate) > MARGIN) {
- mLastReportedRefreshRate = refreshRate;
- }
-
- ALOGV("Refresh rate: %.2f", mLastReportedRefreshRate);
- return mLastReportedRefreshRate;
+ return mLastRefreshRate.reported == 0 ? std::nullopt
+ : std::make_optional(mLastRefreshRate.reported);
}
std::pair<LayerHistory::LayerVoteType, float> LayerInfoV2::getRefreshRate(nsecs_t now) {
@@ -202,15 +206,24 @@
if (isAnimating(now)) {
ALOGV("%s is animating", mName.c_str());
+ mLastRefreshRate.animatingOrInfrequent = true;
return {LayerHistory::LayerVoteType::Max, 0};
}
if (!isFrequent(now)) {
ALOGV("%s is infrequent", mName.c_str());
+ mLastRefreshRate.animatingOrInfrequent = true;
return {LayerHistory::LayerVoteType::Min, 0};
}
- auto refreshRate = calculateRefreshRateIfPossible();
+ // If the layer was previously tagged as animating or infrequent, we clear
+ // the history as it is likely the layer just changed its behavior
+ // and we should not look at stale data
+ if (mLastRefreshRate.animatingOrInfrequent) {
+ clearHistory(now);
+ }
+
+ auto refreshRate = calculateRefreshRateIfPossible(now);
if (refreshRate.has_value()) {
ALOGV("%s calculated refresh rate: %.2f", mName.c_str(), refreshRate.value());
return {LayerHistory::LayerVoteType::Heuristic, refreshRate.value()};
@@ -220,4 +233,65 @@
return {LayerHistory::LayerVoteType::Max, 0};
}
+const char* LayerInfoV2::getTraceTag(android::scheduler::LayerHistory::LayerVoteType type) const {
+ if (mTraceTags.count(type) == 0) {
+ const auto tag = "LFPS " + mName + " " + RefreshRateConfigs::layerVoteTypeString(type);
+ mTraceTags.emplace(type, tag);
+ }
+
+ return mTraceTags.at(type).c_str();
+}
+
+LayerInfoV2::RefreshRateHistory::HeuristicTraceTagData
+LayerInfoV2::RefreshRateHistory::makeHeuristicTraceTagData() const {
+ const std::string prefix = "LFPS ";
+ const std::string suffix = "Heuristic ";
+ return {.min = prefix + mName + suffix + "min",
+ .max = prefix + mName + suffix + "max",
+ .consistent = prefix + mName + suffix + "consistent",
+ .average = prefix + mName + suffix + "average"};
+}
+
+void LayerInfoV2::RefreshRateHistory::clear() {
+ mRefreshRates.clear();
+}
+
+bool LayerInfoV2::RefreshRateHistory::add(float refreshRate, nsecs_t now) {
+ mRefreshRates.push_back({refreshRate, now});
+ while (mRefreshRates.size() >= HISTORY_SIZE ||
+ now - mRefreshRates.front().timestamp > HISTORY_DURATION.count()) {
+ mRefreshRates.pop_front();
+ }
+
+ if (CC_UNLIKELY(sTraceEnabled)) {
+ if (!mHeuristicTraceTagData.has_value()) {
+ mHeuristicTraceTagData = makeHeuristicTraceTagData();
+ }
+
+ ATRACE_INT(mHeuristicTraceTagData->average.c_str(), static_cast<int>(refreshRate));
+ }
+
+ return isConsistent();
+}
+
+bool LayerInfoV2::RefreshRateHistory::isConsistent() const {
+ if (mRefreshRates.empty()) return true;
+
+ const auto max = std::max_element(mRefreshRates.begin(), mRefreshRates.end());
+ const auto min = std::min_element(mRefreshRates.begin(), mRefreshRates.end());
+ const auto consistent = max->refreshRate - min->refreshRate <= MARGIN_FPS;
+
+ if (CC_UNLIKELY(sTraceEnabled)) {
+ if (!mHeuristicTraceTagData.has_value()) {
+ mHeuristicTraceTagData = makeHeuristicTraceTagData();
+ }
+
+ ATRACE_INT(mHeuristicTraceTagData->max.c_str(), static_cast<int>(max->refreshRate));
+ ATRACE_INT(mHeuristicTraceTagData->min.c_str(), static_cast<int>(min->refreshRate));
+ ATRACE_INT(mHeuristicTraceTagData->consistent.c_str(), consistent);
+ }
+
+ return consistent;
+}
+
} // namespace android::scheduler
diff --git a/services/surfaceflinger/Scheduler/LayerInfoV2.h b/services/surfaceflinger/Scheduler/LayerInfoV2.h
index 9e6783f..33dc66f 100644
--- a/services/surfaceflinger/Scheduler/LayerInfoV2.h
+++ b/services/surfaceflinger/Scheduler/LayerInfoV2.h
@@ -56,6 +56,12 @@
friend class LayerHistoryTestV2;
public:
+ static void setTraceEnabled(bool enabled) { sTraceEnabled = enabled; }
+
+ static void setRefreshRateConfigs(const RefreshRateConfigs& refreshRateConfigs) {
+ sRefreshRateConfigs = &refreshRateConfigs;
+ }
+
LayerInfoV2(const std::string& name, nsecs_t highRefreshRatePeriod,
LayerHistory::LayerVoteType defaultVote);
@@ -86,6 +92,9 @@
// updated time, the updated time is the present time.
nsecs_t getLastUpdatedTime() const { return mLastUpdatedTime; }
+ // Returns a C string for tracing a vote
+ const char* getTraceTag(LayerHistory::LayerVoteType type) const;
+
void onLayerInactive(nsecs_t now) {
// Mark mFrameTimeValidSince to now to ignore all previous frame times.
// We are not deleting the old frame to keep track of whether we should treat the first
@@ -93,7 +102,8 @@
// posting infrequent updates.
const auto timePoint = std::chrono::nanoseconds(now);
mFrameTimeValidSince = std::chrono::time_point<std::chrono::steady_clock>(timePoint);
- mLastReportedRefreshRate = 0.0f;
+ mLastRefreshRate = {};
+ mRefreshRateHistory.clear();
}
void clearHistory(nsecs_t now) {
@@ -109,12 +119,73 @@
bool pendingConfigChange;
};
+ // Holds information about the calculated and reported refresh rate
+ struct RefreshRateHeuristicData {
+ // Rate calculated on the layer
+ float calculated = 0.0f;
+ // Last reported rate for LayerInfoV2::getRefreshRate()
+ float reported = 0.0f;
+ // Whether the last reported rate for LayerInfoV2::getRefreshRate()
+ // was due to animation or infrequent updates
+ bool animatingOrInfrequent = false;
+ };
+
+ // Holds information about the layer vote
+ struct LayerVote {
+ LayerHistory::LayerVoteType type = LayerHistory::LayerVoteType::Heuristic;
+ float fps = 0.0f;
+ };
+
+ // Class to store past calculated refresh rate and determine whether
+ // the refresh rate calculated is consistent with past values
+ class RefreshRateHistory {
+ public:
+ static constexpr auto HISTORY_SIZE = 90;
+ static constexpr std::chrono::nanoseconds HISTORY_DURATION = 2s;
+
+ RefreshRateHistory(const std::string& name) : mName(name) {}
+
+ // Clears History
+ void clear();
+
+ // Adds a new refresh rate and returns true if it is consistent
+ bool add(float refreshRate, nsecs_t now);
+
+ private:
+ friend class LayerHistoryTestV2;
+
+ // Holds the refresh rate when it was calculated
+ struct RefreshRateData {
+ float refreshRate = 0.0f;
+ nsecs_t timestamp = 0;
+
+ bool operator<(const RefreshRateData& other) const {
+ return refreshRate < other.refreshRate;
+ }
+ };
+
+ // Holds tracing strings
+ struct HeuristicTraceTagData {
+ std::string min;
+ std::string max;
+ std::string consistent;
+ std::string average;
+ };
+
+ bool isConsistent() const;
+ HeuristicTraceTagData makeHeuristicTraceTagData() const;
+
+ const std::string mName;
+ mutable std::optional<HeuristicTraceTagData> mHeuristicTraceTagData;
+ std::deque<RefreshRateData> mRefreshRates;
+ static constexpr float MARGIN_FPS = 1.0;
+ };
+
bool isFrequent(nsecs_t now) const;
bool isAnimating(nsecs_t now) const;
bool hasEnoughDataForHeuristic() const;
- std::optional<float> calculateRefreshRateIfPossible();
- std::pair<nsecs_t, bool> calculateAverageFrameTime() const;
- bool isRefreshRateStable(nsecs_t averageFrameTime, bool missingPresentTime) const;
+ std::optional<float> calculateRefreshRateIfPossible(nsecs_t now);
+ std::optional<nsecs_t> calculateAverageFrameTime() const;
bool isFrameTimeValid(const FrameTimeData&) const;
const std::string mName;
@@ -123,23 +194,27 @@
const nsecs_t mHighRefreshRatePeriod;
LayerHistory::LayerVoteType mDefaultVote;
+ LayerVote mLayerVote;
+
nsecs_t mLastUpdatedTime = 0;
nsecs_t mLastAnimationTime = 0;
- float mLastReportedRefreshRate = 0.0f;
-
- // Holds information about the layer vote
- struct {
- LayerHistory::LayerVoteType type;
- float fps;
- } mLayerVote;
+ RefreshRateHeuristicData mLastRefreshRate;
std::deque<FrameTimeData> mFrameTimes;
std::chrono::time_point<std::chrono::steady_clock> mFrameTimeValidSince =
std::chrono::steady_clock::now();
- static constexpr size_t HISTORY_SIZE = 90;
- static constexpr std::chrono::nanoseconds HISTORY_TIME = 1s;
+ static constexpr size_t HISTORY_SIZE = RefreshRateHistory::HISTORY_SIZE;
+ static constexpr std::chrono::nanoseconds HISTORY_DURATION = 1s;
+
+ RefreshRateHistory mRefreshRateHistory;
+
+ mutable std::unordered_map<LayerHistory::LayerVoteType, std::string> mTraceTags;
+
+ // Shared for all LayerInfo instances
+ static const RefreshRateConfigs* sRefreshRateConfigs;
+ static bool sTraceEnabled;
};
} // namespace scheduler
diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
index 3c8bd68..6dbff14 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
+++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
@@ -115,12 +115,24 @@
}
const RefreshRate& RefreshRateConfigs::getBestRefreshRate(
- const std::vector<LayerRequirement>& layers, bool touchActive, bool idle,
- bool* touchConsidered) const {
+ const std::vector<LayerRequirement>& layers, const GlobalSignals& globalSignals,
+ GlobalSignals* outSignalsConsidered) const {
ATRACE_CALL();
ALOGV("getRefreshRateForContent %zu layers", layers.size());
- if (touchConsidered) *touchConsidered = false;
+ if (outSignalsConsidered) *outSignalsConsidered = {};
+ const auto setTouchConsidered = [&] {
+ if (outSignalsConsidered) {
+ outSignalsConsidered->touch = true;
+ }
+ };
+
+ const auto setIdleConsidered = [&] {
+ if (outSignalsConsidered) {
+ outSignalsConsidered->idle = true;
+ }
+ };
+
std::lock_guard lock(mLock);
int noVoteLayers = 0;
@@ -150,9 +162,9 @@
// Consider the touch event if there are no Explicit* layers. Otherwise wait until after we've
// selected a refresh rate to see if we should apply touch boost.
- if (touchActive && !hasExplicitVoteLayers) {
+ if (globalSignals.touch && !hasExplicitVoteLayers) {
ALOGV("TouchBoost - choose %s", getMaxRefreshRateByPolicyLocked().getName().c_str());
- if (touchConsidered) *touchConsidered = true;
+ setTouchConsidered();
return getMaxRefreshRateByPolicyLocked();
}
@@ -162,8 +174,10 @@
const Policy* policy = getCurrentPolicyLocked();
const bool primaryRangeIsSingleRate = policy->primaryRange.min == policy->primaryRange.max;
- if (!touchActive && idle && !(primaryRangeIsSingleRate && hasExplicitVoteLayers)) {
+ if (!globalSignals.touch && globalSignals.idle &&
+ !(primaryRangeIsSingleRate && hasExplicitVoteLayers)) {
ALOGV("Idle - choose %s", getMinRefreshRateByPolicyLocked().getName().c_str());
+ setIdleConsidered();
return getMinRefreshRateByPolicyLocked();
}
@@ -242,7 +256,7 @@
if (layer.vote == LayerVoteType::ExplicitExactOrMultiple ||
layer.vote == LayerVoteType::Heuristic) {
- const auto layerScore = [&]() {
+ const auto layerScore = [&] {
// Calculate how many display vsyncs we need to present a single frame for this
// layer
const auto [displayFramesQuot, displayFramesRem] =
@@ -307,9 +321,9 @@
// actually increase the refresh rate over the normal selection.
const RefreshRate& touchRefreshRate = getMaxRefreshRateByPolicyLocked();
- if (touchActive && explicitDefaultVoteLayers == 0 &&
+ if (globalSignals.touch && explicitDefaultVoteLayers == 0 &&
bestRefreshRate->fps < touchRefreshRate.fps) {
- if (touchConsidered) *touchConsidered = true;
+ setTouchConsidered();
ALOGV("TouchBoost - choose %s", touchRefreshRate.getName().c_str());
return touchRefreshRate;
}
@@ -384,7 +398,8 @@
RefreshRateConfigs::RefreshRateConfigs(
const std::vector<std::shared_ptr<const HWC2::Display::Config>>& configs,
- HwcConfigIndexType currentConfigId) {
+ HwcConfigIndexType currentConfigId)
+ : mKnownFrameRates(constructKnownFrameRates(configs)) {
LOG_ALWAYS_FATAL_IF(configs.empty());
LOG_ALWAYS_FATAL_IF(currentConfigId.value() >= configs.size());
@@ -544,4 +559,40 @@
&mAppRequestRefreshRates);
}
+std::vector<float> RefreshRateConfigs::constructKnownFrameRates(
+ const std::vector<std::shared_ptr<const HWC2::Display::Config>>& configs) {
+ std::vector<float> knownFrameRates = {24.0f, 30.0f, 45.0f, 60.0f, 72.0f};
+ knownFrameRates.reserve(knownFrameRates.size() + configs.size());
+
+ // Add all supported refresh rates to the set
+ for (const auto& config : configs) {
+ const auto refreshRate = 1e9f / config->getVsyncPeriod();
+ knownFrameRates.emplace_back(refreshRate);
+ }
+
+ // Sort and remove duplicates
+ const auto frameRatesEqual = [](float a, float b) { return std::abs(a - b) <= 0.01f; };
+ std::sort(knownFrameRates.begin(), knownFrameRates.end());
+ knownFrameRates.erase(std::unique(knownFrameRates.begin(), knownFrameRates.end(),
+ frameRatesEqual),
+ knownFrameRates.end());
+ return knownFrameRates;
+}
+
+float RefreshRateConfigs::findClosestKnownFrameRate(float frameRate) const {
+ if (frameRate <= *mKnownFrameRates.begin()) {
+ return *mKnownFrameRates.begin();
+ }
+
+ if (frameRate >= *std::prev(mKnownFrameRates.end())) {
+ return *std::prev(mKnownFrameRates.end());
+ }
+
+ auto lowerBound = std::lower_bound(mKnownFrameRates.begin(), mKnownFrameRates.end(), frameRate);
+
+ const auto distance1 = std::abs(frameRate - *lowerBound);
+ const auto distance2 = std::abs(frameRate - *std::prev(lowerBound));
+ return distance1 < distance2 ? *lowerBound : *std::prev(lowerBound);
+}
+
} // namespace android::scheduler
diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
index ff1eabd..584a5e7 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
+++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
@@ -29,7 +29,6 @@
#include "Scheduler/StrongTyping.h"
namespace android::scheduler {
-class RefreshRateConfigsTest;
using namespace std::chrono_literals;
@@ -87,7 +86,7 @@
private:
friend RefreshRateConfigs;
- friend RefreshRateConfigsTest;
+ friend class RefreshRateConfigsTest;
// The tolerance within which we consider FPS approximately equals.
static constexpr float FPS_EPSILON = 0.001f;
@@ -212,14 +211,22 @@
const RefreshRate& getRefreshRateForContent(const std::vector<LayerRequirement>& layers) const
EXCLUDES(mLock);
+ // Global state describing signals that affect refresh rate choice.
+ struct GlobalSignals {
+ // Whether the user touched the screen recently. Used to apply touch boost.
+ bool touch = false;
+ // True if the system hasn't seen any buffers posted to layers recently.
+ bool idle = false;
+ };
+
// Returns the refresh rate that fits best to the given layers.
// layers - The layer requirements to consider.
- // touchActive - Whether the user touched the screen recently. Used to apply touch boost.
- // idle - True if the system hasn't seen any buffers posted to layers recently.
- // touchConsidered - An output param that tells the caller whether the refresh rate was chosen
- // based on touch boost.
+ // globalSignals - global state of touch and idle
+ // outSignalsConsidered - An output param that tells the caller whether the refresh rate was
+ // chosen based on touch boost and/or idle timer.
const RefreshRate& getBestRefreshRate(const std::vector<LayerRequirement>& layers,
- bool touchActive, bool idle, bool* touchConsidered) const
+ const GlobalSignals& globalSignals,
+ GlobalSignals* outSignalsConsidered = nullptr) const
EXCLUDES(mLock);
// Returns all the refresh rates supported by the device. This won't change at runtime.
@@ -258,11 +265,18 @@
// Returns a string that represents the layer vote type
static std::string layerVoteTypeString(LayerVoteType vote);
+ // Returns a known frame rate that is the closest to frameRate
+ float findClosestKnownFrameRate(float frameRate) const;
+
RefreshRateConfigs(const std::vector<std::shared_ptr<const HWC2::Display::Config>>& configs,
HwcConfigIndexType currentConfigId);
private:
+ friend class RefreshRateConfigsTest;
+
void constructAvailableRefreshRates() REQUIRES(mLock);
+ static std::vector<float> constructKnownFrameRates(
+ const std::vector<std::shared_ptr<const HWC2::Display::Config>>& configs);
void getSortedRefreshRateList(
const std::function<bool(const RefreshRate&)>& shouldAddRefreshRate,
@@ -320,6 +334,10 @@
const RefreshRate* mMaxSupportedRefreshRate;
mutable std::mutex mLock;
+
+ // A sorted list of known frame rates that a Heuristic layer will choose
+ // from based on the closest value.
+ const std::vector<float> mKnownFrameRates;
};
} // namespace android::scheduler
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index e250bbf..5c0ba01 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -111,7 +111,7 @@
using namespace sysprop;
if (mUseContentDetectionV2) {
- mLayerHistory = std::make_unique<scheduler::impl::LayerHistoryV2>();
+ mLayerHistory = std::make_unique<scheduler::impl::LayerHistoryV2>(refreshRateConfig);
} else {
mLayerHistory = std::make_unique<scheduler::impl::LayerHistory>();
}
@@ -228,8 +228,36 @@
mConnections[handle].thread->onScreenReleased();
}
-void Scheduler::onConfigChanged(ConnectionHandle handle, PhysicalDisplayId displayId,
- HwcConfigIndexType configId, nsecs_t vsyncPeriod) {
+void Scheduler::onPrimaryDisplayConfigChanged(ConnectionHandle handle, PhysicalDisplayId displayId,
+ HwcConfigIndexType configId, nsecs_t vsyncPeriod) {
+ std::lock_guard<std::mutex> lock(mFeatureStateLock);
+ // Cache the last reported config for primary display.
+ mFeatures.cachedConfigChangedParams = {handle, displayId, configId, vsyncPeriod};
+ onNonPrimaryDisplayConfigChanged(handle, displayId, configId, vsyncPeriod);
+}
+
+void Scheduler::dispatchCachedReportedConfig() {
+ const auto configId = *mFeatures.configId;
+ const auto vsyncPeriod =
+ mRefreshRateConfigs.getRefreshRateFromConfigId(configId).getVsyncPeriod();
+
+ // If there is no change from cached config, there is no need to dispatch an event
+ if (configId == mFeatures.cachedConfigChangedParams->configId &&
+ vsyncPeriod == mFeatures.cachedConfigChangedParams->vsyncPeriod) {
+ return;
+ }
+
+ mFeatures.cachedConfigChangedParams->configId = configId;
+ mFeatures.cachedConfigChangedParams->vsyncPeriod = vsyncPeriod;
+ onNonPrimaryDisplayConfigChanged(mFeatures.cachedConfigChangedParams->handle,
+ mFeatures.cachedConfigChangedParams->displayId,
+ mFeatures.cachedConfigChangedParams->configId,
+ mFeatures.cachedConfigChangedParams->vsyncPeriod);
+}
+
+void Scheduler::onNonPrimaryDisplayConfigChanged(ConnectionHandle handle,
+ PhysicalDisplayId displayId,
+ HwcConfigIndexType configId, nsecs_t vsyncPeriod) {
RETURN_IF_INVALID_HANDLE(handle);
mConnections[handle].thread->onConfigChanged(displayId, configId, vsyncPeriod);
}
@@ -446,13 +474,21 @@
mFeatures.contentDetectionV1 =
!summary.empty() ? ContentDetectionState::On : ContentDetectionState::Off;
- newConfigId = calculateRefreshRateConfigIndexType();
+ scheduler::RefreshRateConfigs::GlobalSignals consideredSignals;
+ newConfigId = calculateRefreshRateConfigIndexType(&consideredSignals);
if (mFeatures.configId == newConfigId) {
+ // We don't need to change the config, but we might need to send an event
+ // about a config change, since it was suppressed due to a previous idleConsidered
+ if (!consideredSignals.idle) {
+ dispatchCachedReportedConfig();
+ }
return;
}
mFeatures.configId = newConfigId;
auto& newRefreshRate = mRefreshRateConfigs.getRefreshRateFromConfigId(newConfigId);
- mSchedulerCallback.changeRefreshRate(newRefreshRate, ConfigEvent::Changed);
+ mSchedulerCallback.changeRefreshRate(newRefreshRate,
+ consideredSignals.idle ? ConfigEvent::None
+ : ConfigEvent::Changed);
}
}
@@ -522,21 +558,20 @@
}
void Scheduler::idleTimerCallback(TimerState state) {
- handleTimerStateChanged(&mFeatures.idleTimer, state, false /* eventOnContentDetection */);
+ handleTimerStateChanged(&mFeatures.idleTimer, state);
ATRACE_INT("ExpiredIdleTimer", static_cast<int>(state));
}
void Scheduler::touchTimerCallback(TimerState state) {
const TouchState touch = state == TimerState::Reset ? TouchState::Active : TouchState::Inactive;
- if (handleTimerStateChanged(&mFeatures.touch, touch, true /* eventOnContentDetection */)) {
+ if (handleTimerStateChanged(&mFeatures.touch, touch)) {
mLayerHistory->clear();
}
ATRACE_INT("TouchState", static_cast<int>(touch));
}
void Scheduler::displayPowerTimerCallback(TimerState state) {
- handleTimerStateChanged(&mFeatures.displayPowerTimer, state,
- true /* eventOnContentDetection */);
+ handleTimerStateChanged(&mFeatures.displayPowerTimer, state);
ATRACE_INT("ExpiredDisplayPowerTimer", static_cast<int>(state));
}
@@ -553,33 +588,37 @@
}
template <class T>
-bool Scheduler::handleTimerStateChanged(T* currentState, T newState, bool eventOnContentDetection) {
- ConfigEvent event = ConfigEvent::None;
+bool Scheduler::handleTimerStateChanged(T* currentState, T newState) {
HwcConfigIndexType newConfigId;
- bool touchConsidered = false;
+ scheduler::RefreshRateConfigs::GlobalSignals consideredSignals;
{
std::lock_guard<std::mutex> lock(mFeatureStateLock);
if (*currentState == newState) {
- return touchConsidered;
+ return false;
}
*currentState = newState;
- newConfigId = calculateRefreshRateConfigIndexType(&touchConsidered);
+ newConfigId = calculateRefreshRateConfigIndexType(&consideredSignals);
if (mFeatures.configId == newConfigId) {
- return touchConsidered;
+ // We don't need to change the config, but we might need to send an event
+ // about a config change, since it was suppressed due to a previous idleConsidered
+ if (!consideredSignals.idle) {
+ dispatchCachedReportedConfig();
+ }
+ return consideredSignals.touch;
}
mFeatures.configId = newConfigId;
- if (eventOnContentDetection && !mFeatures.contentRequirements.empty()) {
- event = ConfigEvent::Changed;
- }
}
const RefreshRate& newRefreshRate = mRefreshRateConfigs.getRefreshRateFromConfigId(newConfigId);
- mSchedulerCallback.changeRefreshRate(newRefreshRate, event);
- return touchConsidered;
+ mSchedulerCallback.changeRefreshRate(newRefreshRate,
+ consideredSignals.idle ? ConfigEvent::None
+ : ConfigEvent::Changed);
+ return consideredSignals.touch;
}
-HwcConfigIndexType Scheduler::calculateRefreshRateConfigIndexType(bool* touchConsidered) {
+HwcConfigIndexType Scheduler::calculateRefreshRateConfigIndexType(
+ scheduler::RefreshRateConfigs::GlobalSignals* consideredSignals) {
ATRACE_CALL();
- if (touchConsidered) *touchConsidered = false;
+ if (consideredSignals) *consideredSignals = {};
// If Display Power is not in normal operation we want to be in performance mode. When coming
// back to normal mode, a grace period is given with DisplayPowerTimer.
@@ -600,6 +639,7 @@
// If timer has expired as it means there is no new content on the screen.
if (idle) {
+ if (consideredSignals) consideredSignals->idle = true;
return mRefreshRateConfigs.getMinRefreshRateByPolicy().getConfigId();
}
@@ -615,7 +655,8 @@
}
return mRefreshRateConfigs
- .getBestRefreshRate(mFeatures.contentRequirements, touchActive, idle, touchConsidered)
+ .getBestRefreshRate(mFeatures.contentRequirements, {.touch = touchActive, .idle = idle},
+ consideredSignals)
.getConfigId();
}
diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h
index ebee9e3..9e24f909 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.h
+++ b/services/surfaceflinger/Scheduler/Scheduler.h
@@ -81,9 +81,11 @@
sp<EventThreadConnection> getEventConnection(ConnectionHandle);
void onHotplugReceived(ConnectionHandle, PhysicalDisplayId, bool connected);
- void onConfigChanged(ConnectionHandle, PhysicalDisplayId, HwcConfigIndexType configId,
- nsecs_t vsyncPeriod);
-
+ void onPrimaryDisplayConfigChanged(ConnectionHandle, PhysicalDisplayId,
+ HwcConfigIndexType configId, nsecs_t vsyncPeriod)
+ EXCLUDES(mFeatureStateLock);
+ void onNonPrimaryDisplayConfigChanged(ConnectionHandle, PhysicalDisplayId,
+ HwcConfigIndexType configId, nsecs_t vsyncPeriod);
void onScreenAcquired(ConnectionHandle);
void onScreenReleased(ConnectionHandle);
@@ -179,16 +181,19 @@
// handles various timer features to change the refresh rate.
template <class T>
- bool handleTimerStateChanged(T* currentState, T newState, bool eventOnContentDetection);
+ bool handleTimerStateChanged(T* currentState, T newState);
void setVsyncPeriod(nsecs_t period);
// This function checks whether individual features that are affecting the refresh rate
// selection were initialized, prioritizes them, and calculates the HwcConfigIndexType
// for the suggested refresh rate.
- HwcConfigIndexType calculateRefreshRateConfigIndexType(bool* touchConsidered = nullptr)
+ HwcConfigIndexType calculateRefreshRateConfigIndexType(
+ scheduler::RefreshRateConfigs::GlobalSignals* consideredSignals = nullptr)
REQUIRES(mFeatureStateLock);
+ void dispatchCachedReportedConfig() REQUIRES(mFeatureStateLock);
+
// Stores EventThread associated with a given VSyncSource, and an initial EventThreadConnection.
struct Connection {
sp<EventThreadConnection> connection;
@@ -240,6 +245,16 @@
LayerHistory::Summary contentRequirements;
bool isDisplayPowerStateNormal = true;
+
+ // Used to cache the last parameters of onPrimaryDisplayConfigChanged
+ struct ConfigChangedParams {
+ ConnectionHandle handle;
+ PhysicalDisplayId displayId;
+ HwcConfigIndexType configId;
+ nsecs_t vsyncPeriod;
+ };
+
+ std::optional<ConfigChangedParams> cachedConfigChangedParams;
} mFeatures GUARDED_BY(mFeatureStateLock);
const scheduler::RefreshRateConfigs& mRefreshRateConfigs;
diff --git a/services/surfaceflinger/Scheduler/VSyncModulator.cpp b/services/surfaceflinger/Scheduler/VSyncModulator.cpp
index 40a992c..510dc2d 100644
--- a/services/surfaceflinger/Scheduler/VSyncModulator.cpp
+++ b/services/surfaceflinger/Scheduler/VSyncModulator.cpp
@@ -25,6 +25,7 @@
#include <cutils/properties.h>
#include <utils/Trace.h>
+#include <chrono>
#include <cinttypes>
#include <mutex>
@@ -52,6 +53,7 @@
void VSyncModulator::setTransactionStart(Scheduler::TransactionStart transactionStart) {
if (transactionStart == Scheduler::TransactionStart::EARLY) {
mRemainingEarlyFrameCount = MIN_EARLY_FRAME_COUNT_TRANSACTION;
+ mEarlyTxnStartTime = std::chrono::steady_clock::now();
}
// An early transaction stays an early transaction.
@@ -64,6 +66,7 @@
}
void VSyncModulator::onTransactionHandled() {
+ mTxnAppliedTime = std::chrono::steady_clock::now();
if (mTransactionStart == Scheduler::TransactionStart::NORMAL) return;
mTransactionStart = Scheduler::TransactionStart::NORMAL;
updateOffsets();
@@ -87,9 +90,16 @@
void VSyncModulator::onRefreshed(bool usedRenderEngine) {
bool updateOffsetsNeeded = false;
- if (mRemainingEarlyFrameCount > 0) {
- mRemainingEarlyFrameCount--;
- updateOffsetsNeeded = true;
+
+ // Apply a 1ms margin to account for potential data races
+ // This might make us stay in early offsets for one
+ // additional frame but it's better to be conservative here.
+ static const constexpr std::chrono::nanoseconds kMargin = 1ms;
+ if ((mEarlyTxnStartTime.load() + kMargin) < mTxnAppliedTime.load()) {
+ if (mRemainingEarlyFrameCount > 0) {
+ mRemainingEarlyFrameCount--;
+ updateOffsetsNeeded = true;
+ }
}
if (usedRenderEngine) {
mRemainingRenderEngineUsageCount = MIN_EARLY_GL_FRAME_COUNT_TRANSACTION;
diff --git a/services/surfaceflinger/Scheduler/VSyncModulator.h b/services/surfaceflinger/Scheduler/VSyncModulator.h
index 704a5d5..d777ef9 100644
--- a/services/surfaceflinger/Scheduler/VSyncModulator.h
+++ b/services/surfaceflinger/Scheduler/VSyncModulator.h
@@ -16,6 +16,7 @@
#pragma once
+#include <chrono>
#include <mutex>
#include "Scheduler.h"
@@ -110,6 +111,8 @@
std::atomic<bool> mRefreshRateChangePending = false;
std::atomic<int> mRemainingEarlyFrameCount = 0;
std::atomic<int> mRemainingRenderEngineUsageCount = 0;
+ std::atomic<std::chrono::steady_clock::time_point> mEarlyTxnStartTime = {};
+ std::atomic<std::chrono::steady_clock::time_point> mTxnAppliedTime = {};
bool mTraceDetailedInfo = false;
};
diff --git a/services/surfaceflinger/Scheduler/VSyncReactor.cpp b/services/surfaceflinger/Scheduler/VSyncReactor.cpp
index 16d102c..c743de0 100644
--- a/services/surfaceflinger/Scheduler/VSyncReactor.cpp
+++ b/services/surfaceflinger/Scheduler/VSyncReactor.cpp
@@ -278,7 +278,9 @@
return false;
}
- if (mSupportKernelIdleTimer) {
+ const bool periodIsChanging =
+ mPeriodTransitioningTo && (*mPeriodTransitioningTo != getPeriod());
+ if (mSupportKernelIdleTimer && !periodIsChanging) {
// Clear out the Composer-provided period and use the allowance logic below
HwcVsyncPeriod = {};
}
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 51cf77e..b73361b 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -258,7 +258,7 @@
const String16 sAccessSurfaceFlinger("android.permission.ACCESS_SURFACE_FLINGER");
const String16 sReadFramebuffer("android.permission.READ_FRAME_BUFFER");
const String16 sDump("android.permission.DUMP");
-const char* KERNEL_IDLE_TIMER_PROP = "vendor.display.enable_kernel_idle_timer";
+const char* KERNEL_IDLE_TIMER_PROP = "graphics.display.kernel_idle_timer.enabled";
// ---------------------------------------------------------------------------
int64_t SurfaceFlinger::dispSyncPresentTimeOffset;
@@ -1077,8 +1077,8 @@
const nsecs_t vsyncPeriod =
mRefreshRateConfigs->getRefreshRateFromConfigId(mUpcomingActiveConfig.configId)
.getVsyncPeriod();
- mScheduler->onConfigChanged(mAppConnectionHandle, display->getId()->value,
- mUpcomingActiveConfig.configId, vsyncPeriod);
+ mScheduler->onPrimaryDisplayConfigChanged(mAppConnectionHandle, display->getId()->value,
+ mUpcomingActiveConfig.configId, vsyncPeriod);
}
}
@@ -2995,8 +2995,8 @@
// anyway since there are no connected apps at this point.
const nsecs_t vsyncPeriod =
mRefreshRateConfigs->getRefreshRateFromConfigId(currentConfig).getVsyncPeriod();
- mScheduler->onConfigChanged(mAppConnectionHandle, primaryDisplayId.value, currentConfig,
- vsyncPeriod);
+ mScheduler->onPrimaryDisplayConfigChanged(mAppConnectionHandle, primaryDisplayId.value,
+ currentConfig, vsyncPeriod);
}
void SurfaceFlinger::commitTransaction()
@@ -5943,8 +5943,8 @@
const nsecs_t vsyncPeriod = getHwComposer()
.getConfigs(*displayId)[policy->defaultConfig.value()]
->getVsyncPeriod();
- mScheduler->onConfigChanged(mAppConnectionHandle, display->getId()->value,
- policy->defaultConfig, vsyncPeriod);
+ mScheduler->onNonPrimaryDisplayConfigChanged(mAppConnectionHandle, display->getId()->value,
+ policy->defaultConfig, vsyncPeriod);
return NO_ERROR;
}
@@ -5976,8 +5976,8 @@
const nsecs_t vsyncPeriod =
mRefreshRateConfigs->getRefreshRateFromConfigId(display->getActiveConfig())
.getVsyncPeriod();
- mScheduler->onConfigChanged(mAppConnectionHandle, display->getId()->value,
- display->getActiveConfig(), vsyncPeriod);
+ mScheduler->onPrimaryDisplayConfigChanged(mAppConnectionHandle, display->getId()->value,
+ display->getActiveConfig(), vsyncPeriod);
auto configId = mScheduler->getPreferredConfigId();
auto& preferredRefreshRate = configId
diff --git a/services/surfaceflinger/tests/unittests/LayerHistoryTestV2.cpp b/services/surfaceflinger/tests/unittests/LayerHistoryTestV2.cpp
index f376b4a..afd2b71 100644
--- a/services/surfaceflinger/tests/unittests/LayerHistoryTestV2.cpp
+++ b/services/surfaceflinger/tests/unittests/LayerHistoryTestV2.cpp
@@ -38,7 +38,9 @@
static constexpr auto PRESENT_TIME_HISTORY_SIZE = LayerInfoV2::HISTORY_SIZE;
static constexpr auto MAX_FREQUENT_LAYER_PERIOD_NS = LayerInfoV2::MAX_FREQUENT_LAYER_PERIOD_NS;
static constexpr auto FREQUENT_LAYER_WINDOW_SIZE = LayerInfoV2::FREQUENT_LAYER_WINDOW_SIZE;
- static constexpr auto PRESENT_TIME_HISTORY_TIME = LayerInfoV2::HISTORY_TIME;
+ static constexpr auto PRESENT_TIME_HISTORY_DURATION = LayerInfoV2::HISTORY_DURATION;
+ static constexpr auto REFRESH_RATE_AVERAGE_HISTORY_DURATION =
+ LayerInfoV2::RefreshRateHistory::HISTORY_DURATION;
static constexpr float LO_FPS = 30.f;
static constexpr auto LO_FPS_PERIOD = static_cast<nsecs_t>(1e9f / LO_FPS);
@@ -84,6 +86,23 @@
return sp<mock::MockLayer>(new mock::MockLayer(mFlinger.flinger(), std::move(name)));
}
+ void recordFramesAndExpect(const sp<mock::MockLayer>& layer, nsecs_t& time, float frameRate,
+ float desiredRefreshRate, int numFrames) {
+ const nsecs_t framePeriod = static_cast<nsecs_t>(1e9f / frameRate);
+ impl::LayerHistoryV2::Summary summary;
+ for (int i = 0; i < numFrames; i++) {
+ history().record(layer.get(), time, time, LayerHistory::LayerUpdateType::Buffer);
+ time += framePeriod;
+
+ summary = history().summarize(time);
+ }
+
+ ASSERT_EQ(1, summary.size());
+ ASSERT_EQ(LayerHistory::LayerVoteType::Heuristic, summary[0].vote);
+ ASSERT_FLOAT_EQ(desiredRefreshRate, summary[0].desiredRefreshRate)
+ << "Frame rate is " << frameRate;
+ }
+
Hwc2::mock::Display mDisplay;
RefreshRateConfigs mConfigs{{HWC2::Display::Config::Builder(mDisplay, 0)
.setVsyncPeriod(int32_t(LO_FPS_PERIOD))
@@ -346,14 +365,17 @@
EXPECT_EQ(0, activeLayerCount());
EXPECT_EQ(0, frequentLayerCount(time));
+ impl::LayerHistoryV2::Summary summary;
+
// layer1 is active but infrequent.
for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) {
history().record(layer1.get(), time, time, LayerHistory::LayerUpdateType::Buffer);
time += MAX_FREQUENT_LAYER_PERIOD_NS.count();
+ summary = history().summarize(time);
}
- ASSERT_EQ(1, history().summarize(time).size());
- EXPECT_EQ(LayerHistory::LayerVoteType::Min, history().summarize(time)[0].vote);
+ ASSERT_EQ(1, summary.size());
+ EXPECT_EQ(LayerHistory::LayerVoteType::Min, summary[0].vote);
EXPECT_EQ(1, activeLayerCount());
EXPECT_EQ(0, frequentLayerCount(time));
@@ -361,28 +383,30 @@
for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) {
history().record(layer2.get(), time, time, LayerHistory::LayerUpdateType::Buffer);
time += HI_FPS_PERIOD;
+ summary = history().summarize(time);
}
// layer1 is still active but infrequent.
history().record(layer1.get(), time, time, LayerHistory::LayerUpdateType::Buffer);
- ASSERT_EQ(2, history().summarize(time).size());
- EXPECT_EQ(LayerHistory::LayerVoteType::Min, history().summarize(time)[0].vote);
- ASSERT_EQ(LayerHistory::LayerVoteType::Heuristic, history().summarize(time)[1].vote);
+ ASSERT_EQ(2, summary.size());
+ EXPECT_EQ(LayerHistory::LayerVoteType::Min, summary[0].vote);
+ ASSERT_EQ(LayerHistory::LayerVoteType::Heuristic, summary[1].vote);
EXPECT_FLOAT_EQ(HI_FPS, history().summarize(time)[1].desiredRefreshRate);
EXPECT_EQ(2, activeLayerCount());
EXPECT_EQ(1, frequentLayerCount(time));
// layer1 is no longer active.
// layer2 is frequent and has low refresh rate.
- for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) {
+ for (int i = 0; i < 2 * PRESENT_TIME_HISTORY_SIZE; i++) {
history().record(layer2.get(), time, time, LayerHistory::LayerUpdateType::Buffer);
time += LO_FPS_PERIOD;
+ summary = history().summarize(time);
}
- ASSERT_EQ(1, history().summarize(time).size());
- EXPECT_EQ(LayerHistory::LayerVoteType::Heuristic, history().summarize(time)[0].vote);
- EXPECT_FLOAT_EQ(LO_FPS, history().summarize(time)[0].desiredRefreshRate);
+ ASSERT_EQ(1, summary.size());
+ EXPECT_EQ(LayerHistory::LayerVoteType::Heuristic, summary[0].vote);
+ EXPECT_FLOAT_EQ(LO_FPS, summary[0].desiredRefreshRate);
EXPECT_EQ(1, activeLayerCount());
EXPECT_EQ(1, frequentLayerCount(time));
@@ -396,33 +420,36 @@
history().record(layer3.get(), time, time, LayerHistory::LayerUpdateType::Buffer);
time += HI_FPS_PERIOD;
+ summary = history().summarize(time);
}
- ASSERT_EQ(2, history().summarize(time).size());
- EXPECT_EQ(LayerHistory::LayerVoteType::Heuristic, history().summarize(time)[0].vote);
- EXPECT_FLOAT_EQ(LO_FPS, history().summarize(time)[0].desiredRefreshRate);
- EXPECT_EQ(LayerHistory::LayerVoteType::Max, history().summarize(time)[1].vote);
+ ASSERT_EQ(2, summary.size());
+ EXPECT_EQ(LayerHistory::LayerVoteType::Heuristic, summary[0].vote);
+ EXPECT_FLOAT_EQ(LO_FPS, summary[0].desiredRefreshRate);
+ EXPECT_EQ(LayerHistory::LayerVoteType::Max, summary[1].vote);
EXPECT_EQ(2, activeLayerCount());
EXPECT_EQ(2, frequentLayerCount(time));
// layer3 becomes recently active.
history().record(layer3.get(), time, time, LayerHistory::LayerUpdateType::Buffer);
- ASSERT_EQ(2, history().summarize(time).size());
- EXPECT_EQ(LayerHistory::LayerVoteType::Heuristic, history().summarize(time)[0].vote);
- EXPECT_FLOAT_EQ(LO_FPS, history().summarize(time)[0].desiredRefreshRate);
- EXPECT_EQ(LayerHistory::LayerVoteType::Heuristic, history().summarize(time)[1].vote);
- EXPECT_FLOAT_EQ(HI_FPS, history().summarize(time)[1].desiredRefreshRate);
+ summary = history().summarize(time);
+ ASSERT_EQ(2, summary.size());
+ EXPECT_EQ(LayerHistory::LayerVoteType::Heuristic, summary[0].vote);
+ EXPECT_FLOAT_EQ(LO_FPS, summary[0].desiredRefreshRate);
+ EXPECT_EQ(LayerHistory::LayerVoteType::Heuristic, summary[1].vote);
+ EXPECT_FLOAT_EQ(HI_FPS, summary[1].desiredRefreshRate);
EXPECT_EQ(2, activeLayerCount());
EXPECT_EQ(2, frequentLayerCount(time));
// layer1 expires.
layer1.clear();
- ASSERT_EQ(2, history().summarize(time).size());
- EXPECT_EQ(LayerHistory::LayerVoteType::Heuristic, history().summarize(time)[0].vote);
- EXPECT_EQ(LayerHistory::LayerVoteType::Heuristic, history().summarize(time)[0].vote);
- EXPECT_FLOAT_EQ(LO_FPS, history().summarize(time)[0].desiredRefreshRate);
- EXPECT_EQ(LayerHistory::LayerVoteType::Heuristic, history().summarize(time)[1].vote);
- EXPECT_FLOAT_EQ(HI_FPS, history().summarize(time)[1].desiredRefreshRate);
+ summary = history().summarize(time);
+ ASSERT_EQ(2, summary.size());
+ EXPECT_EQ(LayerHistory::LayerVoteType::Heuristic, summary[0].vote);
+ EXPECT_EQ(LayerHistory::LayerVoteType::Heuristic, summary[0].vote);
+ EXPECT_FLOAT_EQ(LO_FPS, summary[0].desiredRefreshRate);
+ EXPECT_EQ(LayerHistory::LayerVoteType::Heuristic, summary[1].vote);
+ EXPECT_FLOAT_EQ(HI_FPS, summary[1].desiredRefreshRate);
EXPECT_EQ(2, layerCount());
EXPECT_EQ(2, activeLayerCount());
EXPECT_EQ(2, frequentLayerCount(time));
@@ -432,37 +459,41 @@
for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) {
history().record(layer2.get(), time, time, LayerHistory::LayerUpdateType::Buffer);
time += LO_FPS_PERIOD;
+ summary = history().summarize(time);
}
- ASSERT_EQ(1, history().summarize(time).size());
- EXPECT_EQ(LayerHistory::LayerVoteType::Heuristic, history().summarize(time)[0].vote);
- EXPECT_FLOAT_EQ(LO_FPS, history().summarize(time)[0].desiredRefreshRate);
+ ASSERT_EQ(1, summary.size());
+ EXPECT_EQ(LayerHistory::LayerVoteType::Heuristic, summary[0].vote);
+ EXPECT_FLOAT_EQ(LO_FPS, summary[0].desiredRefreshRate);
EXPECT_EQ(1, activeLayerCount());
EXPECT_EQ(1, frequentLayerCount(time));
// layer2 expires.
layer2.clear();
- EXPECT_TRUE(history().summarize(time).empty());
+ summary = history().summarize(time);
+ EXPECT_TRUE(summary.empty());
EXPECT_EQ(1, layerCount());
EXPECT_EQ(0, activeLayerCount());
EXPECT_EQ(0, frequentLayerCount(time));
// layer3 becomes active and has high refresh rate.
- for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) {
+ for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE + FREQUENT_LAYER_WINDOW_SIZE + 1; i++) {
history().record(layer3.get(), time, time, LayerHistory::LayerUpdateType::Buffer);
time += HI_FPS_PERIOD;
+ summary = history().summarize(time);
}
- ASSERT_EQ(1, history().summarize(time).size());
- EXPECT_EQ(LayerHistory::LayerVoteType::Heuristic, history().summarize(time)[0].vote);
- EXPECT_FLOAT_EQ(HI_FPS, history().summarize(time)[0].desiredRefreshRate);
+ ASSERT_EQ(1, summary.size());
+ EXPECT_EQ(LayerHistory::LayerVoteType::Heuristic, summary[0].vote);
+ EXPECT_FLOAT_EQ(HI_FPS, summary[0].desiredRefreshRate);
EXPECT_EQ(1, layerCount());
EXPECT_EQ(1, activeLayerCount());
EXPECT_EQ(1, frequentLayerCount(time));
// layer3 expires.
layer3.clear();
- EXPECT_TRUE(history().summarize(time).empty());
+ summary = history().summarize(time);
+ EXPECT_TRUE(summary.empty());
EXPECT_EQ(0, layerCount());
EXPECT_EQ(0, activeLayerCount());
EXPECT_EQ(0, frequentLayerCount(time));
@@ -600,6 +631,46 @@
EXPECT_EQ(1, animatingLayerCount(time));
}
+TEST_F(LayerHistoryTestV2, heuristicLayer60Hz) {
+ const auto layer = createLayer();
+ EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true));
+ EXPECT_CALL(*layer, getFrameRateForLayerTree()).WillRepeatedly(Return(Layer::FrameRate()));
+
+ nsecs_t time = systemTime();
+ for (float fps = 54.0f; fps < 65.0f; fps += 0.1f) {
+ recordFramesAndExpect(layer, time, fps, 60.0f, PRESENT_TIME_HISTORY_SIZE);
+ }
+}
+
+TEST_F(LayerHistoryTestV2, heuristicLayer60_30Hz) {
+ const auto layer = createLayer();
+ EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true));
+ EXPECT_CALL(*layer, getFrameRateForLayerTree()).WillRepeatedly(Return(Layer::FrameRate()));
+
+ nsecs_t time = systemTime();
+ recordFramesAndExpect(layer, time, 60.0f, 60.0f, PRESENT_TIME_HISTORY_SIZE);
+
+ recordFramesAndExpect(layer, time, 60.0f, 60.0f, PRESENT_TIME_HISTORY_SIZE);
+ recordFramesAndExpect(layer, time, 30.0f, 60.0f, PRESENT_TIME_HISTORY_SIZE);
+ recordFramesAndExpect(layer, time, 30.0f, 30.0f, PRESENT_TIME_HISTORY_SIZE);
+ recordFramesAndExpect(layer, time, 60.0f, 30.0f, PRESENT_TIME_HISTORY_SIZE);
+ recordFramesAndExpect(layer, time, 60.0f, 60.0f, PRESENT_TIME_HISTORY_SIZE);
+}
+
+TEST_F(LayerHistoryTestV2, heuristicLayerNotOscillating) {
+ const auto layer = createLayer();
+ EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true));
+ EXPECT_CALL(*layer, getFrameRateForLayerTree()).WillRepeatedly(Return(Layer::FrameRate()));
+
+ nsecs_t time = systemTime();
+
+ recordFramesAndExpect(layer, time, 27.10f, 30.0f, PRESENT_TIME_HISTORY_SIZE);
+ recordFramesAndExpect(layer, time, 26.90f, 30.0f, PRESENT_TIME_HISTORY_SIZE);
+ recordFramesAndExpect(layer, time, 26.00f, 24.0f, PRESENT_TIME_HISTORY_SIZE);
+ recordFramesAndExpect(layer, time, 26.90f, 24.0f, PRESENT_TIME_HISTORY_SIZE);
+ recordFramesAndExpect(layer, time, 27.10f, 30.0f, PRESENT_TIME_HISTORY_SIZE);
+}
+
class LayerHistoryTestV2Parameterized
: public LayerHistoryTestV2,
public testing::WithParamInterface<std::chrono::nanoseconds> {};
@@ -642,7 +713,7 @@
infrequentLayerUpdates++;
}
- if (time - startTime > PRESENT_TIME_HISTORY_TIME.count()) {
+ if (time - startTime > PRESENT_TIME_HISTORY_DURATION.count()) {
ASSERT_NE(0, history().summarize(time).size());
ASSERT_GE(2, history().summarize(time).size());
diff --git a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp
index c919e93..f24575e 100644
--- a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp
+++ b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp
@@ -43,6 +43,14 @@
RefreshRateConfigsTest();
~RefreshRateConfigsTest();
+ float findClosestKnownFrameRate(const RefreshRateConfigs& refreshRateConfigs, float frameRate) {
+ return refreshRateConfigs.findClosestKnownFrameRate(frameRate);
+ }
+
+ std::vector<float> getKnownFrameRate(const RefreshRateConfigs& refreshRateConfigs) {
+ return refreshRateConfigs.mKnownFrameRates;
+ }
+
// Test config IDs
static inline const HwcConfigIndexType HWC_CONFIG_ID_60 = HwcConfigIndexType(0);
static inline const HwcConfigIndexType HWC_CONFIG_ID_90 = HwcConfigIndexType(1);
@@ -335,7 +343,6 @@
}
TEST_F(RefreshRateConfigsTest, getBestRefreshRate_noLayers) {
- bool ignored;
auto refreshRateConfigs =
std::make_unique<RefreshRateConfigs>(m60_72_90Device, /*currentConfigId=*/
HWC_CONFIG_ID_72);
@@ -344,17 +351,14 @@
// range.
auto layers = std::vector<LayerRequirement>{};
EXPECT_EQ(mExpected90Config,
- refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/
- false, /*idle*/ false, &ignored));
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_60, {60, 60}}), 0);
EXPECT_EQ(mExpected60Config,
- refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/
- false, /*idle*/ false, &ignored));
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
}
TEST_F(RefreshRateConfigsTest, getBestRefreshRate_60_90) {
- bool ignored;
auto refreshRateConfigs =
std::make_unique<RefreshRateConfigs>(m60_90Device,
/*currentConfigId=*/HWC_CONFIG_ID_60);
@@ -365,163 +369,134 @@
lr.vote = LayerVoteType::Min;
lr.name = "Min";
EXPECT_EQ(mExpected60Config,
- refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
- /*idle*/ false, &ignored));
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
lr.vote = LayerVoteType::Max;
lr.name = "Max";
EXPECT_EQ(mExpected90Config,
- refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
- /*idle*/ false, &ignored));
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
lr.desiredRefreshRate = 90.0f;
lr.vote = LayerVoteType::Heuristic;
lr.name = "90Hz Heuristic";
EXPECT_EQ(mExpected90Config,
- refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
- /*idle*/ false, &ignored));
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
lr.desiredRefreshRate = 60.0f;
lr.name = "60Hz Heuristic";
EXPECT_EQ(mExpected60Config,
- refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
- /*idle*/ false, &ignored));
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
lr.desiredRefreshRate = 45.0f;
lr.name = "45Hz Heuristic";
EXPECT_EQ(mExpected90Config,
- refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
- /*idle*/ false, &ignored));
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
lr.desiredRefreshRate = 30.0f;
lr.name = "30Hz Heuristic";
EXPECT_EQ(mExpected60Config,
- refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
- /*idle*/ false, &ignored));
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
lr.desiredRefreshRate = 24.0f;
lr.name = "24Hz Heuristic";
EXPECT_EQ(mExpected60Config,
- refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
- /*idle*/ false, &ignored));
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
lr.name = "";
ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_60, {60, 60}}), 0);
lr.vote = LayerVoteType::Min;
EXPECT_EQ(mExpected60Config,
- refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
- /*idle*/ false, &ignored));
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
lr.vote = LayerVoteType::Max;
EXPECT_EQ(mExpected60Config,
- refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
- /*idle*/ false, &ignored));
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
lr.desiredRefreshRate = 90.0f;
lr.vote = LayerVoteType::Heuristic;
EXPECT_EQ(mExpected60Config,
- refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
- /*idle*/ false, &ignored));
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
lr.desiredRefreshRate = 60.0f;
EXPECT_EQ(mExpected60Config,
- refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
- /*idle*/ false, &ignored));
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
lr.desiredRefreshRate = 45.0f;
EXPECT_EQ(mExpected60Config,
- refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
- /*idle*/ false, &ignored));
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
lr.desiredRefreshRate = 30.0f;
EXPECT_EQ(mExpected60Config,
- refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
- /*idle*/ false, &ignored));
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
lr.desiredRefreshRate = 24.0f;
EXPECT_EQ(mExpected60Config,
- refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
- /*idle*/ false, &ignored));
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_90, {90, 90}}), 0);
lr.vote = LayerVoteType::Min;
EXPECT_EQ(mExpected90Config,
- refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
- /*idle*/ false, &ignored));
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
lr.vote = LayerVoteType::Max;
EXPECT_EQ(mExpected90Config,
- refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
- /*idle*/ false, &ignored));
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
lr.desiredRefreshRate = 90.0f;
lr.vote = LayerVoteType::Heuristic;
EXPECT_EQ(mExpected90Config,
- refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
- /*idle*/ false, &ignored));
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
lr.desiredRefreshRate = 60.0f;
EXPECT_EQ(mExpected90Config,
- refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
- /*idle*/ false, &ignored));
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
lr.desiredRefreshRate = 45.0f;
EXPECT_EQ(mExpected90Config,
- refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
- /*idle*/ false, &ignored));
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
lr.desiredRefreshRate = 30.0f;
EXPECT_EQ(mExpected90Config,
- refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
- /*idle*/ false, &ignored));
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
lr.desiredRefreshRate = 24.0f;
EXPECT_EQ(mExpected90Config,
- refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
- /*idle*/ false, &ignored));
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_60, {0, 120}}), 0);
lr.vote = LayerVoteType::Min;
EXPECT_EQ(mExpected60Config,
- refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
- /*idle*/ false, &ignored));
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
lr.vote = LayerVoteType::Max;
EXPECT_EQ(mExpected90Config,
- refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
- /*idle*/ false, &ignored));
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
lr.desiredRefreshRate = 90.0f;
lr.vote = LayerVoteType::Heuristic;
EXPECT_EQ(mExpected90Config,
- refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
- /*idle*/ false, &ignored));
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
lr.desiredRefreshRate = 60.0f;
EXPECT_EQ(mExpected60Config,
- refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
- /*idle*/ false, &ignored));
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
lr.desiredRefreshRate = 45.0f;
EXPECT_EQ(mExpected90Config,
- refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
- /*idle*/ false, &ignored));
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
lr.desiredRefreshRate = 30.0f;
EXPECT_EQ(mExpected60Config,
- refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
- /*idle*/ false, &ignored));
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
lr.desiredRefreshRate = 24.0f;
EXPECT_EQ(mExpected60Config,
- refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
- /*idle*/ false, &ignored));
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
}
TEST_F(RefreshRateConfigsTest, getBestRefreshRate_60_72_90) {
- bool ignored;
auto refreshRateConfigs =
std::make_unique<RefreshRateConfigs>(m60_72_90Device,
/*currentConfigId=*/HWC_CONFIG_ID_60);
@@ -531,43 +506,35 @@
lr.vote = LayerVoteType::Min;
EXPECT_EQ(mExpected60Config,
- refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
- /*idle*/ false, &ignored));
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
lr.vote = LayerVoteType::Max;
EXPECT_EQ(mExpected90Config,
- refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
- /*idle*/ false, &ignored));
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
lr.desiredRefreshRate = 90.0f;
lr.vote = LayerVoteType::Heuristic;
EXPECT_EQ(mExpected90Config,
- refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
- /*idle*/ false, &ignored));
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
lr.desiredRefreshRate = 60.0f;
EXPECT_EQ(mExpected60Config,
- refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
- /*idle*/ false, &ignored));
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
lr.desiredRefreshRate = 45.0f;
EXPECT_EQ(mExpected90Config,
- refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
- /*idle*/ false, &ignored));
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
lr.desiredRefreshRate = 30.0f;
EXPECT_EQ(mExpected60Config,
- refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
- /*idle*/ false, &ignored));
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
lr.desiredRefreshRate = 24.0f;
EXPECT_EQ(mExpected72Config,
- refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
- /*idle*/ false, &ignored));
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
}
TEST_F(RefreshRateConfigsTest, getBestRefreshRate_30_60_72_90_120) {
- bool ignored;
auto refreshRateConfigs =
std::make_unique<RefreshRateConfigs>(m30_60_72_90_120Device,
/*currentConfigId=*/HWC_CONFIG_ID_60);
@@ -582,28 +549,24 @@
lr2.desiredRefreshRate = 60.0f;
lr2.vote = LayerVoteType::Heuristic;
EXPECT_EQ(mExpected120Config,
- refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
- /*idle*/ false, &ignored));
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
lr1.desiredRefreshRate = 24.0f;
lr1.vote = LayerVoteType::Heuristic;
lr2.desiredRefreshRate = 48.0f;
lr2.vote = LayerVoteType::Heuristic;
EXPECT_EQ(mExpected72Config,
- refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
- /*idle*/ false, &ignored));
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
lr1.desiredRefreshRate = 24.0f;
lr1.vote = LayerVoteType::Heuristic;
lr2.desiredRefreshRate = 48.0f;
lr2.vote = LayerVoteType::Heuristic;
EXPECT_EQ(mExpected72Config,
- refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
- /*idle*/ false, &ignored));
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
}
TEST_F(RefreshRateConfigsTest, getBestRefreshRate_30_60_90_120_DifferentTypes) {
- bool ignored;
auto refreshRateConfigs =
std::make_unique<RefreshRateConfigs>(m30_60_72_90_120Device,
/*currentConfigId=*/HWC_CONFIG_ID_60);
@@ -620,8 +583,7 @@
lr2.vote = LayerVoteType::Heuristic;
lr2.name = "60Hz Heuristic";
EXPECT_EQ(mExpected120Config,
- refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
- /*idle*/ false, &ignored));
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
lr1.desiredRefreshRate = 24.0f;
lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
@@ -630,8 +592,7 @@
lr2.vote = LayerVoteType::Heuristic;
lr2.name = "60Hz Heuristic";
EXPECT_EQ(mExpected120Config,
- refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
- /*idle*/ false, &ignored));
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
lr1.desiredRefreshRate = 24.0f;
lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
@@ -640,8 +601,7 @@
lr2.vote = LayerVoteType::ExplicitDefault;
lr2.name = "60Hz ExplicitDefault";
EXPECT_EQ(mExpected120Config,
- refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
- /*idle*/ false, &ignored));
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
lr1.desiredRefreshRate = 24.0f;
lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
@@ -650,8 +610,7 @@
lr2.vote = LayerVoteType::Heuristic;
lr2.name = "90Hz Heuristic";
EXPECT_EQ(mExpected90Config,
- refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
- /*idle*/ false, &ignored));
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
lr1.desiredRefreshRate = 24.0f;
lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
@@ -660,8 +619,7 @@
lr2.vote = LayerVoteType::ExplicitDefault;
lr2.name = "90Hz Heuristic";
EXPECT_EQ(mExpected72Config,
- refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
- /*idle*/ false, &ignored));
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
lr1.desiredRefreshRate = 24.0f;
lr1.vote = LayerVoteType::ExplicitDefault;
@@ -670,8 +628,7 @@
lr2.vote = LayerVoteType::Heuristic;
lr2.name = "90Hz Heuristic";
EXPECT_EQ(mExpected90Config,
- refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
- /*idle*/ false, &ignored));
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
lr1.desiredRefreshRate = 24.0f;
lr1.vote = LayerVoteType::Heuristic;
@@ -680,8 +637,7 @@
lr2.vote = LayerVoteType::ExplicitDefault;
lr2.name = "90Hz ExplicitDefault";
EXPECT_EQ(mExpected72Config,
- refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
- /*idle*/ false, &ignored));
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
lr1.desiredRefreshRate = 24.0f;
lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
@@ -690,8 +646,7 @@
lr2.vote = LayerVoteType::ExplicitDefault;
lr2.name = "90Hz ExplicitDefault";
EXPECT_EQ(mExpected72Config,
- refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
- /*idle*/ false, &ignored));
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
lr1.desiredRefreshRate = 24.0f;
lr1.vote = LayerVoteType::ExplicitDefault;
@@ -700,12 +655,10 @@
lr2.vote = LayerVoteType::ExplicitExactOrMultiple;
lr2.name = "90Hz ExplicitExactOrMultiple";
EXPECT_EQ(mExpected90Config,
- refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
- /*idle*/ false, &ignored));
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
}
TEST_F(RefreshRateConfigsTest, getBestRefreshRate_30_60) {
- bool ignored;
auto refreshRateConfigs =
std::make_unique<RefreshRateConfigs>(m30_60Device,
/*currentConfigId=*/HWC_CONFIG_ID_60);
@@ -715,43 +668,35 @@
lr.vote = LayerVoteType::Min;
EXPECT_EQ(mExpected30Config,
- refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
- /*idle*/ false, &ignored));
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
lr.vote = LayerVoteType::Max;
EXPECT_EQ(mExpected60Config,
- refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
- /*idle*/ false, &ignored));
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
lr.desiredRefreshRate = 90.0f;
lr.vote = LayerVoteType::Heuristic;
EXPECT_EQ(mExpected60Config,
- refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
- /*idle*/ false, &ignored));
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
lr.desiredRefreshRate = 60.0f;
EXPECT_EQ(mExpected60Config,
- refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
- /*idle*/ false, &ignored));
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
lr.desiredRefreshRate = 45.0f;
EXPECT_EQ(mExpected60Config,
- refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
- /*idle*/ false, &ignored));
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
lr.desiredRefreshRate = 30.0f;
EXPECT_EQ(mExpected30Config,
- refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
- /*idle*/ false, &ignored));
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
lr.desiredRefreshRate = 24.0f;
EXPECT_EQ(mExpected60Config,
- refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
- /*idle*/ false, &ignored));
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
}
TEST_F(RefreshRateConfigsTest, getBestRefreshRate_30_60_72_90) {
- bool ignored;
auto refreshRateConfigs =
std::make_unique<RefreshRateConfigs>(m30_60_72_90Device,
/*currentConfigId=*/HWC_CONFIG_ID_60);
@@ -762,71 +707,57 @@
lr.vote = LayerVoteType::Min;
lr.name = "Min";
EXPECT_EQ(mExpected30Config,
- refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
- /*idle*/ false, &ignored));
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
lr.vote = LayerVoteType::Max;
lr.name = "Max";
EXPECT_EQ(mExpected90Config,
- refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
- /*idle*/ false, &ignored));
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
lr.desiredRefreshRate = 90.0f;
lr.vote = LayerVoteType::Heuristic;
lr.name = "90Hz Heuristic";
EXPECT_EQ(mExpected90Config,
- refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
- /*idle*/ false, &ignored));
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
lr.desiredRefreshRate = 60.0f;
lr.name = "60Hz Heuristic";
EXPECT_EQ(mExpected60Config,
- refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
- /*idle*/ false, &ignored));
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
EXPECT_EQ(mExpected90Config,
- refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ true,
- /*idle*/ false, &ignored));
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = true, .idle = false}));
lr.desiredRefreshRate = 45.0f;
lr.name = "45Hz Heuristic";
EXPECT_EQ(mExpected90Config,
- refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
- /*idle*/ false, &ignored));
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
EXPECT_EQ(mExpected90Config,
- refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ true,
- /*idle*/ false, &ignored));
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = true, .idle = false}));
lr.desiredRefreshRate = 30.0f;
lr.name = "30Hz Heuristic";
EXPECT_EQ(mExpected30Config,
- refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
- /*idle*/ false, &ignored));
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
EXPECT_EQ(mExpected90Config,
- refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ true,
- /*idle*/ false, &ignored));
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = true, .idle = false}));
lr.desiredRefreshRate = 24.0f;
lr.name = "24Hz Heuristic";
EXPECT_EQ(mExpected72Config,
- refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
- /*idle*/ false, &ignored));
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
EXPECT_EQ(mExpected90Config,
- refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ true,
- /*idle*/ false, &ignored));
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = true, .idle = false}));
lr.desiredRefreshRate = 24.0f;
lr.vote = LayerVoteType::ExplicitExactOrMultiple;
lr.name = "24Hz ExplicitExactOrMultiple";
EXPECT_EQ(mExpected72Config,
- refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
- /*idle*/ false, &ignored));
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
EXPECT_EQ(mExpected90Config,
- refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ true,
- /*idle*/ false, &ignored));
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = true, .idle = false}));
}
TEST_F(RefreshRateConfigsTest, getBestRefreshRate_PriorityTest) {
- bool ignored;
auto refreshRateConfigs =
std::make_unique<RefreshRateConfigs>(m30_60_90Device,
/*currentConfigId=*/HWC_CONFIG_ID_60);
@@ -839,56 +770,48 @@
lr1.vote = LayerVoteType::Min;
lr2.vote = LayerVoteType::Max;
EXPECT_EQ(mExpected90Config,
- refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
- /*idle*/ false, &ignored));
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
lr1.vote = LayerVoteType::Min;
lr2.vote = LayerVoteType::Heuristic;
lr2.desiredRefreshRate = 24.0f;
EXPECT_EQ(mExpected60Config,
- refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
- /*idle*/ false, &ignored));
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
lr1.vote = LayerVoteType::Min;
lr2.vote = LayerVoteType::ExplicitExactOrMultiple;
lr2.desiredRefreshRate = 24.0f;
EXPECT_EQ(mExpected60Config,
- refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
- /*idle*/ false, &ignored));
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
lr1.vote = LayerVoteType::Max;
lr2.vote = LayerVoteType::Heuristic;
lr2.desiredRefreshRate = 60.0f;
EXPECT_EQ(mExpected90Config,
- refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
- /*idle*/ false, &ignored));
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
lr1.vote = LayerVoteType::Max;
lr2.vote = LayerVoteType::ExplicitExactOrMultiple;
lr2.desiredRefreshRate = 60.0f;
EXPECT_EQ(mExpected90Config,
- refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
- /*idle*/ false, &ignored));
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
lr1.vote = LayerVoteType::Heuristic;
lr1.desiredRefreshRate = 15.0f;
lr2.vote = LayerVoteType::Heuristic;
lr2.desiredRefreshRate = 45.0f;
EXPECT_EQ(mExpected90Config,
- refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
- /*idle*/ false, &ignored));
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
lr1.vote = LayerVoteType::Heuristic;
lr1.desiredRefreshRate = 30.0f;
lr2.vote = LayerVoteType::ExplicitExactOrMultiple;
lr2.desiredRefreshRate = 45.0f;
EXPECT_EQ(mExpected90Config,
- refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
- /*idle*/ false, &ignored));
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
}
TEST_F(RefreshRateConfigsTest, getBestRefreshRate_24FpsVideo) {
- bool ignored;
auto refreshRateConfigs =
std::make_unique<RefreshRateConfigs>(m60_90Device,
/*currentConfigId=*/HWC_CONFIG_ID_60);
@@ -900,10 +823,8 @@
for (float fps = 23.0f; fps < 25.0f; fps += 0.1f) {
lr.desiredRefreshRate = fps;
const auto& refreshRate =
- refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
- /*idle*/ false, &ignored);
- printf("%.2fHz chooses %s\n", fps, refreshRate.getName().c_str());
- EXPECT_EQ(mExpected60Config, refreshRate);
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false});
+ EXPECT_EQ(mExpected60Config, refreshRate) << fps << "Hz chooses " << refreshRate.getName();
}
}
@@ -931,7 +852,6 @@
}
TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_getBestRefreshRate_Explicit) {
- bool ignored;
auto refreshRateConfigs =
std::make_unique<RefreshRateConfigs>(m60_90Device,
/*currentConfigId=*/HWC_CONFIG_ID_60);
@@ -946,24 +866,21 @@
lr2.vote = LayerVoteType::ExplicitExactOrMultiple;
lr2.desiredRefreshRate = 90.0f;
EXPECT_EQ(mExpected90Config,
- refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
- /*idle*/ false, &ignored));
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
lr1.vote = LayerVoteType::ExplicitDefault;
lr1.desiredRefreshRate = 90.0f;
lr2.vote = LayerVoteType::ExplicitExactOrMultiple;
lr2.desiredRefreshRate = 60.0f;
EXPECT_EQ(mExpected60Config,
- refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
- /*idle*/ false, &ignored));
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
lr1.vote = LayerVoteType::Heuristic;
lr1.desiredRefreshRate = 90.0f;
lr2.vote = LayerVoteType::ExplicitExactOrMultiple;
lr2.desiredRefreshRate = 60.0f;
EXPECT_EQ(mExpected90Config,
- refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
- /*idle*/ false, &ignored));
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
}
TEST_F(RefreshRateConfigsTest, testInPolicy) {
@@ -975,7 +892,6 @@
}
TEST_F(RefreshRateConfigsTest, getBestRefreshRate_75HzContent) {
- bool ignored;
auto refreshRateConfigs =
std::make_unique<RefreshRateConfigs>(m60_90Device,
/*currentConfigId=*/HWC_CONFIG_ID_60);
@@ -987,15 +903,12 @@
for (float fps = 75.0f; fps < 100.0f; fps += 0.1f) {
lr.desiredRefreshRate = fps;
const auto& refreshRate =
- refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
- /*idle*/ false, &ignored);
- printf("%.2fHz chooses %s\n", fps, refreshRate.getName().c_str());
- EXPECT_EQ(mExpected90Config, refreshRate);
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false});
+ EXPECT_EQ(mExpected90Config, refreshRate) << fps << "Hz chooses " << refreshRate.getName();
}
}
TEST_F(RefreshRateConfigsTest, getBestRefreshRate_Multiples) {
- bool ignored;
auto refreshRateConfigs =
std::make_unique<RefreshRateConfigs>(m60_90Device,
/*currentConfigId=*/HWC_CONFIG_ID_60);
@@ -1012,8 +925,7 @@
lr2.desiredRefreshRate = 90.0f;
lr2.name = "90Hz Heuristic";
EXPECT_EQ(mExpected90Config,
- refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
- /*idle*/ false, &ignored));
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
lr1.desiredRefreshRate = 60.0f;
@@ -1022,8 +934,7 @@
lr2.desiredRefreshRate = 90.0f;
lr2.name = "90Hz ExplicitDefault";
EXPECT_EQ(mExpected60Config,
- refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
- /*idle*/ false, &ignored));
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
lr1.desiredRefreshRate = 60.0f;
@@ -1031,8 +942,7 @@
lr2.vote = LayerVoteType::Max;
lr2.name = "Max";
EXPECT_EQ(mExpected90Config,
- refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
- /*idle*/ false, &ignored));
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
lr1.desiredRefreshRate = 30.0f;
@@ -1041,8 +951,7 @@
lr2.desiredRefreshRate = 90.0f;
lr2.name = "90Hz Heuristic";
EXPECT_EQ(mExpected90Config,
- refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
- /*idle*/ false, &ignored));
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
lr1.desiredRefreshRate = 30.0f;
@@ -1050,12 +959,10 @@
lr2.vote = LayerVoteType::Max;
lr2.name = "Max";
EXPECT_EQ(mExpected90Config,
- refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
- /*idle*/ false, &ignored));
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
}
TEST_F(RefreshRateConfigsTest, scrollWhileWatching60fps_60_90) {
- bool ignored;
auto refreshRateConfigs =
std::make_unique<RefreshRateConfigs>(m60_90Device,
/*currentConfigId=*/HWC_CONFIG_ID_60);
@@ -1071,7 +978,7 @@
lr2.vote = LayerVoteType::NoVote;
lr2.name = "NoVote";
EXPECT_EQ(mExpected60Config,
- refreshRateConfigs->getBestRefreshRate(layers, false, /*idle*/ false, &ignored));
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
lr1.desiredRefreshRate = 60.0f;
@@ -1079,7 +986,7 @@
lr2.vote = LayerVoteType::NoVote;
lr2.name = "NoVote";
EXPECT_EQ(mExpected90Config,
- refreshRateConfigs->getBestRefreshRate(layers, true, /*idle*/ false, &ignored));
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = true, .idle = false}));
lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
lr1.desiredRefreshRate = 60.0f;
@@ -1087,7 +994,7 @@
lr2.vote = LayerVoteType::Max;
lr2.name = "Max";
EXPECT_EQ(mExpected90Config,
- refreshRateConfigs->getBestRefreshRate(layers, true, /*idle*/ false, &ignored));
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = true, .idle = false}));
lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
lr1.desiredRefreshRate = 60.0f;
@@ -1095,7 +1002,7 @@
lr2.vote = LayerVoteType::Max;
lr2.name = "Max";
EXPECT_EQ(mExpected90Config,
- refreshRateConfigs->getBestRefreshRate(layers, false, /*idle*/ false, &ignored));
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
// The other layer starts to provide buffers
lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
@@ -1105,20 +1012,20 @@
lr2.desiredRefreshRate = 90.0f;
lr2.name = "90Hz Heuristic";
EXPECT_EQ(mExpected90Config,
- refreshRateConfigs->getBestRefreshRate(layers, false, /*idle*/ false, &ignored));
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
}
TEST_F(RefreshRateConfigsTest, touchConsidered) {
- bool touchConsidered;
+ RefreshRateConfigs::GlobalSignals consideredSignals;
auto refreshRateConfigs =
std::make_unique<RefreshRateConfigs>(m60_90Device,
/*currentConfigId=*/HWC_CONFIG_ID_60);
- refreshRateConfigs->getBestRefreshRate({}, false, /*idle*/ false, &touchConsidered);
- EXPECT_EQ(false, touchConsidered);
+ refreshRateConfigs->getBestRefreshRate({}, {.touch = false, .idle = false}, &consideredSignals);
+ EXPECT_EQ(false, consideredSignals.touch);
- refreshRateConfigs->getBestRefreshRate({}, true, /*idle*/ false, &touchConsidered);
- EXPECT_EQ(true, touchConsidered);
+ refreshRateConfigs->getBestRefreshRate({}, {.touch = true, .idle = false}, &consideredSignals);
+ EXPECT_EQ(true, consideredSignals.touch);
auto layers = std::vector<LayerRequirement>{LayerRequirement{.weight = 1.0f},
LayerRequirement{.weight = 1.0f}};
@@ -1131,8 +1038,9 @@
lr2.vote = LayerVoteType::Heuristic;
lr2.desiredRefreshRate = 60.0f;
lr2.name = "60Hz Heuristic";
- refreshRateConfigs->getBestRefreshRate(layers, true, /*idle*/ false, &touchConsidered);
- EXPECT_EQ(true, touchConsidered);
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = true, .idle = false},
+ &consideredSignals);
+ EXPECT_EQ(true, consideredSignals.touch);
lr1.vote = LayerVoteType::ExplicitDefault;
lr1.desiredRefreshRate = 60.0f;
@@ -1140,8 +1048,9 @@
lr2.vote = LayerVoteType::Heuristic;
lr2.desiredRefreshRate = 60.0f;
lr2.name = "60Hz Heuristic";
- refreshRateConfigs->getBestRefreshRate(layers, true, /*idle*/ false, &touchConsidered);
- EXPECT_EQ(false, touchConsidered);
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = true, .idle = false},
+ &consideredSignals);
+ EXPECT_EQ(false, consideredSignals.touch);
lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
lr1.desiredRefreshRate = 60.0f;
@@ -1149,8 +1058,9 @@
lr2.vote = LayerVoteType::Heuristic;
lr2.desiredRefreshRate = 60.0f;
lr2.name = "60Hz Heuristic";
- refreshRateConfigs->getBestRefreshRate(layers, true, /*idle*/ false, &touchConsidered);
- EXPECT_EQ(true, touchConsidered);
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = true, .idle = false},
+ &consideredSignals);
+ EXPECT_EQ(true, consideredSignals.touch);
lr1.vote = LayerVoteType::ExplicitDefault;
lr1.desiredRefreshRate = 60.0f;
@@ -1158,12 +1068,12 @@
lr2.vote = LayerVoteType::Heuristic;
lr2.desiredRefreshRate = 60.0f;
lr2.name = "60Hz Heuristic";
- refreshRateConfigs->getBestRefreshRate(layers, true, /*idle*/ false, &touchConsidered);
- EXPECT_EQ(false, touchConsidered);
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = true, .idle = false},
+ &consideredSignals);
+ EXPECT_EQ(false, consideredSignals.touch);
}
TEST_F(RefreshRateConfigsTest, getBestRefreshRate_ExplicitDefault) {
- bool ignored;
auto refreshRateConfigs =
std::make_unique<RefreshRateConfigs>(m60_90_72_120Device, /*currentConfigId=*/
HWC_CONFIG_ID_60);
@@ -1199,7 +1109,7 @@
lr.name = ss.str();
const auto& refreshRate =
- refreshRateConfigs->getBestRefreshRate(layers, false, /*idle*/ false, &ignored);
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false});
EXPECT_FLOAT_EQ(refreshRate.getFps(), test.second)
<< "Expecting " << test.first << "fps => " << test.second << "Hz";
}
@@ -1218,22 +1128,22 @@
auto layers = std::vector<LayerRequirement>{LayerRequirement{.weight = 1.0f}};
auto& lr = layers[0];
- bool touchConsidered = false;
+ RefreshRateConfigs::GlobalSignals consideredSignals;
lr.vote = LayerVoteType::ExplicitExactOrMultiple;
lr.desiredRefreshRate = 60.0f;
lr.name = "60Hz ExplicitExactOrMultiple";
EXPECT_EQ(mExpected60Config,
- refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ true, /*idle*/ false,
- &touchConsidered));
- EXPECT_EQ(false, touchConsidered);
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = true, .idle = true},
+ &consideredSignals));
+ EXPECT_EQ(false, consideredSignals.touch);
lr.vote = LayerVoteType::ExplicitDefault;
lr.desiredRefreshRate = 60.0f;
lr.name = "60Hz ExplicitDefault";
EXPECT_EQ(mExpected60Config,
- refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ true, /*idle*/ false,
- &touchConsidered));
- EXPECT_EQ(false, touchConsidered);
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = true, .idle = true},
+ &consideredSignals));
+ EXPECT_EQ(false, consideredSignals.touch);
}
TEST_F(RefreshRateConfigsTest,
@@ -1249,20 +1159,17 @@
auto layers = std::vector<LayerRequirement>{LayerRequirement{.weight = 1.0f}};
auto& lr = layers[0];
- bool touchConsidered = false;
lr.vote = LayerVoteType::ExplicitExactOrMultiple;
lr.desiredRefreshRate = 90.0f;
lr.name = "90Hz ExplicitExactOrMultiple";
EXPECT_EQ(mExpected90Config,
- refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false, /*idle*/ true,
- &touchConsidered));
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = true}));
lr.vote = LayerVoteType::ExplicitDefault;
lr.desiredRefreshRate = 90.0f;
lr.name = "90Hz ExplicitDefault";
EXPECT_EQ(mExpected90Config,
- refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false, /*idle*/ true,
- &touchConsidered));
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = true}));
}
TEST_F(RefreshRateConfigsTest,
@@ -1275,11 +1182,11 @@
{HWC_CONFIG_ID_90, {90.f, 90.f}, {60.f, 90.f}}),
0);
- bool touchConsidered = false;
+ RefreshRateConfigs::GlobalSignals consideredSignals;
EXPECT_EQ(mExpected90Config,
- refreshRateConfigs->getBestRefreshRate({}, /*touchActive*/ false, /*idle*/ false,
- &touchConsidered));
- EXPECT_EQ(false, touchConsidered);
+ refreshRateConfigs->getBestRefreshRate({}, {.touch = false, .idle = false},
+ &consideredSignals));
+ EXPECT_EQ(false, consideredSignals.touch);
auto layers = std::vector<LayerRequirement>{LayerRequirement{.weight = 1.0f}};
auto& lr = layers[0];
@@ -1288,36 +1195,31 @@
lr.desiredRefreshRate = 60.0f;
lr.name = "60Hz ExplicitExactOrMultiple";
EXPECT_EQ(mExpected60Config,
- refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false, /*idle*/ false,
- &touchConsidered));
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
lr.vote = LayerVoteType::ExplicitDefault;
lr.desiredRefreshRate = 60.0f;
lr.name = "60Hz ExplicitDefault";
EXPECT_EQ(mExpected60Config,
- refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false, /*idle*/ false,
- &touchConsidered));
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
lr.vote = LayerVoteType::Heuristic;
lr.desiredRefreshRate = 60.0f;
lr.name = "60Hz Heuristic";
EXPECT_EQ(mExpected90Config,
- refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false, /*idle*/ false,
- &touchConsidered));
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
lr.vote = LayerVoteType::Max;
lr.desiredRefreshRate = 60.0f;
lr.name = "60Hz Max";
EXPECT_EQ(mExpected90Config,
- refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false, /*idle*/ false,
- &touchConsidered));
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
lr.vote = LayerVoteType::Min;
lr.desiredRefreshRate = 60.0f;
lr.name = "60Hz Min";
EXPECT_EQ(mExpected90Config,
- refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false, /*idle*/ false,
- &touchConsidered));
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
}
TEST_F(RefreshRateConfigsTest, groupSwitching) {
@@ -1331,10 +1233,8 @@
layer.desiredRefreshRate = 90.0f;
layer.name = "90Hz ExplicitDefault";
- bool touchConsidered;
ASSERT_EQ(HWC_CONFIG_ID_60,
- refreshRateConfigs
- ->getBestRefreshRate(layers, false, /*idle*/ false, &touchConsidered)
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})
.getConfigId());
RefreshRateConfigs::Policy policy;
@@ -1342,8 +1242,7 @@
policy.allowGroupSwitching = true;
ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy(policy), 0);
ASSERT_EQ(HWC_CONFIG_ID_90,
- refreshRateConfigs
- ->getBestRefreshRate(layers, false, /*idle*/ false, &touchConsidered)
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})
.getConfigId());
}
@@ -1361,20 +1260,15 @@
bool touchActive = false) -> HwcConfigIndexType {
layers[0].vote = voteType;
layers[0].desiredRefreshRate = fps;
- bool touchConsidered;
- return refreshRateConfigs
- ->getBestRefreshRate(layers, touchActive, /*idle*/ false, &touchConsidered)
+ return refreshRateConfigs->getBestRefreshRate(layers, {.touch = touchActive, .idle = false})
.getConfigId();
};
ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy(
{HWC_CONFIG_ID_60, {30.f, 60.f}, {30.f, 90.f}}),
0);
- bool touchConsidered;
EXPECT_EQ(HWC_CONFIG_ID_60,
- refreshRateConfigs
- ->getBestRefreshRate({}, /*touchActive=*/false, /*idle*/ false,
- &touchConsidered)
+ refreshRateConfigs->getBestRefreshRate({}, {.touch = false, .idle = false})
.getConfigId());
EXPECT_EQ(HWC_CONFIG_ID_60, getFrameRate(LayerVoteType::NoVote, 90.f));
EXPECT_EQ(HWC_CONFIG_ID_30, getFrameRate(LayerVoteType::Min, 90.f));
@@ -1410,13 +1304,19 @@
auto layers = std::vector<LayerRequirement>{LayerRequirement{.weight = 1.0f}};
layers[0].name = "Test layer";
- auto getIdleFrameRate = [&](LayerVoteType voteType, bool touchActive) -> HwcConfigIndexType {
+ const auto getIdleFrameRate = [&](LayerVoteType voteType,
+ bool touchActive) -> HwcConfigIndexType {
layers[0].vote = voteType;
layers[0].desiredRefreshRate = 90.f;
- bool touchConsidered;
- return refreshRateConfigs
- ->getBestRefreshRate(layers, touchActive, /*idle=*/true, &touchConsidered)
- .getConfigId();
+ RefreshRateConfigs::GlobalSignals consideredSignals;
+ const auto configId =
+ refreshRateConfigs
+ ->getBestRefreshRate(layers, {.touch = touchActive, .idle = true},
+ &consideredSignals)
+ .getConfigId();
+ // Refresh rate will be chosen by either touch state or idle state
+ EXPECT_EQ(!touchActive, consideredSignals.idle);
+ return configId;
};
ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy(
@@ -1424,38 +1324,102 @@
0);
// Idle should be lower priority than touch boost.
- EXPECT_EQ(HWC_CONFIG_ID_90, getIdleFrameRate(LayerVoteType::NoVote, true));
- EXPECT_EQ(HWC_CONFIG_ID_90, getIdleFrameRate(LayerVoteType::Min, true));
- EXPECT_EQ(HWC_CONFIG_ID_90, getIdleFrameRate(LayerVoteType::Max, true));
- EXPECT_EQ(HWC_CONFIG_ID_90, getIdleFrameRate(LayerVoteType::Heuristic, true));
- EXPECT_EQ(HWC_CONFIG_ID_90, getIdleFrameRate(LayerVoteType::ExplicitDefault, true));
- EXPECT_EQ(HWC_CONFIG_ID_90, getIdleFrameRate(LayerVoteType::ExplicitExactOrMultiple, true));
+ EXPECT_EQ(HWC_CONFIG_ID_90, getIdleFrameRate(LayerVoteType::NoVote, /*touchActive=*/true));
+ EXPECT_EQ(HWC_CONFIG_ID_90, getIdleFrameRate(LayerVoteType::Min, /*touchActive=*/true));
+ EXPECT_EQ(HWC_CONFIG_ID_90, getIdleFrameRate(LayerVoteType::Max, /*touchActive=*/true));
+ EXPECT_EQ(HWC_CONFIG_ID_90, getIdleFrameRate(LayerVoteType::Heuristic, /*touchActive=*/true));
+ EXPECT_EQ(HWC_CONFIG_ID_90,
+ getIdleFrameRate(LayerVoteType::ExplicitDefault, /*touchActive=*/true));
+ EXPECT_EQ(HWC_CONFIG_ID_90,
+ getIdleFrameRate(LayerVoteType::ExplicitExactOrMultiple, /*touchActive=*/true));
// With no layers, idle should still be lower priority than touch boost.
- bool touchConsidered;
EXPECT_EQ(HWC_CONFIG_ID_90,
- refreshRateConfigs
- ->getBestRefreshRate({}, /*touchActive=*/true, /*idle=*/true,
- &touchConsidered)
+ refreshRateConfigs->getBestRefreshRate({}, {.touch = true, .idle = true})
.getConfigId());
// Idle should be higher precedence than other layer frame rate considerations.
refreshRateConfigs->setCurrentConfigId(HWC_CONFIG_ID_90);
- EXPECT_EQ(HWC_CONFIG_ID_60, getIdleFrameRate(LayerVoteType::NoVote, false));
- EXPECT_EQ(HWC_CONFIG_ID_60, getIdleFrameRate(LayerVoteType::Min, false));
- EXPECT_EQ(HWC_CONFIG_ID_60, getIdleFrameRate(LayerVoteType::Max, false));
- EXPECT_EQ(HWC_CONFIG_ID_60, getIdleFrameRate(LayerVoteType::Heuristic, false));
- EXPECT_EQ(HWC_CONFIG_ID_60, getIdleFrameRate(LayerVoteType::ExplicitDefault, false));
- EXPECT_EQ(HWC_CONFIG_ID_60, getIdleFrameRate(LayerVoteType::ExplicitExactOrMultiple, false));
+ EXPECT_EQ(HWC_CONFIG_ID_60, getIdleFrameRate(LayerVoteType::NoVote, /*touchActive=*/false));
+ EXPECT_EQ(HWC_CONFIG_ID_60, getIdleFrameRate(LayerVoteType::Min, /*touchActive=*/false));
+ EXPECT_EQ(HWC_CONFIG_ID_60, getIdleFrameRate(LayerVoteType::Max, /*touchActive=*/false));
+ EXPECT_EQ(HWC_CONFIG_ID_60, getIdleFrameRate(LayerVoteType::Heuristic, /*touchActive=*/false));
+ EXPECT_EQ(HWC_CONFIG_ID_60,
+ getIdleFrameRate(LayerVoteType::ExplicitDefault, /*touchActive=*/false));
+ EXPECT_EQ(HWC_CONFIG_ID_60,
+ getIdleFrameRate(LayerVoteType::ExplicitExactOrMultiple, /*touchActive=*/false));
// Idle should be applied rather than the current config when there are no layers.
EXPECT_EQ(HWC_CONFIG_ID_60,
- refreshRateConfigs
- ->getBestRefreshRate({}, /*touchActive=*/false, /*idle=*/true,
- &touchConsidered)
+ refreshRateConfigs->getBestRefreshRate({}, {.touch = false, .idle = true})
.getConfigId());
}
+TEST_F(RefreshRateConfigsTest, findClosestKnownFrameRate) {
+ auto refreshRateConfigs =
+ std::make_unique<RefreshRateConfigs>(m60_90Device,
+ /*currentConfigId=*/HWC_CONFIG_ID_60);
+
+ for (float fps = 1.0f; fps <= 120.0f; fps += 0.1f) {
+ const auto knownFrameRate = findClosestKnownFrameRate(*refreshRateConfigs, fps);
+ float expectedFrameRate;
+ if (fps < 26.91f) {
+ expectedFrameRate = 24.0f;
+ } else if (fps < 37.51f) {
+ expectedFrameRate = 30.0f;
+ } else if (fps < 52.51f) {
+ expectedFrameRate = 45.0f;
+ } else if (fps < 66.01f) {
+ expectedFrameRate = 60.0f;
+ } else if (fps < 81.01f) {
+ expectedFrameRate = 72.0f;
+ } else {
+ expectedFrameRate = 90.0f;
+ }
+ EXPECT_FLOAT_EQ(expectedFrameRate, knownFrameRate)
+ << "findClosestKnownFrameRate(" << fps << ") = " << knownFrameRate;
+ }
+}
+
+TEST_F(RefreshRateConfigsTest, getBestRefreshRate_KnownFrameRate) {
+ auto refreshRateConfigs =
+ std::make_unique<RefreshRateConfigs>(m60_90Device,
+ /*currentConfigId=*/HWC_CONFIG_ID_60);
+
+ struct ExpectedRate {
+ float rate;
+ const RefreshRate& expected;
+ };
+
+ /* clang-format off */
+ std::vector<ExpectedRate> knownFrameRatesExpectations = {
+ {24.0f, mExpected60Config},
+ {30.0f, mExpected60Config},
+ {45.0f, mExpected90Config},
+ {60.0f, mExpected60Config},
+ {72.0f, mExpected90Config},
+ {90.0f, mExpected90Config},
+ };
+ /* clang-format on */
+
+ // Make sure the test tests all the known frame rate
+ const auto knownFrameRateList = getKnownFrameRate(*refreshRateConfigs);
+ const auto equal = std::equal(knownFrameRateList.begin(), knownFrameRateList.end(),
+ knownFrameRatesExpectations.begin(),
+ [](float a, const ExpectedRate& b) { return a == b.rate; });
+ EXPECT_TRUE(equal);
+
+ auto layers = std::vector<LayerRequirement>{LayerRequirement{.weight = 1.0f}};
+ auto& layer = layers[0];
+ layer.vote = LayerVoteType::Heuristic;
+ for (const auto& expectedRate : knownFrameRatesExpectations) {
+ layer.desiredRefreshRate = expectedRate.rate;
+ const auto& refreshRate =
+ refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false});
+ EXPECT_EQ(expectedRate.expected, refreshRate);
+ }
+}
+
} // namespace
} // namespace scheduler
} // namespace android
diff --git a/services/surfaceflinger/tests/unittests/TestableScheduler.h b/services/surfaceflinger/tests/unittests/TestableScheduler.h
index 41b5d49..d5ecae8 100644
--- a/services/surfaceflinger/tests/unittests/TestableScheduler.h
+++ b/services/surfaceflinger/tests/unittests/TestableScheduler.h
@@ -31,7 +31,7 @@
TestableScheduler(const scheduler::RefreshRateConfigs& configs, bool useContentDetectionV2)
: Scheduler([](bool) {}, configs, *this, useContentDetectionV2, true) {
if (mUseContentDetectionV2) {
- mLayerHistory = std::make_unique<scheduler::impl::LayerHistoryV2>();
+ mLayerHistory = std::make_unique<scheduler::impl::LayerHistoryV2>(configs);
} else {
mLayerHistory = std::make_unique<scheduler::impl::LayerHistory>();
}
@@ -43,7 +43,7 @@
: Scheduler(std::move(primaryDispSync), std::move(eventControlThread), configs, *this,
useContentDetectionV2, true) {
if (mUseContentDetectionV2) {
- mLayerHistory = std::make_unique<scheduler::impl::LayerHistoryV2>();
+ mLayerHistory = std::make_unique<scheduler::impl::LayerHistoryV2>(configs);
} else {
mLayerHistory = std::make_unique<scheduler::impl::LayerHistory>();
}
diff --git a/services/surfaceflinger/tests/unittests/VSyncReactorTest.cpp b/services/surfaceflinger/tests/unittests/VSyncReactorTest.cpp
index ccbd17f..a972562 100644
--- a/services/surfaceflinger/tests/unittests/VSyncReactorTest.cpp
+++ b/services/surfaceflinger/tests/unittests/VSyncReactorTest.cpp
@@ -672,15 +672,30 @@
kPendingLimit, true /* supportKernelIdleTimer */);
bool periodFlushed = true;
- EXPECT_CALL(*mMockTracker, addVsyncTimestamp(_)).Times(2);
+ EXPECT_CALL(*mMockTracker, addVsyncTimestamp(_)).Times(5);
idleReactor.setIgnorePresentFences(true);
- nsecs_t const newPeriod = 5000;
- idleReactor.setPeriod(newPeriod);
-
+ // First, set the same period, which should only be confirmed when we receive two
+ // matching callbacks
+ idleReactor.setPeriod(10000);
EXPECT_TRUE(idleReactor.addResyncSample(0, 0, &periodFlushed));
EXPECT_FALSE(periodFlushed);
- EXPECT_FALSE(idleReactor.addResyncSample(newPeriod, 0, &periodFlushed));
+ // Correct period but incorrect timestamp delta
+ EXPECT_TRUE(idleReactor.addResyncSample(0, 10000, &periodFlushed));
+ EXPECT_FALSE(periodFlushed);
+ // Correct period and correct timestamp delta
+ EXPECT_FALSE(idleReactor.addResyncSample(10000, 10000, &periodFlushed));
+ EXPECT_TRUE(periodFlushed);
+
+ // Then, set a new period, which should be confirmed as soon as we receive a callback
+ // reporting the new period
+ nsecs_t const newPeriod = 5000;
+ idleReactor.setPeriod(newPeriod);
+ // Incorrect timestamp delta and period
+ EXPECT_TRUE(idleReactor.addResyncSample(20000, 10000, &periodFlushed));
+ EXPECT_FALSE(periodFlushed);
+ // Incorrect timestamp delta but correct period
+ EXPECT_FALSE(idleReactor.addResyncSample(20000, 5000, &periodFlushed));
EXPECT_TRUE(periodFlushed);
EXPECT_TRUE(idleReactor.addPresentFence(generateSignalledFenceWithTime(0)));
diff --git a/vulkan/scripts/generator_common.py b/vulkan/scripts/generator_common.py
index cf370fa..ef0719d 100644
--- a/vulkan/scripts/generator_common.py
+++ b/vulkan/scripts/generator_common.py
@@ -22,7 +22,7 @@
import xml.etree.ElementTree as element_tree
# Extensions unsupported on Android.
-_BLACKLISTED_EXTENSIONS = [
+_BLOCKED_EXTENSIONS = [
'VK_EXT_acquire_xlib_display',
'VK_EXT_direct_mode_display',
'VK_EXT_display_control',
@@ -192,7 +192,7 @@
if cmd not in extension_dict:
return True
else:
- if extension_dict[cmd] not in _BLACKLISTED_EXTENSIONS:
+ if extension_dict[cmd] not in _BLOCKED_EXTENSIONS:
return True
return False