SF: remove wp<Layer> from LayerHistory
wp::promote has a significant performace impact. Instead we maintain
a copy of the relevant layer information in LayerInfo.
This shows reduction in simpleperf for the main thread
3.07% -> 0.81%
Test: simpleperf for PIP + Notification shade expansion
Test: atest SetFrameRateTest
Bug: 169873384
Change-Id: Ib1414a2db73a4c30a26379a0ba8ba9e639f920ce
diff --git a/services/surfaceflinger/Scheduler/LayerHistory.cpp b/services/surfaceflinger/Scheduler/LayerHistory.cpp
index ea92ad8..f4bc2a1 100644
--- a/services/surfaceflinger/Scheduler/LayerHistory.cpp
+++ b/services/surfaceflinger/Scheduler/LayerHistory.cpp
@@ -39,13 +39,13 @@
namespace {
-bool isLayerActive(const Layer& layer, const LayerInfo& info, nsecs_t threshold) {
+bool isLayerActive(const LayerInfo& info, nsecs_t threshold) {
// Layers with an explicit vote are always kept active
- if (layer.getFrameRateForLayerTree().rate.isValid()) {
+ if (info.getSetFrameRateVote().rate.isValid()) {
return true;
}
- return layer.isVisible() && info.getLastUpdatedTime() >= threshold;
+ return info.isVisible() && info.getLastUpdatedTime() >= threshold;
}
bool traceEnabled() {
@@ -58,11 +58,7 @@
return atoi(value);
}
-void trace(const wp<Layer>& weak, const LayerInfo& info, LayerHistory::LayerVoteType type,
- int fps) {
- const auto layer = weak.promote();
- if (!layer) return;
-
+void trace(const LayerInfo& info, LayerHistory::LayerVoteType type, int fps) {
const auto traceType = [&](LayerHistory::LayerVoteType checkedType, int value) {
ATRACE_INT(info.getTraceTag(checkedType), type == checkedType ? value : 0);
};
@@ -75,7 +71,7 @@
traceType(LayerHistory::LayerVoteType::Min, 1);
traceType(LayerHistory::LayerVoteType::Max, 1);
- ALOGD("%s: %s @ %d Hz", __FUNCTION__, layer->getName().c_str(), fps);
+ ALOGD("%s: %s @ %d Hz", __FUNCTION__, info.getName().c_str(), fps);
}
} // namespace
@@ -88,11 +84,27 @@
LayerHistory::~LayerHistory() = default;
void LayerHistory::registerLayer(Layer* layer, LayerVoteType type) {
- auto info = std::make_unique<LayerInfo>(layer->getName(), type);
+ auto info = std::make_unique<LayerInfo>(layer->getName(), layer->getOwnerUid(), type);
std::lock_guard lock(mLock);
mLayerInfos.emplace_back(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_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--;
+ }
+ 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);
@@ -102,7 +114,15 @@
LOG_FATAL_IF(it == mLayerInfos.end(), "%s: unknown layer %p", __FUNCTION__, layer);
const auto& info = it->second;
- info->setLastPresentTime(presentTime, now, updateType, mModeChangePending);
+ const auto layerProps = LayerInfo::LayerProps{
+ .visible = layer->isVisible(),
+ .bounds = layer->getBounds(),
+ .transform = layer->getTransform(),
+ .setFrameRateVote = layer->getFrameRateForLayerTree(),
+ .frameRateSelectionPriority = layer->getFrameRateSelectionPriority(),
+ };
+
+ info->setLastPresentTime(presentTime, now, updateType, mModeChangePending, layerProps);
// Activate layer if inactive.
if (const auto end = activeLayers().end(); it >= end) {
@@ -119,15 +139,10 @@
partitionLayers(now);
for (const auto& [layer, info] : activeLayers()) {
- const auto strong = layer.promote();
- if (!strong) {
- continue;
- }
-
- const auto frameRateSelectionPriority = strong->getFrameRateSelectionPriority();
+ const auto frameRateSelectionPriority = info->getFrameRateSelectionPriority();
const auto layerFocused = Layer::isLayerFocusedBasedOnPriority(frameRateSelectionPriority);
- ALOGV("%s has priority: %d %s focused", strong->getName().c_str(),
- frameRateSelectionPriority, layerFocused ? "" : "not");
+ ALOGV("%s has priority: %d %s focused", info->getName().c_str(), frameRateSelectionPriority,
+ layerFocused ? "" : "not");
const auto vote = info->getRefreshRateVote(now);
// Skip NoVote layer as those don't have any requirements
@@ -136,18 +151,18 @@
}
// Compute the layer's position on the screen
- const Rect bounds = Rect(strong->getBounds());
- const ui::Transform transform = strong->getTransform();
+ const Rect bounds = Rect(info->getBounds());
+ const ui::Transform transform = info->getTransform();
constexpr bool roundOutwards = true;
Rect transformed = transform.transform(bounds, roundOutwards);
const float layerArea = transformed.getWidth() * transformed.getHeight();
float weight = mDisplayArea ? layerArea / mDisplayArea : 0.0f;
- summary.push_back({strong->getName(), strong->getOwnerUid(), vote.type, vote.fps,
+ summary.push_back({info->getName(), info->getOwnerUid(), vote.type, vote.fps,
vote.seamlessness, weight, layerFocused});
if (CC_UNLIKELY(mTraceEnabled)) {
- trace(layer, *info, vote.type, vote.fps.getIntValue());
+ trace(*info, vote.type, vote.fps.getIntValue());
}
}
@@ -160,11 +175,11 @@
// Collect expired and inactive layers after active layers.
size_t i = 0;
while (i < mActiveLayersEnd) {
- auto& [weak, info] = mLayerInfos[i];
- if (const auto layer = weak.promote(); layer && isLayerActive(*layer, *info, threshold)) {
+ auto& [layerUnsafe, info] = mLayerInfos[i];
+ if (isLayerActive(*info, threshold)) {
i++;
// Set layer vote if set
- const auto frameRate = layer->getFrameRateForLayerTree();
+ const auto frameRate = info->getSetFrameRateVote();
const auto voteType = [&]() {
switch (frameRate.type) {
case Layer::FrameRateCompatibility::Default:
@@ -179,7 +194,7 @@
}();
if (frameRate.rate.isValid() || voteType == LayerVoteType::NoVote) {
- const auto type = layer->isVisible() ? voteType : LayerVoteType::NoVote;
+ const auto type = info->isVisible() ? voteType : LayerVoteType::NoVote;
info->setLayerVote({type, frameRate.rate, frameRate.seamlessness});
} else {
info->resetLayerVote();
@@ -188,24 +203,12 @@
}
if (CC_UNLIKELY(mTraceEnabled)) {
- trace(weak, *info, LayerHistory::LayerVoteType::NoVote, 0);
+ trace(*info, LayerHistory::LayerVoteType::NoVote, 0);
}
info->onLayerInactive(now);
std::swap(mLayerInfos[i], mLayerInfos[--mActiveLayersEnd]);
}
-
- // Collect expired layers after inactive layers.
- size_t end = mLayerInfos.size();
- while (i < end) {
- if (mLayerInfos[i].first.promote()) {
- i++;
- } else {
- std::swap(mLayerInfos[i], mLayerInfos[--end]);
- }
- }
-
- mLayerInfos.erase(mLayerInfos.begin() + static_cast<long>(end), mLayerInfos.end());
}
void LayerHistory::clear() {