diff options
author | 2017-04-10 16:55:57 -0700 | |
---|---|---|
committer | 2017-04-12 12:48:05 -0700 | |
commit | db66e627ad8904491e384c64f82fc77a939b9705 (patch) | |
tree | 28bde44d8ef5a51448b544b511539a41ba336828 | |
parent | 1d472756aa06f17c34020c35d2f2a598dce69bfb (diff) |
SurfaceFlinger: Add parent-less relative layering.
This is a temporary functionality for the intermediate state where not
all child-surface like things in WM land are ported to use Child
Surfaces. In particular, we have ported SurfaceView to use child
surfaces and relative Z ordering. However the TV frameworks provide a
View framework component which overlays views over the SurfaceView but
below the main application window. Since we have not ported View
framework surfaces to use child layers, there is nothing the WM or
View Framework can do about this situation. Luckily the WM API's to
have requested this are @hide but we have the one media framework
component using it. In order to solve this issue we provide a method
to set Z ordering relative to another window without inheriting
its coordinate space as a child window would. This way the WM can
recognize these TYPE_APPLICATION_MEDIA_OVERLAY windows and Z-order
them at -1 with respect to the parents (and the SurfaceView can be at
-2).
Test: Included in transaction tests. Also manual test of bug repro steps with accomp frameworks/base CL
Bug: 36693738
Change-Id: I921852d3d34f67f79ec745b9703f9e679867e7a1
-rw-r--r-- | include/gui/SurfaceComposerClient.h | 2 | ||||
-rw-r--r-- | include/gui/SurfaceControl.h | 21 | ||||
-rw-r--r-- | include/private/gui/LayerState.h | 5 | ||||
-rw-r--r-- | libs/gui/LayerState.cpp | 2 | ||||
-rw-r--r-- | libs/gui/SurfaceComposerClient.cpp | 21 | ||||
-rw-r--r-- | libs/gui/SurfaceControl.cpp | 8 | ||||
-rw-r--r-- | services/surfaceflinger/Layer.cpp | 105 | ||||
-rw-r--r-- | services/surfaceflinger/Layer.h | 12 | ||||
-rw-r--r-- | services/surfaceflinger/LayerVector.cpp | 12 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceFlinger.cpp | 5 | ||||
-rw-r--r-- | services/surfaceflinger/tests/Transaction_test.cpp | 43 |
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 { |