Merge "SurfaceFlinger: Add parent-less relative layering." into oc-dev
diff --git a/include/gui/SurfaceComposerClient.h b/include/gui/SurfaceComposerClient.h
index 394425a..ec310cf 100644
--- a/include/gui/SurfaceComposerClient.h
+++ b/include/gui/SurfaceComposerClient.h
@@ -146,6 +146,8 @@
status_t setFlags(const sp<IBinder>& id, uint32_t flags, uint32_t mask);
status_t setTransparentRegionHint(const sp<IBinder>& id, const Region& transparent);
status_t setLayer(const sp<IBinder>& id, int32_t layer);
+ status_t setRelativeLayer(const sp<IBinder>& id,
+ const sp<IBinder>& relativeTo, int32_t layer);
status_t setAlpha(const sp<IBinder>& id, float alpha=1.0f);
status_t setMatrix(const sp<IBinder>& id, float dsdx, float dtdx, float dtdy, float dsdy);
status_t setPosition(const sp<IBinder>& id, float x, float y);
diff --git a/include/gui/SurfaceControl.h b/include/gui/SurfaceControl.h
index 3cff7df..712a323 100644
--- a/include/gui/SurfaceControl.h
+++ b/include/gui/SurfaceControl.h
@@ -62,6 +62,27 @@
status_t setLayerStack(uint32_t layerStack);
status_t setLayer(int32_t layer);
+
+ // Sets a Z order relative to the Surface specified by "relativeTo" but
+ // without becoming a full child of the relative. Z-ordering works exactly
+ // as if it were a child however.
+ //
+ // As a nod to sanity, only non-child surfaces may have a relative Z-order.
+ //
+ // This overrides any previous and is overriden by any future calls
+ // to setLayer.
+ //
+ // If the relative dissapears, the Surface will have no layer and be
+ // invisible, until the next time set(Relative)Layer is called.
+ //
+ // TODO: This is probably a hack. Currently it exists only to work around
+ // some framework usage of the hidden APPLICATION_MEDIA_OVERLAY window type
+ // which allows inserting a window between a SurfaceView and it's main application
+ // window. However, since we are using child windows for the SurfaceView, but not using
+ // child windows elsewhere in O, the WindowManager can't set the layer appropriately.
+ // This is only used by the "TvInputService" and following the port of ViewRootImpl
+ // to child surfaces, we can then port this and remove this method.
+ status_t setRelativeLayer(const sp<IBinder>& relativeTo, int32_t layer);
status_t setPosition(float x, float y);
status_t setSize(uint32_t w, uint32_t h);
status_t hide();
diff --git a/include/private/gui/LayerState.h b/include/private/gui/LayerState.h
index 20f51a5..307c764 100644
--- a/include/private/gui/LayerState.h
+++ b/include/private/gui/LayerState.h
@@ -58,7 +58,8 @@
eOverrideScalingModeChanged = 0x00000800,
eGeometryAppliesWithResize = 0x00001000,
eReparentChildren = 0x00002000,
- eDetachChildren = 0x00004000
+ eDetachChildren = 0x00004000,
+ eRelativeLayerChanged = 0x00008000
};
layer_state_t()
@@ -104,6 +105,8 @@
sp<IGraphicBufferProducer> barrierGbp;
+ sp<IBinder> relativeLayerHandle;
+
// non POD must be last. see write/read
Region transparentRegion;
};
diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp
index 2461cba..9b06e63 100644
--- a/libs/gui/LayerState.cpp
+++ b/libs/gui/LayerState.cpp
@@ -44,6 +44,7 @@
output.writeUint64(frameNumber);
output.writeInt32(overrideScalingMode);
output.writeStrongBinder(IInterface::asBinder(barrierGbp));
+ output.writeStrongBinder(relativeLayerHandle);
output.write(transparentRegion);
return NO_ERROR;
}
@@ -75,6 +76,7 @@
overrideScalingMode = input.readInt32();
barrierGbp =
interface_cast<IGraphicBufferProducer>(input.readStrongBinder());
+ relativeLayerHandle = input.readStrongBinder();
input.read(transparentRegion);
return NO_ERROR;
}
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 56c7586..8c83843 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -149,6 +149,8 @@
uint32_t w, uint32_t h);
status_t setLayer(const sp<SurfaceComposerClient>& client, const sp<IBinder>& id,
int32_t z);
+ status_t setRelativeLayer(const sp<SurfaceComposerClient>& client, const sp<IBinder>& id,
+ const sp<IBinder>& relativeTo, int32_t z);
status_t setFlags(const sp<SurfaceComposerClient>& client, const sp<IBinder>& id,
uint32_t flags, uint32_t mask);
status_t setTransparentRegionHint(
@@ -343,6 +345,20 @@
return NO_ERROR;
}
+status_t Composer::setRelativeLayer(const sp<SurfaceComposerClient>& client,
+ const sp<IBinder>& id, const sp<IBinder>& relativeTo,
+ int32_t z) {
+ Mutex::Autolock _l(mLock);
+ layer_state_t* s = getLayerStateLocked(client, id);
+ if (!s) {
+ return BAD_INDEX;
+ }
+ s->what |= layer_state_t::eRelativeLayerChanged;
+ s->relativeLayerHandle = relativeTo;
+ s->z = z;
+ return NO_ERROR;
+}
+
status_t Composer::setFlags(const sp<SurfaceComposerClient>& client,
const sp<IBinder>& id, uint32_t flags,
uint32_t mask) {
@@ -760,6 +776,11 @@
return getComposer().setLayer(this, id, z);
}
+status_t SurfaceComposerClient::setRelativeLayer(const sp<IBinder>& id,
+ const sp<IBinder>& relativeTo, int32_t z) {
+ return getComposer().setRelativeLayer(this, id, relativeTo, z);
+}
+
status_t SurfaceComposerClient::hide(const sp<IBinder>& id) {
return getComposer().setFlags(this, id,
layer_state_t::eLayerHidden,
diff --git a/libs/gui/SurfaceControl.cpp b/libs/gui/SurfaceControl.cpp
index 7a68f11..bf8a815 100644
--- a/libs/gui/SurfaceControl.cpp
+++ b/libs/gui/SurfaceControl.cpp
@@ -102,11 +102,19 @@
if (err < 0) return err;
return mClient->setLayerStack(mHandle, layerStack);
}
+
status_t SurfaceControl::setLayer(int32_t layer) {
status_t err = validate();
if (err < 0) return err;
return mClient->setLayer(mHandle, layer);
}
+
+status_t SurfaceControl::setRelativeLayer(const sp<IBinder>& relativeTo, int32_t layer) {
+ status_t err = validate();
+ if (err < 0) return err;
+ return mClient->setRelativeLayer(mHandle, relativeTo, layer);
+}
+
status_t SurfaceControl::setPosition(float x, float y) {
status_t err = validate();
if (err < 0) return err;
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 598a65a..027fae6 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -1713,10 +1713,55 @@
mCurrentState.sequence++;
mCurrentState.z = z;
mCurrentState.modified = true;
+
+ // Discard all relative layering.
+ if (mCurrentState.zOrderRelativeOf != nullptr) {
+ sp<Layer> strongRelative = mCurrentState.zOrderRelativeOf.promote();
+ if (strongRelative != nullptr) {
+ strongRelative->removeZOrderRelative(this);
+ }
+ mCurrentState.zOrderRelativeOf = nullptr;
+ }
setTransactionFlags(eTransactionNeeded);
return true;
}
+void Layer::removeZOrderRelative(const wp<Layer>& relative) {
+ mCurrentState.zOrderRelatives.remove(relative);
+ mCurrentState.sequence++;
+ mCurrentState.modified = true;
+ setTransactionFlags(eTransactionNeeded);
+}
+
+void Layer::addZOrderRelative(const wp<Layer>& relative) {
+ mCurrentState.zOrderRelatives.add(relative);
+ mCurrentState.modified = true;
+ mCurrentState.sequence++;
+ setTransactionFlags(eTransactionNeeded);
+}
+
+bool Layer::setRelativeLayer(const sp<IBinder>& relativeToHandle, int32_t z) {
+ sp<Handle> handle = static_cast<Handle*>(relativeToHandle.get());
+ if (handle == nullptr) {
+ return false;
+ }
+ sp<Layer> relative = handle->owner.promote();
+ if (relative == nullptr) {
+ return false;
+ }
+
+ mCurrentState.sequence++;
+ mCurrentState.modified = true;
+ mCurrentState.z = z;
+
+ mCurrentState.zOrderRelativeOf = relative;
+ relative->addZOrderRelative(this);
+
+ setTransactionFlags(eTransactionNeeded);
+
+ return true;
+}
+
bool Layer::setSize(uint32_t w, uint32_t h) {
if (mCurrentState.requested.w == w && mCurrentState.requested.h == h)
return false;
@@ -2500,40 +2545,70 @@
return mDrawingState.z;
}
+LayerVector Layer::makeTraversalList() {
+ if (mDrawingState.zOrderRelatives.size() == 0) {
+ return mDrawingChildren;
+ }
+ LayerVector traverse;
+
+ for (const wp<Layer>& weakRelative : mDrawingState.zOrderRelatives) {
+ sp<Layer> strongRelative = weakRelative.promote();
+ if (strongRelative != nullptr) {
+ traverse.add(strongRelative);
+ } else {
+ // We need to erase from current state instead of drawing
+ // state so we don't overwrite when copying
+ // the current state to the drawing state.
+ mCurrentState.zOrderRelatives.remove(weakRelative);
+ }
+ }
+
+ for (const sp<Layer>& child : mDrawingChildren) {
+ traverse.add(child);
+ }
+
+ return traverse;
+}
+
/**
- * Negatively signed children are before 'this' in Z-order.
+ * Negatively signed relatives are before 'this' in Z-order.
*/
void Layer::traverseInZOrder(const std::function<void(Layer*)>& exec) {
+ LayerVector list = makeTraversalList();
+
size_t i = 0;
- for (; i < mDrawingChildren.size(); i++) {
- const auto& child = mDrawingChildren[i];
- if (child->getZ() >= 0)
+ for (; i < list.size(); i++) {
+ const auto& relative = list[i];
+ if (relative->getZ() >= 0) {
break;
- child->traverseInZOrder(exec);
+ }
+ relative->traverseInZOrder(exec);
}
exec(this);
- for (; i < mDrawingChildren.size(); i++) {
- const auto& child = mDrawingChildren[i];
- child->traverseInZOrder(exec);
+ for (; i < list.size(); i++) {
+ const auto& relative = list[i];
+ relative->traverseInZOrder(exec);
}
}
/**
- * Positively signed children are before 'this' in reverse Z-order.
+ * Positively signed relatives are before 'this' in reverse Z-order.
*/
void Layer::traverseInReverseZOrder(const std::function<void(Layer*)>& exec) {
+ LayerVector list = makeTraversalList();
+
int32_t i = 0;
- for (i = mDrawingChildren.size()-1; i>=0; i--) {
- const auto& child = mDrawingChildren[i];
- if (child->getZ() < 0) {
+ for (i = list.size()-1; i>=0; i--) {
+ const auto& relative = list[i];
+ if (relative->getZ() < 0) {
break;
}
- child->traverseInReverseZOrder(exec);
+ relative->traverseInReverseZOrder(exec);
}
exec(this);
for (; i>=0; i--) {
- const auto& child = mDrawingChildren[i];
- child->traverseInReverseZOrder(exec);
+ const auto& relative = list[i];
+ relative->traverseInReverseZOrder(exec);
}
}
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index e21be8b..a5224ec 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -151,6 +151,12 @@
uint32_t appId;
uint32_t type;
+
+ // If non-null, a Surface this Surface's Z-order is interpreted relative to.
+ wp<Layer> zOrderRelativeOf;
+
+ // A list of surfaces whose Z-order is interpreted relative to ours.
+ SortedVector<wp<Layer>> zOrderRelatives;
};
// -----------------------------------------------------------------------
@@ -173,6 +179,8 @@
bool setFinalCrop(const Rect& crop, bool immediate);
bool setLayer(int32_t z);
+ bool setRelativeLayer(const sp<IBinder>& relativeToHandle, int32_t relativeZ);
+
bool setSize(uint32_t w, uint32_t h);
#ifdef USE_HWC2
bool setAlpha(float alpha);
@@ -549,6 +557,10 @@
void setParent(const sp<Layer>& layer);
+ LayerVector makeTraversalList();
+ void addZOrderRelative(const wp<Layer>& relative);
+ void removeZOrderRelative(const wp<Layer>& relative);
+
// -----------------------------------------------------------------------
class SyncPoint
diff --git a/services/surfaceflinger/LayerVector.cpp b/services/surfaceflinger/LayerVector.cpp
index 7ba6ad3..90e6395 100644
--- a/services/surfaceflinger/LayerVector.cpp
+++ b/services/surfaceflinger/LayerVector.cpp
@@ -42,13 +42,21 @@
void LayerVector::traverseInZOrder(const std::function<void(Layer*)>& consume) const {
for (size_t i = 0; i < size(); i++) {
- (*this)[i]->traverseInZOrder(consume);
+ const auto& layer = (*this)[i];
+ if (layer->getDrawingState().zOrderRelativeOf != nullptr) {
+ continue;
+ }
+ layer->traverseInZOrder(consume);
}
}
void LayerVector::traverseInReverseZOrder(const std::function<void(Layer*)>& consume) const {
for (auto i = static_cast<int64_t>(size()) - 1; i >= 0; i--) {
- (*this)[i]->traverseInReverseZOrder(consume);
+ const auto& layer = (*this)[i];
+ if (layer->getDrawingState().zOrderRelativeOf != nullptr) {
+ continue;
+ }
+ layer->traverseInReverseZOrder(consume);
}
}
} // namespace android
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index d72b3b5..f0cb93a 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -2866,6 +2866,11 @@
}
}
}
+ if (what & layer_state_t::eRelativeLayerChanged) {
+ if (layer->setRelativeLayer(s.relativeLayerHandle, s.z)) {
+ flags |= eTransactionNeeded|eTraversalNeeded;
+ }
+ }
if (what & layer_state_t::eSizeChanged) {
if (layer->setSize(s.w, s.h)) {
flags |= eTraversalNeeded;
diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp
index a46ba48..441fc7e 100644
--- a/services/surfaceflinger/tests/Transaction_test.cpp
+++ b/services/surfaceflinger/tests/Transaction_test.cpp
@@ -662,6 +662,49 @@
}
}
+TEST_F(LayerUpdateTest, LayerSetRelativeLayerWorks) {
+ sp<ScreenCapture> sc;
+ {
+ SCOPED_TRACE("before adding relative surface");
+ ScreenCapture::captureScreen(&sc);
+ sc->expectBGColor(24, 24);
+ sc->expectFGColor(75, 75);
+ sc->expectBGColor(145, 145);
+ }
+
+ auto relativeSurfaceControl = mComposerClient->createSurface(
+ String8("Test Surface"), 64, 64, PIXEL_FORMAT_RGBA_8888, 0);
+ fillSurfaceRGBA8(relativeSurfaceControl, 255, 177, 177);
+ waitForPostedBuffers();
+
+ // Now we stack the surface above the foreground surface and make sure it is visible.
+ SurfaceComposerClient::openGlobalTransaction();
+ relativeSurfaceControl->setPosition(64, 64);
+ relativeSurfaceControl->show();
+ relativeSurfaceControl->setRelativeLayer(mFGSurfaceControl->getHandle(), 1);
+ SurfaceComposerClient::closeGlobalTransaction(true);
+
+
+ {
+ SCOPED_TRACE("after adding relative surface");
+ ScreenCapture::captureScreen(&sc);
+ // our relative surface should be visible now.
+ sc->checkPixel(75, 75, 255, 177, 177);
+ }
+
+ // A call to setLayer will override a call to setRelativeLayer
+ SurfaceComposerClient::openGlobalTransaction();
+ relativeSurfaceControl->setLayer(0);
+ SurfaceComposerClient::closeGlobalTransaction();
+
+ {
+ SCOPED_TRACE("after set layer");
+ ScreenCapture::captureScreen(&sc);
+ // now the FG surface should be visible again.
+ sc->expectFGColor(75, 75);
+ }
+}
+
class ChildLayerTest : public LayerUpdateTest {
protected:
void SetUp() override {