Pass fps data to flattener
Use this extra data in determining if a layer should be considered inactive for flattening.
The effect is that sub 1 fps layers are cached immediately upon updating.
Test: Unit tests added, and confirmation of the intended effect on R6 during camera recording using
dumpsys surfaceflinger (expected all CameraLauncher layers to be device composited)
Bug: b/192271493
Change-Id: I06f2dd0b3256da5699ffca7347285dc8cf52713c
diff --git a/services/surfaceflinger/Scheduler/LayerHistory.cpp b/services/surfaceflinger/Scheduler/LayerHistory.cpp
index 84e3548..74a2ca7 100644
--- a/services/surfaceflinger/Scheduler/LayerHistory.cpp
+++ b/services/surfaceflinger/Scheduler/LayerHistory.cpp
@@ -84,42 +84,38 @@
void LayerHistory::registerLayer(Layer* layer, LayerVoteType type) {
std::lock_guard lock(mLock);
- for (const auto& info : mLayerInfos) {
- LOG_ALWAYS_FATAL_IF(info.first == layer, "%s already registered", layer->getName().c_str());
- }
+ LOG_ALWAYS_FATAL_IF(findLayer(layer->getSequence()).first !=
+ LayerHistory::layerStatus::NotFound,
+ "%s already registered", layer->getName().c_str());
auto info = std::make_unique<LayerInfo>(layer->getName(), layer->getOwnerUid(), type);
- mLayerInfos.emplace_back(layer, std::move(info));
+
+ // The layer can be placed on either map, it is assumed that partitionLayers() will be called
+ // to correct them.
+ mInactiveLayerInfos.insert({layer->getSequence(), std::make_pair(layer, std::move(info))});
}
void LayerHistory::deregisterLayer(Layer* layer) {
std::lock_guard lock(mLock);
-
- const auto it = std::find_if(mLayerInfos.begin(), mLayerInfos.end(),
- [layer](const auto& pair) { return pair.first == layer; });
- LOG_ALWAYS_FATAL_IF(it == mLayerInfos.end(), "%s: unknown layer %p", __FUNCTION__, layer);
-
- const size_t i = static_cast<size_t>(it - mLayerInfos.begin());
- if (i < mActiveLayersEnd) {
- mActiveLayersEnd--;
+ if (!mActiveLayerInfos.erase(layer->getSequence())) {
+ if (!mInactiveLayerInfos.erase(layer->getSequence())) {
+ LOG_ALWAYS_FATAL("%s: unknown layer %p", __FUNCTION__, layer);
+ }
}
- const size_t last = mLayerInfos.size() - 1;
- std::swap(mLayerInfos[i], mLayerInfos[last]);
- mLayerInfos.erase(mLayerInfos.begin() + static_cast<long>(last));
}
void LayerHistory::record(Layer* layer, nsecs_t presentTime, nsecs_t now,
LayerUpdateType updateType) {
std::lock_guard lock(mLock);
+ auto id = layer->getSequence();
- const auto it = std::find_if(mLayerInfos.begin(), mLayerInfos.end(),
- [layer](const auto& pair) { return pair.first == layer; });
- if (it == mLayerInfos.end()) {
+ auto [found, layerPair] = findLayer(id);
+ if (found == LayerHistory::layerStatus::NotFound) {
// Offscreen layer
ALOGV("LayerHistory::record: %s not registered", layer->getName().c_str());
return;
}
- const auto& info = it->second;
+ const auto& info = layerPair->second;
const auto layerProps = LayerInfo::LayerProps{
.visible = layer->isVisible(),
.bounds = layer->getBounds(),
@@ -131,9 +127,10 @@
info->setLastPresentTime(presentTime, now, updateType, mModeChangePending, layerProps);
// Activate layer if inactive.
- if (const auto end = activeLayers().end(); it >= end) {
- std::iter_swap(it, end);
- mActiveLayersEnd++;
+ if (found == LayerHistory::layerStatus::LayerInInactiveMap) {
+ mActiveLayerInfos.insert(
+ {id, std::make_pair(layerPair->first, std::move(layerPair->second))});
+ mInactiveLayerInfos.erase(id);
}
}
@@ -145,7 +142,8 @@
partitionLayers(now);
- for (const auto& [layer, info] : activeLayers()) {
+ for (const auto& [key, value] : mActiveLayerInfos) {
+ auto& info = value.second;
const auto frameRateSelectionPriority = info->getFrameRateSelectionPriority();
const auto layerFocused = Layer::isLayerFocusedBasedOnPriority(frameRateSelectionPriority);
ALOGV("%s has priority: %d %s focused", info->getName().c_str(), frameRateSelectionPriority,
@@ -179,12 +177,29 @@
void LayerHistory::partitionLayers(nsecs_t now) {
const nsecs_t threshold = getActiveLayerThreshold(now);
- // Collect expired and inactive layers after active layers.
- size_t i = 0;
- while (i < mActiveLayersEnd) {
- auto& [layerUnsafe, info] = mLayerInfos[i];
+ // iterate over inactive map
+ LayerInfos::iterator it = mInactiveLayerInfos.begin();
+ while (it != mInactiveLayerInfos.end()) {
+ auto& [layerUnsafe, info] = it->second;
if (isLayerActive(*info, threshold)) {
- i++;
+ // move this to the active map
+
+ mActiveLayerInfos.insert({it->first, std::move(it->second)});
+ it = mInactiveLayerInfos.erase(it);
+ } else {
+ if (CC_UNLIKELY(mTraceEnabled)) {
+ trace(*info, LayerHistory::LayerVoteType::NoVote, 0);
+ }
+ info->onLayerInactive(now);
+ it++;
+ }
+ }
+
+ // iterate over active map
+ it = mActiveLayerInfos.begin();
+ while (it != mActiveLayerInfos.end()) {
+ auto& [layerUnsafe, info] = it->second;
+ if (isLayerActive(*info, threshold)) {
// Set layer vote if set
const auto frameRate = info->getSetFrameRateVote();
const auto voteType = [&]() {
@@ -206,30 +221,68 @@
} else {
info->resetLayerVote();
}
- continue;
- }
- if (CC_UNLIKELY(mTraceEnabled)) {
- trace(*info, LayerHistory::LayerVoteType::NoVote, 0);
+ it++;
+ } else {
+ if (CC_UNLIKELY(mTraceEnabled)) {
+ trace(*info, LayerHistory::LayerVoteType::NoVote, 0);
+ }
+ info->onLayerInactive(now);
+ // move this to the inactive map
+ mInactiveLayerInfos.insert({it->first, std::move(it->second)});
+ it = mActiveLayerInfos.erase(it);
}
-
- info->onLayerInactive(now);
- std::swap(mLayerInfos[i], mLayerInfos[--mActiveLayersEnd]);
}
}
void LayerHistory::clear() {
std::lock_guard lock(mLock);
-
- for (const auto& [layer, info] : activeLayers()) {
- info->clearHistory(systemTime());
+ for (const auto& [key, value] : mActiveLayerInfos) {
+ value.second->clearHistory(systemTime());
}
}
std::string LayerHistory::dump() const {
std::lock_guard lock(mLock);
- return base::StringPrintf("LayerHistory{size=%zu, active=%zu}", mLayerInfos.size(),
- mActiveLayersEnd);
+ return base::StringPrintf("LayerHistory{size=%zu, active=%zu}",
+ mActiveLayerInfos.size() + mInactiveLayerInfos.size(),
+ mActiveLayerInfos.size());
+}
+
+float LayerHistory::getLayerFramerate(nsecs_t now, int32_t id) const {
+ std::lock_guard lock(mLock);
+ auto [found, layerPair] = findLayer(id);
+ if (found != LayerHistory::layerStatus::NotFound) {
+ return layerPair->second->getFps(now).getValue();
+ }
+ return 0.f;
+}
+
+std::pair<LayerHistory::layerStatus, LayerHistory::LayerPair*> LayerHistory::findLayer(int32_t id) {
+ // the layer could be in either the active or inactive map, try both
+ auto it = mActiveLayerInfos.find(id);
+ if (it != mActiveLayerInfos.end()) {
+ return std::make_pair(LayerHistory::layerStatus::LayerInActiveMap, &(it->second));
+ }
+ it = mInactiveLayerInfos.find(id);
+ if (it != mInactiveLayerInfos.end()) {
+ return std::make_pair(LayerHistory::layerStatus::LayerInInactiveMap, &(it->second));
+ }
+ return std::make_pair(LayerHistory::layerStatus::NotFound, nullptr);
+}
+
+std::pair<LayerHistory::layerStatus, const LayerHistory::LayerPair*> LayerHistory::findLayer(
+ int32_t id) const {
+ // the layer could be in either the active or inactive map, try both
+ auto it = mActiveLayerInfos.find(id);
+ if (it != mActiveLayerInfos.end()) {
+ return std::make_pair(LayerHistory::layerStatus::LayerInActiveMap, &(it->second));
+ }
+ it = mInactiveLayerInfos.find(id);
+ if (it != mInactiveLayerInfos.end()) {
+ return std::make_pair(LayerHistory::layerStatus::LayerInInactiveMap, &(it->second));
+ }
+ return std::make_pair(LayerHistory::layerStatus::NotFound, nullptr);
}
} // namespace android::scheduler