summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/gui/SurfaceComposerClient.h2
-rw-r--r--include/gui/SurfaceControl.h21
-rw-r--r--include/private/gui/LayerState.h5
-rw-r--r--libs/gui/LayerState.cpp2
-rw-r--r--libs/gui/SurfaceComposerClient.cpp21
-rw-r--r--libs/gui/SurfaceControl.cpp8
-rw-r--r--services/surfaceflinger/Layer.cpp105
-rw-r--r--services/surfaceflinger/Layer.h12
-rw-r--r--services/surfaceflinger/LayerVector.cpp12
-rw-r--r--services/surfaceflinger/SurfaceFlinger.cpp5
-rw-r--r--services/surfaceflinger/tests/Transaction_test.cpp43
11 files changed, 218 insertions, 18 deletions
diff --git a/include/gui/SurfaceComposerClient.h b/include/gui/SurfaceComposerClient.h
index 394425a328..ec310cf6f9 100644
--- a/include/gui/SurfaceComposerClient.h
+++ b/include/gui/SurfaceComposerClient.h
@@ -146,6 +146,8 @@ public:
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 3cff7df260..712a323337 100644
--- a/include/gui/SurfaceControl.h
+++ b/include/gui/SurfaceControl.h
@@ -62,6 +62,27 @@ public:
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 20f51a57ce..307c764702 100644
--- a/include/private/gui/LayerState.h
+++ b/include/private/gui/LayerState.h
@@ -58,7 +58,8 @@ struct layer_state_t {
eOverrideScalingModeChanged = 0x00000800,
eGeometryAppliesWithResize = 0x00001000,
eReparentChildren = 0x00002000,
- eDetachChildren = 0x00004000
+ eDetachChildren = 0x00004000,
+ eRelativeLayerChanged = 0x00008000
};
layer_state_t()
@@ -104,6 +105,8 @@ struct layer_state_t {
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 2461cba152..9b06e63610 100644
--- a/libs/gui/LayerState.cpp
+++ b/libs/gui/LayerState.cpp
@@ -44,6 +44,7 @@ status_t layer_state_t::write(Parcel& output) const
output.writeUint64(frameNumber);
output.writeInt32(overrideScalingMode);
output.writeStrongBinder(IInterface::asBinder(barrierGbp));
+ output.writeStrongBinder(relativeLayerHandle);
output.write(transparentRegion);
return NO_ERROR;
}
@@ -75,6 +76,7 @@ status_t layer_state_t::read(const Parcel& input)
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 56c7586041..8c8384399c 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -149,6 +149,8 @@ public:
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 @@ status_t Composer::setLayer(const sp<SurfaceComposerClient>& client,
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 @@ status_t SurfaceComposerClient::setLayer(const sp<IBinder>& id, int32_t z) {
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 7a68f1174a..bf8a815fe6 100644
--- a/libs/gui/SurfaceControl.cpp
+++ b/libs/gui/SurfaceControl.cpp
@@ -102,11 +102,19 @@ status_t SurfaceControl::setLayerStack(uint32_t layerStack) {
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 c211c7b4ed..b10d437fea 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -1719,10 +1719,55 @@ bool Layer::setLayer(int32_t z) {
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;
@@ -2506,40 +2551,70 @@ int32_t Layer::getZ() const {
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 e21be8b032..a5224ecb4b 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -151,6 +151,12 @@ public:
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 @@ public:
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 @@ private:
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 7ba6ad3bfa..90e6395ea1 100644
--- a/services/surfaceflinger/LayerVector.cpp
+++ b/services/surfaceflinger/LayerVector.cpp
@@ -42,13 +42,21 @@ int LayerVector::do_compare(const void* lhs, const void* rhs) const
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 26baaaecb2..dcb24e4e35 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -2820,6 +2820,11 @@ uint32_t SurfaceFlinger::setClientStateLocked(
}
}
}
+ 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 a46ba48026..441fc7e092 100644
--- a/services/surfaceflinger/tests/Transaction_test.cpp
+++ b/services/surfaceflinger/tests/Transaction_test.cpp
@@ -662,6 +662,49 @@ TEST_F(LayerUpdateTest, DeferredTransactionTest) {
}
}
+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 {