Merge "Allow relative layering of children"
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 58b5db0..413d06a 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -1102,6 +1102,19 @@
return true;
}
+bool Layer::setChildRelativeLayer(const sp<Layer>& childLayer,
+ const sp<IBinder>& relativeToHandle, int32_t relativeZ) {
+ ssize_t idx = mCurrentChildren.indexOf(childLayer);
+ if (idx < 0) {
+ return false;
+ }
+ if (childLayer->setRelativeLayer(relativeToHandle, relativeZ)) {
+ mCurrentChildren.removeAt(idx);
+ mCurrentChildren.add(childLayer);
+ }
+ return true;
+}
+
bool Layer::setLayer(int32_t z) {
if (mCurrentState.z == z) return false;
mCurrentState.sequence++;
@@ -1603,11 +1616,7 @@
const LayerVector& children = useDrawing ? mDrawingChildren : mCurrentChildren;
const State& state = useDrawing ? mDrawingState : mCurrentState;
- if (state.zOrderRelatives.size() == 0) {
- return children;
- }
LayerVector traverse;
-
for (const wp<Layer>& weakRelative : state.zOrderRelatives) {
sp<Layer> strongRelative = weakRelative.promote();
if (strongRelative != nullptr) {
@@ -1616,6 +1625,10 @@
}
for (const sp<Layer>& child : children) {
+ const State& childState = useDrawing ? child->mDrawingState : child->mCurrentState;
+ if (childState.zOrderRelativeOf != nullptr) {
+ continue;
+ }
traverse.add(child);
}
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 44b178a..9ea800e 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -482,6 +482,8 @@
bool hasParent() const { return getParent() != nullptr; }
Rect computeScreenBounds(bool reduceTransparentRegion = true) const;
bool setChildLayer(const sp<Layer>& childLayer, int32_t z);
+ bool setChildRelativeLayer(const sp<Layer>& childLayer,
+ const sp<IBinder>& relativeToHandle, int32_t relativeZ);
// Copy the current list of children to the drawing state. Called by
// SurfaceFlinger to complete a transaction.
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index dc178d7..4c03112 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -3143,11 +3143,21 @@
}
}
if (what & layer_state_t::eRelativeLayerChanged) {
- ssize_t idx = mCurrentState.layersSortedByZ.indexOf(layer);
- if (layer->setRelativeLayer(s.relativeLayerHandle, s.z)) {
- mCurrentState.layersSortedByZ.removeAt(idx);
- mCurrentState.layersSortedByZ.add(layer);
- flags |= eTransactionNeeded|eTraversalNeeded;
+ // NOTE: index needs to be calculated before we update the state
+ const auto& p = layer->getParent();
+ if (p == nullptr) {
+ ssize_t idx = mCurrentState.layersSortedByZ.indexOf(layer);
+ if (layer->setRelativeLayer(s.relativeLayerHandle, s.z) && idx >= 0) {
+ mCurrentState.layersSortedByZ.removeAt(idx);
+ mCurrentState.layersSortedByZ.add(layer);
+ // we need traversal (state changed)
+ // AND transaction (list changed)
+ flags |= eTransactionNeeded|eTraversalNeeded;
+ }
+ } else {
+ if (p->setChildRelativeLayer(layer, s.relativeLayerHandle, s.z)) {
+ flags |= eTransactionNeeded|eTraversalNeeded;
+ }
}
}
if (what & layer_state_t::eSizeChanged) {
diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp
index 16a16a5..90d48b9 100644
--- a/services/surfaceflinger/tests/Transaction_test.cpp
+++ b/services/surfaceflinger/tests/Transaction_test.cpp
@@ -1413,6 +1413,27 @@
}
}
+TEST_F(ChildLayerTest, ChildLayerRelativeLayer) {
+ sp<SurfaceControl> relative = mComposerClient->createSurface(String8("Relative surface"),
+ 128, 128, PIXEL_FORMAT_RGBA_8888, 0);
+ fillSurfaceRGBA8(relative, 255, 255, 255);
+
+ Transaction t;
+ t.setLayer(relative, INT32_MAX)
+ .setRelativeLayer(mChild, relative->getHandle(), 1)
+ .setPosition(mFGSurfaceControl, 0, 0)
+ .apply(true);
+
+ // We expect that the child should have been elevated above our
+ // INT_MAX layer even though it's not a child of it.
+ {
+ ScreenCapture::captureScreen(&mCapture);
+ mCapture->expectChildColor(0, 0);
+ mCapture->expectChildColor(9, 9);
+ mCapture->checkPixel(10, 10, 255, 255, 255);
+ }
+}
+
class LayerColorTest : public LayerUpdateTest {
protected:
void SetUp() override {