summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Vishnu Nair <vishnun@google.com> 2023-08-22 20:23:32 -0700
committer Vishnu Nair <vishnun@google.com> 2023-08-22 20:23:32 -0700
commit0109d3d3226882490106fee0b48cd46599675b5e (patch)
tree1155dd4420262cd44f916495befd6eb40c527964
parenta5b9bd87b3868a6d99aa84220a6a288efcad52d5 (diff)
[sf] recover when layer snapshot is null
Updates to frontend may require CE to recalculate visble regions. SF keeps track of this state using the mVisibleRegionsDirty flag. If this flag is not set, this usually indicates the next frame consists of buffer updates and the flag is used to skip uncessary work during composition. However, if we fail to set this flag, we may end in a scenario where CE uses stale data and ends up accessing a null snapshot. This is an unexpected scenario but instead of crashing, capture traces to disk and recover gracefully by forcing CE to rebuild layer stack. The traces can be used to reconstruct the scenario which lead to the inconsistent state. Test: presubmit Bug: 295069311 Change-Id: I4331aef37f775ef48aab380ac082ca878f4d1708
-rw-r--r--services/surfaceflinger/SurfaceFlinger.cpp23
1 files changed, 14 insertions, 9 deletions
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index a9a213337a..46374a405d 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -2621,19 +2621,24 @@ CompositeResultsPerDisplay SurfaceFlinger::composite(
constexpr bool kCursorOnly = false;
const auto layers = moveSnapshotsToCompositionArgs(refreshArgs, kCursorOnly);
- if (mLayerLifecycleManagerEnabled && !refreshArgs.updatingGeometryThisFrame) {
+ if (mLayerLifecycleManagerEnabled && !mVisibleRegionsDirty) {
for (const auto& [token, display] : FTL_FAKE_GUARD(mStateLock, mDisplays)) {
auto compositionDisplay = display->getCompositionDisplay();
if (!compositionDisplay->getState().isEnabled) continue;
for (auto outputLayer : compositionDisplay->getOutputLayersOrderedByZ()) {
- LLOG_ALWAYS_FATAL_WITH_TRACE_IF(outputLayer->getLayerFE().getCompositionState() ==
- nullptr,
- "Output layer %s for display %s %" PRIu64
- " has a null "
- "snapshot.",
- outputLayer->getLayerFE().getDebugName(),
- compositionDisplay->getName().c_str(),
- compositionDisplay->getId().value);
+ if (outputLayer->getLayerFE().getCompositionState() == nullptr) {
+ // This is unexpected but instead of crashing, capture traces to disk
+ // and recover gracefully by forcing CE to rebuild layer stack.
+ ALOGE("Output layer %s for display %s %" PRIu64 " has a null "
+ "snapshot. Forcing mVisibleRegionsDirty",
+ outputLayer->getLayerFE().getDebugName(),
+ compositionDisplay->getName().c_str(), compositionDisplay->getId().value);
+
+ TransactionTraceWriter::getInstance().invoke(__func__, /* overwrite= */ false);
+ mVisibleRegionsDirty = true;
+ refreshArgs.updatingOutputGeometryThisFrame = mVisibleRegionsDirty;
+ refreshArgs.updatingGeometryThisFrame = mVisibleRegionsDirty;
+ }
}
}
}