Ignore local transforms when mirroring a partial hierarchy
When mirroring a partial hierarchy remove the local transform
on the mirrored root. This is necessary because we are placing
the mirrored root under a new parent layer and its original
position relative to the old parent is no longer relevant. This
fixes offsets when mirroring a freeform window.
Flag: com.android.graphics.surfaceflinger.flags.detached_mirror
Fixes: 337845753
Test: atest libsurfaceflinger_unittest
Change-Id: I0453026217f62868a4f6d1362cdc8187baf3f9b0
diff --git a/services/surfaceflinger/FrontEnd/LayerHierarchy.cpp b/services/surfaceflinger/FrontEnd/LayerHierarchy.cpp
index 821ac0c..0dcbb3c 100644
--- a/services/surfaceflinger/FrontEnd/LayerHierarchy.cpp
+++ b/services/surfaceflinger/FrontEnd/LayerHierarchy.cpp
@@ -153,7 +153,7 @@
out << prefix + (isLastChild ? "└─ " : "├─ ");
if (variant == LayerHierarchy::Variant::Relative) {
out << "(Relative) ";
- } else if (variant == LayerHierarchy::Variant::Mirror) {
+ } else if (LayerHierarchy::isMirror(variant)) {
if (!includeMirroredHierarchy) {
out << "(Mirroring) " << *mLayer << "\n" + prefix + " └─ ...";
return;
@@ -289,6 +289,12 @@
LayerHierarchy* mirror = getHierarchyFromId(mirrorId);
hierarchy->addChild(mirror, LayerHierarchy::Variant::Mirror);
}
+ if (FlagManager::getInstance().detached_mirror()) {
+ if (layer->layerIdToMirror != UNASSIGNED_LAYER_ID) {
+ LayerHierarchy* mirror = getHierarchyFromId(layer->layerIdToMirror);
+ hierarchy->addChild(mirror, LayerHierarchy::Variant::Detached_Mirror);
+ }
+ }
}
void LayerHierarchyBuilder::onLayerDestroyed(RequestedLayerState* layer) {
@@ -325,7 +331,7 @@
LayerHierarchy* hierarchy = getHierarchyFromId(layer->id);
auto it = hierarchy->mChildren.begin();
while (it != hierarchy->mChildren.end()) {
- if (it->second == LayerHierarchy::Variant::Mirror) {
+ if (LayerHierarchy::isMirror(it->second)) {
it = hierarchy->mChildren.erase(it);
} else {
it++;
@@ -335,6 +341,12 @@
for (uint32_t mirrorId : layer->mirrorIds) {
hierarchy->addChild(getHierarchyFromId(mirrorId), LayerHierarchy::Variant::Mirror);
}
+ if (FlagManager::getInstance().detached_mirror()) {
+ if (layer->layerIdToMirror != UNASSIGNED_LAYER_ID) {
+ hierarchy->addChild(getHierarchyFromId(layer->layerIdToMirror),
+ LayerHierarchy::Variant::Detached_Mirror);
+ }
+ }
}
void LayerHierarchyBuilder::doUpdate(
@@ -501,7 +513,7 @@
// stored to reset the id upon destruction.
traversalPath.id = layerId;
traversalPath.variant = variant;
- if (variant == LayerHierarchy::Variant::Mirror) {
+ if (LayerHierarchy::isMirror(variant)) {
traversalPath.mirrorRootIds.emplace_back(mParentPath.id);
} else if (variant == LayerHierarchy::Variant::Relative) {
if (std::find(traversalPath.relativeRootIds.begin(), traversalPath.relativeRootIds.end(),
@@ -516,7 +528,7 @@
LayerHierarchy::ScopedAddToTraversalPath::~ScopedAddToTraversalPath() {
// Reset the traversal id to its original parent state using the state that was saved in
// the constructor.
- if (mTraversalPath.variant == LayerHierarchy::Variant::Mirror) {
+ if (LayerHierarchy::isMirror(mTraversalPath.variant)) {
mTraversalPath.mirrorRootIds.pop_back();
} else if (mTraversalPath.variant == LayerHierarchy::Variant::Relative) {
mTraversalPath.relativeRootIds.pop_back();
diff --git a/services/surfaceflinger/FrontEnd/LayerHierarchy.h b/services/surfaceflinger/FrontEnd/LayerHierarchy.h
index a1c73c3..f62e758 100644
--- a/services/surfaceflinger/FrontEnd/LayerHierarchy.h
+++ b/services/surfaceflinger/FrontEnd/LayerHierarchy.h
@@ -35,6 +35,7 @@
// Detached - child of the parent but currently relative parented to another layer
// Relative - relative child of the parent
// Mirror - mirrored from another layer
+// Detached_Mirror - mirrored from another layer, ignoring local transform
//
// By representing the hierarchy as a graph, we can represent mirrored layer hierarchies without
// cloning the layer requested state. The mirrored hierarchy and its corresponding
@@ -43,13 +44,18 @@
class LayerHierarchy {
public:
enum Variant : uint32_t {
- Attached, // child of the parent
- Detached, // child of the parent but currently relative parented to another layer
- Relative, // relative child of the parent
- Mirror, // mirrored from another layer
+ Attached, // child of the parent
+ Detached, // child of the parent but currently relative parented to another layer
+ Relative, // relative child of the parent
+ Mirror, // mirrored from another layer
+ Detached_Mirror, // mirrored from another layer, ignoring local transform
ftl_first = Attached,
- ftl_last = Mirror,
+ ftl_last = Detached_Mirror,
};
+ static inline bool isMirror(Variant variant) {
+ return ((variant == Mirror) || (variant == Detached_Mirror));
+ }
+
// Represents a unique path to a node.
// The layer hierarchy is represented as a graph. Each node can be visited by multiple parents.
// This allows us to represent mirroring in an efficient way. See the example below:
diff --git a/services/surfaceflinger/FrontEnd/LayerLifecycleManager.cpp b/services/surfaceflinger/FrontEnd/LayerLifecycleManager.cpp
index 0983e7c..4b0618e 100644
--- a/services/surfaceflinger/FrontEnd/LayerLifecycleManager.cpp
+++ b/services/surfaceflinger/FrontEnd/LayerLifecycleManager.cpp
@@ -72,8 +72,10 @@
// Check if we are mirroring a single layer, and if so add it to the list of children
// to be mirrored.
layer.layerIdToMirror = linkLayer(layer.layerIdToMirror, layer.id);
- if (layer.layerIdToMirror != UNASSIGNED_LAYER_ID) {
- layer.mirrorIds.emplace_back(layer.layerIdToMirror);
+ if (!FlagManager::getInstance().detached_mirror()) {
+ if (layer.layerIdToMirror != UNASSIGNED_LAYER_ID) {
+ layer.mirrorIds.emplace_back(layer.layerIdToMirror);
+ }
}
}
layer.touchCropId = linkLayer(layer.touchCropId, layer.id);
diff --git a/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp b/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp
index ea06cf6..70e3c64 100644
--- a/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp
+++ b/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp
@@ -127,9 +127,8 @@
pid = state.ownerPid;
changes = RequestedLayerState::Changes::Created;
clientChanges = 0;
- mirrorRootPath = path.variant == LayerHierarchy::Variant::Mirror
- ? path
- : LayerHierarchy::TraversalPath::ROOT;
+ mirrorRootPath =
+ LayerHierarchy::isMirror(path.variant) ? path : LayerHierarchy::TraversalPath::ROOT;
reachablilty = LayerSnapshot::Reachablilty::Unreachable;
frameRateSelectionPriority = state.frameRateSelectionPriority;
layerMetadata = state.metadata;
@@ -472,13 +471,14 @@
geomContentCrop = requested.getBufferCrop();
}
- if (forceUpdate ||
- requested.what &
- (layer_state_t::eFlagsChanged | layer_state_t::eDestinationFrameChanged |
- layer_state_t::ePositionChanged | layer_state_t::eMatrixChanged |
- layer_state_t::eBufferTransformChanged |
- layer_state_t::eTransformToDisplayInverseChanged) ||
- requested.changes.test(RequestedLayerState::Changes::BufferSize) || displayChanges) {
+ if ((forceUpdate ||
+ requested.what &
+ (layer_state_t::eFlagsChanged | layer_state_t::eDestinationFrameChanged |
+ layer_state_t::ePositionChanged | layer_state_t::eMatrixChanged |
+ layer_state_t::eBufferTransformChanged |
+ layer_state_t::eTransformToDisplayInverseChanged) ||
+ requested.changes.test(RequestedLayerState::Changes::BufferSize) || displayChanges) &&
+ !ignoreLocalTransform) {
localTransform = requested.getTransform(displayRotationFlags);
localTransformInverse = localTransform.inverse();
}
diff --git a/services/surfaceflinger/FrontEnd/LayerSnapshot.h b/services/surfaceflinger/FrontEnd/LayerSnapshot.h
index 73ee22f..eef8dff 100644
--- a/services/surfaceflinger/FrontEnd/LayerSnapshot.h
+++ b/services/surfaceflinger/FrontEnd/LayerSnapshot.h
@@ -80,6 +80,9 @@
ui::Transform localTransformInverse;
gui::WindowInfo inputInfo;
ui::Transform localTransform;
+ // set to true if this snapshot will ignore local transforms. Used when the snapshot
+ // is a mirror root
+ bool ignoreLocalTransform;
gui::DropInputMode dropInputMode;
bool isTrustedOverlay;
gui::GameMode gameMode;
diff --git a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp
index 7daeefe..a2b5329 100644
--- a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp
+++ b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp
@@ -575,9 +575,11 @@
mSnapshots.emplace_back(std::make_unique<LayerSnapshot>(layer, path));
LayerSnapshot* snapshot = mSnapshots.back().get();
snapshot->globalZ = static_cast<size_t>(mSnapshots.size()) - 1;
- if (path.isClone() && path.variant != LayerHierarchy::Variant::Mirror) {
+ if (path.isClone() && !LayerHierarchy::isMirror(path.variant)) {
snapshot->mirrorRootPath = parentSnapshot.mirrorRootPath;
}
+ snapshot->ignoreLocalTransform =
+ path.isClone() && path.variant == LayerHierarchy::Variant::Detached_Mirror;
mPathToSnapshot[path] = snapshot;
mIdToSnapshots.emplace(path.id, snapshot);