[sf] fix snapshot updates for mirror layers
Ensure we update the mirrored snapshots when they are
created.
Test: atest CtsSurfaceControlTests
Bug: 238781169
Change-Id: I245702f8b521745ba59f0f993bcaef90d0cdbe9a
diff --git a/services/surfaceflinger/FrontEnd/LayerHierarchy.cpp b/services/surfaceflinger/FrontEnd/LayerHierarchy.cpp
index afe557e..14d67c6 100644
--- a/services/surfaceflinger/FrontEnd/LayerHierarchy.cpp
+++ b/services/surfaceflinger/FrontEnd/LayerHierarchy.cpp
@@ -449,7 +449,7 @@
traversalPath.id = layerId;
traversalPath.variant = variant;
if (variant == LayerHierarchy::Variant::Mirror) {
- traversalPath.mirrorRootId = layerId;
+ traversalPath.mirrorRootId = mParentPath.id;
} else if (variant == LayerHierarchy::Variant::Relative) {
if (std::find(traversalPath.relativeRootIds.begin(), traversalPath.relativeRootIds.end(),
layerId) != traversalPath.relativeRootIds.end()) {
diff --git a/services/surfaceflinger/FrontEnd/LayerLifecycleManager.cpp b/services/surfaceflinger/FrontEnd/LayerLifecycleManager.cpp
index 79ffcbf..360a0a9 100644
--- a/services/surfaceflinger/FrontEnd/LayerLifecycleManager.cpp
+++ b/services/surfaceflinger/FrontEnd/LayerLifecycleManager.cpp
@@ -37,7 +37,6 @@
mGlobalChanges |= RequestedLayerState::Changes::Hierarchy;
for (auto& newLayer : newLayers) {
RequestedLayerState& layer = *newLayer.get();
- LLOGV(layer.id, "%s layer %s", __func__, layer.getDebugStringShort().c_str());
auto [it, inserted] = mIdToLayer.try_emplace(layer.id, References{.owner = layer});
if (!inserted) {
LOG_ALWAYS_FATAL("Duplicate layer id %d found. Existing layer: %s", layer.id,
@@ -68,6 +67,7 @@
if (layer.isRoot()) {
updateDisplayMirrorLayers(layer);
}
+ LLOGV(layer.id, "%s", layer.getDebugString().c_str());
mLayers.emplace_back(std::move(newLayer));
}
}
@@ -81,6 +81,7 @@
continue;
}
RequestedLayerState& layer = it->second.owner;
+ LLOGV(layer.id, "%s", layer.getDebugString().c_str());
layer.handleAlive = false;
if (!layer.canBeDestroyed()) {
continue;
@@ -148,7 +149,7 @@
while (it != mLayers.end()) {
RequestedLayerState* layer = it->get();
if (layer->changes.test(RequestedLayerState::Changes::Destroyed)) {
- LLOGV(layer->id, "destroyed layer %s", layer->getDebugStringShort().c_str());
+ LLOGV(layer->id, "destroyed %s", layer->getDebugStringShort().c_str());
std::iter_swap(it, mLayers.end() - 1);
mDestroyedLayers.emplace_back(std::move(mLayers.back()));
if (it == mLayers.end() - 1) {
diff --git a/services/surfaceflinger/FrontEnd/LayerLog.h b/services/surfaceflinger/FrontEnd/LayerLog.h
index 47e1e30..4943483 100644
--- a/services/surfaceflinger/FrontEnd/LayerLog.h
+++ b/services/surfaceflinger/FrontEnd/LayerLog.h
@@ -25,3 +25,5 @@
#else
#define LLOGV(LAYER_ID, x, ...) ALOGV("[%d] %s " x, (LAYER_ID), __func__, ##__VA_ARGS__);
#endif
+
+#define LLOGD(LAYER_ID, x, ...) ALOGD("[%d] %s " x, (LAYER_ID), __func__, ##__VA_ARGS__);
diff --git a/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp b/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp
index f866175..85b00d7 100644
--- a/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp
+++ b/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp
@@ -35,6 +35,10 @@
inputInfo.id = static_cast<int32_t>(state.id);
inputInfo.ownerUid = static_cast<int32_t>(state.ownerUid);
inputInfo.ownerPid = state.ownerPid;
+ changes = RequestedLayerState::Changes::Created;
+ mirrorRootPath = path.variant == LayerHierarchy::Variant::Mirror
+ ? path
+ : LayerHierarchy::TraversalPath::ROOT;
}
// As documented in libhardware header, formats in the range
@@ -165,7 +169,8 @@
std::string LayerSnapshot::getDebugString() const {
std::stringstream debug;
debug << "Snapshot{" << path.toString() << name << " isVisible=" << isVisible << " {"
- << getIsVisibleReason() << "} changes=" << changes.string() << "}";
+ << getIsVisibleReason() << "} changes=" << changes.string()
+ << " layerStack=" << outputFilter.layerStack.id << "}";
return debug.str();
}
diff --git a/services/surfaceflinger/FrontEnd/LayerSnapshot.h b/services/surfaceflinger/FrontEnd/LayerSnapshot.h
index 5d74203..9757640 100644
--- a/services/surfaceflinger/FrontEnd/LayerSnapshot.h
+++ b/services/surfaceflinger/FrontEnd/LayerSnapshot.h
@@ -84,6 +84,7 @@
scheduler::LayerInfo::FrameRate frameRate;
ui::Transform::RotationFlags fixedTransformHint;
bool handleSkipScreenshotFlag = false;
+ LayerHierarchy::TraversalPath mirrorRootPath;
ChildState childState;
static bool isOpaqueFormat(PixelFormat format);
diff --git a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp
index 4c722e5..9ccf6dc 100644
--- a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp
+++ b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp
@@ -328,6 +328,7 @@
LayerSnapshot LayerSnapshotBuilder::getRootSnapshot() {
LayerSnapshot snapshot;
+ snapshot.path = LayerHierarchy::TraversalPath::ROOT;
snapshot.changes = ftl::Flags<RequestedLayerState::Changes>();
snapshot.isHiddenByPolicyFromParent = false;
snapshot.isHiddenByPolicyFromRelativeParent = false;
@@ -368,10 +369,6 @@
}
if (args.layerLifecycleManager.getGlobalChanges().get() == 0) {
- // there are no changes, so just clear the change flags from before.
- for (auto& snapshot : mSnapshots) {
- clearChanges(*snapshot);
- }
return true;
}
@@ -396,14 +393,12 @@
// Walk through the snapshots, clearing previous change flags and updating the snapshots
// if needed.
for (auto& snapshot : mSnapshots) {
- clearChanges(*snapshot);
auto it = layersWithChanges.find(snapshot->path.id);
if (it != layersWithChanges.end()) {
ALOGV("%s fast path snapshot changes = %s", __func__,
mRootSnapshot.changes.string().c_str());
LayerHierarchy::TraversalPath root = LayerHierarchy::TraversalPath::ROOT;
- updateSnapshot(*snapshot, args, *it->second, mRootSnapshot, root,
- /*newSnapshot=*/false);
+ updateSnapshot(*snapshot, args, *it->second, mRootSnapshot, root);
}
}
return true;
@@ -468,6 +463,10 @@
}
void LayerSnapshotBuilder::update(const Args& args) {
+ for (auto& snapshot : mSnapshots) {
+ clearChanges(*snapshot);
+ }
+
if (tryFastUpdate(args)) {
return;
}
@@ -481,7 +480,7 @@
LayerSnapshot* snapshot = getSnapshot(traversalPath);
const bool newSnapshot = snapshot == nullptr;
if (newSnapshot) {
- snapshot = createSnapshot(traversalPath, *layer);
+ snapshot = createSnapshot(traversalPath, *layer, parentSnapshot);
}
scheduler::LayerInfo::FrameRate oldFrameRate = snapshot->frameRate;
if (traversalPath.isRelative()) {
@@ -491,7 +490,7 @@
if (traversalPath.isAttached()) {
resetRelativeState(*snapshot);
}
- updateSnapshot(*snapshot, args, *layer, parentSnapshot, traversalPath, newSnapshot);
+ updateSnapshot(*snapshot, args, *layer, parentSnapshot, traversalPath);
}
for (auto& [childHierarchy, variant] : hierarchy.mChildren) {
@@ -522,12 +521,16 @@
return it == mIdToSnapshot.end() ? nullptr : it->second;
}
-LayerSnapshot* LayerSnapshotBuilder::createSnapshot(const LayerHierarchy::TraversalPath& id,
- const RequestedLayerState& layer) {
- mSnapshots.emplace_back(std::make_unique<LayerSnapshot>(layer, id));
+LayerSnapshot* LayerSnapshotBuilder::createSnapshot(const LayerHierarchy::TraversalPath& path,
+ const RequestedLayerState& layer,
+ const LayerSnapshot& parentSnapshot) {
+ mSnapshots.emplace_back(std::make_unique<LayerSnapshot>(layer, path));
LayerSnapshot* snapshot = mSnapshots.back().get();
snapshot->globalZ = static_cast<size_t>(mSnapshots.size()) - 1;
- mIdToSnapshot[id] = snapshot;
+ if (path.isClone() && path.variant != LayerHierarchy::Variant::Mirror) {
+ snapshot->mirrorRootPath = parentSnapshot.mirrorRootPath;
+ }
+ mIdToSnapshot[path] = snapshot;
return snapshot;
}
@@ -650,15 +653,14 @@
void LayerSnapshotBuilder::updateSnapshot(LayerSnapshot& snapshot, const Args& args,
const RequestedLayerState& requested,
const LayerSnapshot& parentSnapshot,
- const LayerHierarchy::TraversalPath& path,
- bool newSnapshot) {
+ const LayerHierarchy::TraversalPath& path) {
// Always update flags and visibility
ftl::Flags<RequestedLayerState::Changes> parentChanges = parentSnapshot.changes &
(RequestedLayerState::Changes::Hierarchy | RequestedLayerState::Changes::Geometry |
RequestedLayerState::Changes::Visibility | RequestedLayerState::Changes::Metadata |
RequestedLayerState::Changes::AffectsChildren |
RequestedLayerState::Changes::FrameRate);
- snapshot.changes = parentChanges | requested.changes;
+ snapshot.changes |= parentChanges | requested.changes;
snapshot.isHiddenByPolicyFromParent = parentSnapshot.isHiddenByPolicyFromParent ||
parentSnapshot.invalidTransform || requested.isHiddenByPolicy() ||
(args.excludeLayerIds.find(path.id) != args.excludeLayerIds.end());
@@ -668,16 +670,15 @@
snapshot.sidebandStreamHasFrame = requested.hasSidebandStreamFrame();
updateSurfaceDamage(requested, snapshot.hasReadyFrame, args.forceFullDamage,
snapshot.surfaceDamage);
-
- const bool forceUpdate = newSnapshot || args.forceUpdate == ForceUpdateFlags::ALL ||
- snapshot.changes.any(RequestedLayerState::Changes::Visibility |
- RequestedLayerState::Changes::Created);
- snapshot.outputFilter.layerStack = requested.parentId != UNASSIGNED_LAYER_ID
- ? parentSnapshot.outputFilter.layerStack
- : requested.layerStack;
+ snapshot.outputFilter.layerStack = parentSnapshot.path == LayerHierarchy::TraversalPath::ROOT
+ ? requested.layerStack
+ : parentSnapshot.outputFilter.layerStack;
uint32_t displayRotationFlags =
getDisplayRotationFlags(args.displays, snapshot.outputFilter.layerStack);
+ const bool forceUpdate = args.forceUpdate == ForceUpdateFlags::ALL ||
+ snapshot.changes.any(RequestedLayerState::Changes::Visibility |
+ RequestedLayerState::Changes::Created);
// always update the buffer regardless of visibility
if (forceUpdate || requested.what & layer_state_t::BUFFER_CHANGES || args.displayChanges) {
@@ -710,7 +711,8 @@
snapshot.desiredSdrHdrRatio = requested.desiredSdrHdrRatio;
}
- if (snapshot.isHiddenByPolicyFromParent && !newSnapshot) {
+ if (snapshot.isHiddenByPolicyFromParent &&
+ !snapshot.changes.test(RequestedLayerState::Changes::Created)) {
if (forceUpdate ||
snapshot.changes.any(RequestedLayerState::Changes::Hierarchy |
RequestedLayerState::Changes::Geometry |
@@ -727,9 +729,6 @@
snapshot.isSecure =
parentSnapshot.isSecure || (requested.flags & layer_state_t::eLayerSecure);
snapshot.isTrustedOverlay = parentSnapshot.isTrustedOverlay || requested.isTrustedOverlay;
- snapshot.outputFilter.layerStack = requested.parentId != UNASSIGNED_LAYER_ID
- ? parentSnapshot.outputFilter.layerStack
- : requested.layerStack;
snapshot.outputFilter.toInternalDisplay = parentSnapshot.outputFilter.toInternalDisplay ||
(requested.flags & layer_state_t::eLayerSkipScreenshot);
snapshot.stretchEffect = (requested.stretchEffect.hasEffect())
@@ -816,12 +815,11 @@
snapshot.color.a == 1.f;
snapshot.blendMode = getBlendMode(snapshot, requested);
LLOGV(snapshot.sequence,
- "%supdated [%d]%s changes parent:%s global:%s local:%s requested:%s %s from parent %s",
- args.forceUpdate == ForceUpdateFlags::ALL ? "Force " : "", requested.id,
- requested.name.c_str(), parentSnapshot.changes.string().c_str(),
- snapshot.changes.string().c_str(), requested.changes.string().c_str(),
- std::to_string(requested.what).c_str(), snapshot.getDebugString().c_str(),
- parentSnapshot.getDebugString().c_str());
+ "%supdated %s changes:%s parent:%s requested:%s requested:%s from parent %s",
+ args.forceUpdate == ForceUpdateFlags::ALL ? "Force " : "",
+ snapshot.getDebugString().c_str(), snapshot.changes.string().c_str(),
+ parentSnapshot.changes.string().c_str(), requested.changes.string().c_str(),
+ std::to_string(requested.what).c_str(), parentSnapshot.getDebugString().c_str());
}
void LayerSnapshotBuilder::updateRoundedCorner(LayerSnapshot& snapshot,
@@ -1024,7 +1022,7 @@
// touches from going outside the cloned area.
if (path.isClone()) {
snapshot.inputInfo.inputConfig |= gui::WindowInfo::InputConfig::CLONE;
- auto clonedRootSnapshot = getSnapshot(path.getMirrorRoot());
+ auto clonedRootSnapshot = getSnapshot(snapshot.mirrorRootPath);
if (clonedRootSnapshot) {
const Rect rect =
displayInfo.transform.transform(Rect{clonedRootSnapshot->transformedBounds});
diff --git a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.h b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.h
index 548cbc0..07b0d14 100644
--- a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.h
+++ b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.h
@@ -99,8 +99,7 @@
LayerHierarchy::TraversalPath& traversalPath,
const LayerSnapshot& parentSnapshot);
void updateSnapshot(LayerSnapshot&, const Args&, const RequestedLayerState&,
- const LayerSnapshot& parentSnapshot, const LayerHierarchy::TraversalPath&,
- bool newSnapshot);
+ const LayerSnapshot& parentSnapshot, const LayerHierarchy::TraversalPath&);
static void updateRelativeState(LayerSnapshot& snapshot, const LayerSnapshot& parentSnapshot,
bool parentIsRelative, const Args& args);
static void resetRelativeState(LayerSnapshot& snapshot);
@@ -115,7 +114,8 @@
const Args& args);
void sortSnapshotsByZ(const Args& args);
LayerSnapshot* createSnapshot(const LayerHierarchy::TraversalPath& id,
- const RequestedLayerState& layer);
+ const RequestedLayerState& layer,
+ const LayerSnapshot& parentSnapshot);
void updateChildState(LayerSnapshot& snapshot, const LayerSnapshot& childSnapshot,
const Args& args);
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 39f8307..bee89aa 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -5097,7 +5097,7 @@
args.name, args.flags, -1 /* parentId */);
}
- {
+ if (mLegacyFrontEndEnabled) {
std::scoped_lock<std::mutex> lock(mMirrorDisplayLock);
mMirrorDisplays.emplace_back(layerStack, outResult.handle, args.client);
}
diff --git a/services/surfaceflinger/tests/unittests/LayerHierarchyTest.h b/services/surfaceflinger/tests/unittests/LayerHierarchyTest.h
index cdcc6f4..b9a6159 100644
--- a/services/surfaceflinger/tests/unittests/LayerHierarchyTest.h
+++ b/services/surfaceflinger/tests/unittests/LayerHierarchyTest.h
@@ -274,6 +274,22 @@
mLifecycleManager.applyTransactions(transactions);
}
+ void setTouchableRegion(uint32_t id, Region region) {
+ std::vector<TransactionState> transactions;
+ transactions.emplace_back();
+ transactions.back().states.push_back({});
+
+ transactions.back().states.front().state.what = layer_state_t::eInputInfoChanged;
+ transactions.back().states.front().state.surface = mHandles[id];
+ transactions.back().states.front().state.layerId = static_cast<int32_t>(id);
+ transactions.back().states.front().state.windowInfoHandle =
+ sp<gui::WindowInfoHandle>::make();
+ auto inputInfo = transactions.back().states.front().state.windowInfoHandle->editInfo();
+ inputInfo->touchableRegion = region;
+ inputInfo->token = sp<BBinder>::make();
+ mLifecycleManager.applyTransactions(transactions);
+ }
+
LayerLifecycleManager mLifecycleManager;
std::unordered_map<uint32_t, sp<LayerHandle>> mHandles;
};
diff --git a/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp b/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp
index 5c8bd6f..14569ab 100644
--- a/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp
+++ b/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp
@@ -100,6 +100,9 @@
}
LayerSnapshot* getSnapshot(uint32_t layerId) { return mSnapshotBuilder.getSnapshot(layerId); }
+ LayerSnapshot* getSnapshot(const LayerHierarchy::TraversalPath path) {
+ return mSnapshotBuilder.getSnapshot(path);
+ }
LayerHierarchyBuilder mHierarchyBuilder{{}};
LayerSnapshotBuilder mSnapshotBuilder;
@@ -322,7 +325,7 @@
// └── 2
// ROOT (DISPLAY 1)
// └── 3 (mirrors display 0)
-TEST_F(LayerSnapshotTest, displayMirrorRespects) {
+TEST_F(LayerSnapshotTest, displayMirrorRespectsLayerSkipScreenshotFlag) {
setFlags(12, layer_state_t::eLayerSkipScreenshot, layer_state_t::eLayerSkipScreenshot);
createDisplayMirrorLayer(3, ui::LayerStack::fromValue(0));
setLayerStack(3, 1);
@@ -331,4 +334,61 @@
UPDATE_AND_VERIFY(mSnapshotBuilder, expected);
}
+// ROOT (DISPLAY 0)
+// ├── 1
+// │ ├── 11
+// │ │ └── 111
+// │ └── 13
+// └── 2
+// ROOT (DISPLAY 3)
+// └── 3 (mirrors display 0)
+TEST_F(LayerSnapshotTest, mirrorLayerGetsCorrectLayerStack) {
+ reparentLayer(12, UNASSIGNED_LAYER_ID);
+ createDisplayMirrorLayer(3, ui::LayerStack::fromValue(0));
+ setLayerStack(3, 3);
+ createDisplayMirrorLayer(4, ui::LayerStack::fromValue(0));
+ setLayerStack(4, 4);
+
+ std::vector<uint32_t> expected = {4, 1, 11, 111, 13, 2, 3, 1, 11,
+ 111, 13, 2, 1, 11, 111, 13, 2};
+ UPDATE_AND_VERIFY(mSnapshotBuilder, expected);
+ EXPECT_EQ(getSnapshot({.id = 111, .mirrorRootId = 3})->outputFilter.layerStack.id, 3u);
+ EXPECT_EQ(getSnapshot({.id = 111, .mirrorRootId = 4})->outputFilter.layerStack.id, 4u);
+}
+
+// ROOT (DISPLAY 0)
+// ├── 1 (crop 50x50)
+// │ ├── 11
+// │ │ └── 111
+// │ └── 13
+// └── 2
+// ROOT (DISPLAY 3)
+// └── 3 (mirrors display 0) (crop 100x100)
+TEST_F(LayerSnapshotTest, mirrorLayerTouchIsCroppedByMirrorRoot) {
+ reparentLayer(12, UNASSIGNED_LAYER_ID);
+ createDisplayMirrorLayer(3, ui::LayerStack::fromValue(0));
+ setLayerStack(3, 3);
+ setCrop(1, Rect{50, 50});
+ setCrop(3, Rect{100, 100});
+ setCrop(111, Rect{200, 200});
+ Region touch{Rect{0, 0, 1000, 1000}};
+ setTouchableRegion(111, touch);
+ std::vector<uint32_t> expected = {3, 1, 11, 111, 13, 2, 1, 11, 111, 13, 2};
+ UPDATE_AND_VERIFY(mSnapshotBuilder, expected);
+ EXPECT_TRUE(getSnapshot({.id = 111})->inputInfo.touchableRegion.hasSameRects(touch));
+ Region touchCroppedByMirrorRoot{Rect{0, 0, 50, 50}};
+ EXPECT_TRUE(getSnapshot({.id = 111, .mirrorRootId = 3})
+ ->inputInfo.touchableRegion.hasSameRects(touchCroppedByMirrorRoot));
+}
+
+TEST_F(LayerSnapshotTest, canRemoveDisplayMirror) {
+ setFlags(12, layer_state_t::eLayerSkipScreenshot, layer_state_t::eLayerSkipScreenshot);
+ createDisplayMirrorLayer(3, ui::LayerStack::fromValue(0));
+ setLayerStack(3, 1);
+ std::vector<uint32_t> expected = {3, 1, 11, 111, 13, 2, 1, 11, 111, 12, 121, 122, 1221, 13, 2};
+ UPDATE_AND_VERIFY(mSnapshotBuilder, expected);
+ destroyLayerHandle(3);
+ UPDATE_AND_VERIFY(mSnapshotBuilder, STARTING_ZORDER);
+}
+
} // namespace android::surfaceflinger::frontend