diff options
author | 2017-03-01 17:49:23 +0000 | |
---|---|---|
committer | 2017-03-01 17:49:27 +0000 | |
commit | 77c073bdbe1b24a332056e1194a6162b7717a848 (patch) | |
tree | fefa2a6dc41aa65e35c8cc06d9dddaf64fc7b665 | |
parent | 5ebcd56c6f57514f7833e7528a08d8ca55c48f69 (diff) | |
parent | 9524cb3b37a91b5741790c77ff24fd825b02bca7 (diff) |
Merge changes from topic 'surfaceview-without-wm'
* changes:
Add detachChildren transaction.
Add deferTransaction variant taking GraphicBufferProducer.
-rw-r--r-- | include/gui/SurfaceComposerClient.h | 3 | ||||
-rw-r--r-- | include/gui/SurfaceControl.h | 22 | ||||
-rw-r--r-- | include/private/gui/LayerState.h | 7 | ||||
-rw-r--r-- | libs/gui/LayerState.cpp | 7 | ||||
-rw-r--r-- | libs/gui/SurfaceComposerClient.cpp | 43 | ||||
-rw-r--r-- | libs/gui/SurfaceControl.cpp | 13 | ||||
-rw-r--r-- | services/surfaceflinger/Client.cpp | 5 | ||||
-rw-r--r-- | services/surfaceflinger/Layer.cpp | 50 | ||||
-rw-r--r-- | services/surfaceflinger/Layer.h | 8 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceFlinger.cpp | 45 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceFlinger.h | 5 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceFlinger_hwc1.cpp | 45 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceInterceptor.cpp | 25 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceInterceptor.h | 5 | ||||
-rw-r--r-- | services/surfaceflinger/tests/Transaction_test.cpp | 64 |
15 files changed, 290 insertions, 57 deletions
diff --git a/include/gui/SurfaceComposerClient.h b/include/gui/SurfaceComposerClient.h index 46a3a5ff7f..1e8cf76627 100644 --- a/include/gui/SurfaceComposerClient.h +++ b/include/gui/SurfaceComposerClient.h @@ -155,8 +155,11 @@ public: status_t setLayerStack(const sp<IBinder>& id, uint32_t layerStack); status_t deferTransactionUntil(const sp<IBinder>& id, const sp<IBinder>& handle, uint64_t frameNumber); + status_t deferTransactionUntil(const sp<IBinder>& id, + const sp<Surface>& handle, uint64_t frameNumber); status_t reparentChildren(const sp<IBinder>& id, const sp<IBinder>& newParentHandle); + status_t detachChildren(const sp<IBinder>& id); status_t setOverrideScalingMode(const sp<IBinder>& id, int32_t overrideScalingMode); status_t setGeometryAppliesWithResize(const sp<IBinder>& id); diff --git a/include/gui/SurfaceControl.h b/include/gui/SurfaceControl.h index 99208b2e16..8ee35bc495 100644 --- a/include/gui/SurfaceControl.h +++ b/include/gui/SurfaceControl.h @@ -80,11 +80,31 @@ public: status_t setGeometryAppliesWithResize(); // Defers applying any changes made in this transaction until the Layer - // identified by handle reaches the given frameNumber + // identified by handle reaches the given frameNumber. If the Layer identified + // by handle is removed, then we will apply this transaction regardless of + // what frame number has been reached. status_t deferTransactionUntil(const sp<IBinder>& handle, uint64_t frameNumber); + + // A variant of deferTransactionUntil which identifies the Layer we wait for by + // Surface instead of Handle. Useful for clients which may not have the + // SurfaceControl for some of their Surfaces. Otherwise behaves identically. + status_t deferTransactionUntil(const sp<Surface>& barrier, uint64_t frameNumber); + // Reparents all children of this layer to the new parent handle. status_t reparentChildren(const sp<IBinder>& newParentHandle); + // Detaches all child surfaces (and their children recursively) + // from their SurfaceControl. + // The child SurfaceControl's will not throw exceptions or return errors, + // but transactions will have no effect. + // The child surfaces will continue to follow their parent surfaces, + // and remain eligible for rendering, but their relative state will be + // frozen. We use this in the WindowManager, in app shutdown/relaunch + // scenarios, where the app would otherwise clean up its child Surfaces. + // Sometimes the WindowManager needs to extend their lifetime slightly + // in order to perform an exit animation or prevent flicker. + status_t detachChildren(); + // Set an override scaling mode as documented in <system/window.h> // the override scaling mode will take precedence over any client // specified scaling mode. -1 will clear the override scaling mode. diff --git a/include/private/gui/LayerState.h b/include/private/gui/LayerState.h index 0bcff465d0..20f51a57ce 100644 --- a/include/private/gui/LayerState.h +++ b/include/private/gui/LayerState.h @@ -24,6 +24,7 @@ #include <ui/Region.h> #include <ui/Rect.h> +#include <gui/IGraphicBufferProducer.h> namespace android { @@ -57,6 +58,7 @@ struct layer_state_t { eOverrideScalingModeChanged = 0x00000800, eGeometryAppliesWithResize = 0x00001000, eReparentChildren = 0x00002000, + eDetachChildren = 0x00004000 }; layer_state_t() @@ -95,10 +97,13 @@ struct layer_state_t { matrix22_t matrix; Rect crop; Rect finalCrop; - sp<IBinder> handle; + sp<IBinder> barrierHandle; sp<IBinder> reparentHandle; uint64_t frameNumber; int32_t overrideScalingMode; + + sp<IGraphicBufferProducer> barrierGbp; + // non POD must be last. see write/read Region transparentRegion; }; diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp index bb552aa67c..2461cba152 100644 --- a/libs/gui/LayerState.cpp +++ b/libs/gui/LayerState.cpp @@ -39,10 +39,11 @@ status_t layer_state_t::write(Parcel& output) const output.writeInplace(sizeof(layer_state_t::matrix22_t))) = matrix; output.write(crop); output.write(finalCrop); - output.writeStrongBinder(handle); + output.writeStrongBinder(barrierHandle); output.writeStrongBinder(reparentHandle); output.writeUint64(frameNumber); output.writeInt32(overrideScalingMode); + output.writeStrongBinder(IInterface::asBinder(barrierGbp)); output.write(transparentRegion); return NO_ERROR; } @@ -68,10 +69,12 @@ status_t layer_state_t::read(const Parcel& input) } input.read(crop); input.read(finalCrop); - handle = input.readStrongBinder(); + barrierHandle = input.readStrongBinder(); reparentHandle = input.readStrongBinder(); frameNumber = input.readUint64(); overrideScalingMode = input.readInt32(); + barrierGbp = + interface_cast<IGraphicBufferProducer>(input.readStrongBinder()); input.read(transparentRegion); return NO_ERROR; } diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 91e84c40ee..088933afb6 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -37,6 +37,7 @@ #include <gui/IGraphicBufferProducer.h> #include <gui/ISurfaceComposer.h> #include <gui/ISurfaceComposerClient.h> +#include <gui/Surface.h> #include <gui/SurfaceComposerClient.h> #include <private/gui/ComposerService.h> @@ -167,9 +168,14 @@ public: status_t deferTransactionUntil(const sp<SurfaceComposerClient>& client, const sp<IBinder>& id, const sp<IBinder>& handle, uint64_t frameNumber); + status_t deferTransactionUntil(const sp<SurfaceComposerClient>& client, + const sp<IBinder>& id, const sp<Surface>& barrierSurface, + uint64_t frameNumber); status_t reparentChildren(const sp<SurfaceComposerClient>& client, const sp<IBinder>& id, const sp<IBinder>& newParentHandle); + status_t detachChildren(const sp<SurfaceComposerClient>& client, + const sp<IBinder>& id); status_t setOverrideScalingMode(const sp<SurfaceComposerClient>& client, const sp<IBinder>& id, int32_t overrideScalingMode); status_t setGeometryAppliesWithResize(const sp<SurfaceComposerClient>& client, @@ -438,7 +444,21 @@ status_t Composer::deferTransactionUntil( return BAD_INDEX; } s->what |= layer_state_t::eDeferTransaction; - s->handle = handle; + s->barrierHandle = handle; + s->frameNumber = frameNumber; + return NO_ERROR; +} + +status_t Composer::deferTransactionUntil( + const sp<SurfaceComposerClient>& client, const sp<IBinder>& id, + const sp<Surface>& barrierSurface, uint64_t frameNumber) { + Mutex::Autolock lock(mLock); + layer_state_t* s = getLayerStateLocked(client, id); + if (!s) { + return BAD_INDEX; + } + s->what |= layer_state_t::eDeferTransaction; + s->barrierGbp = barrierSurface->getIGraphicBufferProducer(); s->frameNumber = frameNumber; return NO_ERROR; } @@ -457,6 +477,18 @@ status_t Composer::reparentChildren( return NO_ERROR; } +status_t Composer::detachChildren( + const sp<SurfaceComposerClient>& client, + const sp<IBinder>& id) { + Mutex::Autolock lock(mLock); + layer_state_t* s = getLayerStateLocked(client, id); + if (!s) { + return BAD_INDEX; + } + s->what |= layer_state_t::eDetachChildren; + return NO_ERROR; +} + status_t Composer::setOverrideScalingMode( const sp<SurfaceComposerClient>& client, const sp<IBinder>& id, int32_t overrideScalingMode) { @@ -776,11 +808,20 @@ status_t SurfaceComposerClient::deferTransactionUntil(const sp<IBinder>& id, return getComposer().deferTransactionUntil(this, id, handle, frameNumber); } +status_t SurfaceComposerClient::deferTransactionUntil(const sp<IBinder>& id, + const sp<Surface>& barrierSurface, uint64_t frameNumber) { + return getComposer().deferTransactionUntil(this, id, barrierSurface, frameNumber); +} + status_t SurfaceComposerClient::reparentChildren(const sp<IBinder>& id, const sp<IBinder>& newParentHandle) { return getComposer().reparentChildren(this, id, newParentHandle); } +status_t SurfaceComposerClient::detachChildren(const sp<IBinder>& id) { + return getComposer().detachChildren(this, id); +} + status_t SurfaceComposerClient::setOverrideScalingMode( const sp<IBinder>& id, int32_t overrideScalingMode) { return getComposer().setOverrideScalingMode( diff --git a/libs/gui/SurfaceControl.cpp b/libs/gui/SurfaceControl.cpp index 070a3c85d7..1e693796eb 100644 --- a/libs/gui/SurfaceControl.cpp +++ b/libs/gui/SurfaceControl.cpp @@ -170,12 +170,25 @@ status_t SurfaceControl::deferTransactionUntil(const sp<IBinder>& handle, return mClient->deferTransactionUntil(mHandle, handle, frameNumber); } +status_t SurfaceControl::deferTransactionUntil(const sp<Surface>& handle, + uint64_t frameNumber) { + status_t err = validate(); + if (err < 0) return err; + return mClient->deferTransactionUntil(mHandle, handle, frameNumber); +} + status_t SurfaceControl::reparentChildren(const sp<IBinder>& newParentHandle) { status_t err = validate(); if (err < 0) return err; return mClient->reparentChildren(mHandle, newParentHandle); } +status_t SurfaceControl::detachChildren() { + status_t err = validate(); + if (err < 0) return err; + return mClient->detachChildren(mHandle); +} + status_t SurfaceControl::setOverrideScalingMode(int32_t overrideScalingMode) { status_t err = validate(); if (err < 0) return err; diff --git a/services/surfaceflinger/Client.cpp b/services/surfaceflinger/Client.cpp index 2b4f4cb6fd..9ddae2b4dc 100644 --- a/services/surfaceflinger/Client.cpp +++ b/services/surfaceflinger/Client.cpp @@ -49,7 +49,10 @@ Client::~Client() { const size_t count = mLayers.size(); for (size_t i=0 ; i<count ; i++) { - mFlinger->removeLayer(mLayers.valueAt(i)); + sp<Layer> l = mLayers.valueAt(i).promote(); + if (l != nullptr) { + mFlinger->removeLayer(l); + } } } diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index f45f2a1458..24ebac7bca 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -1436,29 +1436,23 @@ void Layer::pushPendingState() { // If this transaction is waiting on the receipt of a frame, generate a sync // point and send it to the remote layer. - if (mCurrentState.handle != nullptr) { - sp<IBinder> strongBinder = mCurrentState.handle.promote(); - sp<Handle> handle = nullptr; - sp<Layer> handleLayer = nullptr; - if (strongBinder != nullptr) { - handle = static_cast<Handle*>(strongBinder.get()); - handleLayer = handle->owner.promote(); - } - if (strongBinder == nullptr || handleLayer == nullptr) { - ALOGE("[%s] Unable to promote Layer handle", mName.string()); + if (mCurrentState.barrierLayer != nullptr) { + sp<Layer> barrierLayer = mCurrentState.barrierLayer.promote(); + if (barrierLayer == nullptr) { + ALOGE("[%s] Unable to promote barrier Layer.", mName.string()); // If we can't promote the layer we are intended to wait on, // then it is expired or otherwise invalid. Allow this transaction // to be applied as per normal (no synchronization). - mCurrentState.handle = nullptr; + mCurrentState.barrierLayer = nullptr; } else { auto syncPoint = std::make_shared<SyncPoint>( mCurrentState.frameNumber); - if (handleLayer->addSyncPoint(syncPoint)) { + if (barrierLayer->addSyncPoint(syncPoint)) { mRemoteSyncPoints.push_back(std::move(syncPoint)); } else { // We already missed the frame we're supposed to synchronize // on, so go ahead and apply the state update - mCurrentState.handle = nullptr; + mCurrentState.barrierLayer = nullptr; } } @@ -1481,7 +1475,7 @@ void Layer::popPendingState(State* stateToCommit) { bool Layer::applyPendingStates(State* stateToCommit) { bool stateUpdateAvailable = false; while (!mPendingStates.empty()) { - if (mPendingStates[0].handle != nullptr) { + if (mPendingStates[0].barrierLayer != nullptr) { if (mRemoteSyncPoints.empty()) { // If we don't have a sync point for this, apply it anyway. It // will be visually wrong, but it should keep us from getting @@ -1828,17 +1822,24 @@ uint32_t Layer::getLayerStack() const { return p->getLayerStack(); } -void Layer::deferTransactionUntil(const sp<IBinder>& handle, +void Layer::deferTransactionUntil(const sp<Layer>& barrierLayer, uint64_t frameNumber) { - mCurrentState.handle = handle; + mCurrentState.barrierLayer = barrierLayer; mCurrentState.frameNumber = frameNumber; // We don't set eTransactionNeeded, because just receiving a deferral // request without any other state updates shouldn't actually induce a delay mCurrentState.modified = true; pushPendingState(); - mCurrentState.handle = nullptr; + mCurrentState.barrierLayer = nullptr; mCurrentState.frameNumber = 0; mCurrentState.modified = false; + ALOGE("Deferred transaction"); +} + +void Layer::deferTransactionUntil(const sp<IBinder>& barrierHandle, + uint64_t frameNumber) { + sp<Handle> handle = static_cast<Handle*>(barrierHandle.get()); + deferTransactionUntil(handle->owner.promote(), frameNumber); } void Layer::useSurfaceDamage() { @@ -2454,6 +2455,21 @@ bool Layer::reparentChildren(const sp<IBinder>& newParentHandle) { return true; } +bool Layer::detachChildren() { + traverseInZOrder([this](Layer* child) { + if (child == this) { + return; + } + + sp<Client> client(child->mClientRef.promote()); + if (client != nullptr) { + client->detachLayer(child); + } + }); + + return true; +} + void Layer::setParent(const sp<Layer>& layer) { mParent = layer; } diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index c5fea73be4..f2e5f2284d 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -128,9 +128,9 @@ public: // finalCrop is expressed in display space coordinate. Rect finalCrop; - // If set, defers this state update until the Layer identified by handle + // If set, defers this state update until the identified Layer // receives a frame with the given frameNumber - wp<IBinder> handle; + wp<Layer> barrierLayer; uint64_t frameNumber; // the transparentRegion hint is a bit special, it's latched only @@ -171,10 +171,12 @@ public: bool setLayerStack(uint32_t layerStack); bool setDataSpace(android_dataspace dataSpace); uint32_t getLayerStack() const; - void deferTransactionUntil(const sp<IBinder>& handle, uint64_t frameNumber); + void deferTransactionUntil(const sp<IBinder>& barrierHandle, uint64_t frameNumber); + void deferTransactionUntil(const sp<Layer>& barrierLayer, uint64_t frameNumber); bool setOverrideScalingMode(int32_t overrideScalingMode); void setInfo(uint32_t type, uint32_t appId); bool reparentChildren(const sp<IBinder>& layer); + bool detachChildren(); // If we have received a new buffer this frame, we will pass its surface // damage down to hardware composer. Otherwise, we must send a region with diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index e9613cce80..4acdb826e0 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -166,7 +166,7 @@ SurfaceFlinger::SurfaceFlinger() mLastTransactionTime(0), mBootFinished(false), mForceFullDamage(false), - mInterceptor(), + mInterceptor(this), mPrimaryDispSync("PrimaryDispSync"), mPrimaryHWVsyncEnabled(false), mHWVsyncAvailable(false), @@ -628,6 +628,11 @@ size_t SurfaceFlinger::getMaxViewportDims() const { bool SurfaceFlinger::authenticateSurfaceTexture( const sp<IGraphicBufferProducer>& bufferProducer) const { Mutex::Autolock _l(mStateLock); + return authenticateSurfaceTextureLocked(bufferProducer); +} + +bool SurfaceFlinger::authenticateSurfaceTextureLocked( + const sp<IGraphicBufferProducer>& bufferProducer) const { sp<IBinder> surfaceTextureBinder(IInterface::asBinder(bufferProducer)); return mGraphicBufferProducerList.indexOf(surfaceTextureBinder) >= 0; } @@ -2529,14 +2534,7 @@ status_t SurfaceFlinger::addClientLayer(const sp<Client>& client, return NO_ERROR; } -status_t SurfaceFlinger::removeLayer(const wp<Layer>& weakLayer) { - Mutex::Autolock _l(mStateLock); - sp<Layer> layer = weakLayer.promote(); - if (layer == nullptr) { - // The layer has already been removed, carry on - return NO_ERROR; - } - +status_t SurfaceFlinger::removeLayer(const sp<Layer>& layer) { const auto& p = layer->getParent(); const ssize_t index = (p != nullptr) ? p->removeChild(layer) : mCurrentState.layersSortedByZ.remove(layer); @@ -2798,7 +2796,19 @@ uint32_t SurfaceFlinger::setClientStateLocked( } } if (what & layer_state_t::eDeferTransaction) { - layer->deferTransactionUntil(s.handle, s.frameNumber); + if (s.barrierHandle != nullptr) { + layer->deferTransactionUntil(s.barrierHandle, s.frameNumber); + } else if (s.barrierGbp != nullptr) { + const sp<IGraphicBufferProducer>& gbp = s.barrierGbp; + if (authenticateSurfaceTextureLocked(gbp)) { + const auto& otherLayer = + (static_cast<MonitoredProducer*>(gbp.get()))->getLayer(); + layer->deferTransactionUntil(otherLayer, s.frameNumber); + } else { + ALOGE("Attempt to defer transaction to to an" + " unrecognized GraphicBufferProducer"); + } + } // We don't trigger a traversal here because if no other state is // changed, we don't want this to cause any more work } @@ -2807,6 +2817,9 @@ uint32_t SurfaceFlinger::setClientStateLocked( flags |= eTransactionNeeded|eTraversalNeeded; } } + if (what & layer_state_t::eDetachChildren) { + layer->detachChildren(); + } if (what & layer_state_t::eOverrideScalingModeChanged) { layer->setOverrideScalingMode(s.overrideScalingMode); // We don't trigger a traversal here because if no other state is @@ -2903,7 +2916,7 @@ status_t SurfaceFlinger::createDimLayer(const sp<Client>& client, status_t SurfaceFlinger::onLayerRemoved(const sp<Client>& client, const sp<IBinder>& handle) { - // called by the window manager when it wants to remove a Layer + // called by a client when it wants to remove a Layer status_t err = NO_ERROR; sp<Layer> l(client->getLayerUser(handle)); if (l != NULL) { @@ -2919,7 +2932,15 @@ status_t SurfaceFlinger::onLayerDestroyed(const wp<Layer>& layer) { // called by ~LayerCleaner() when all references to the IBinder (handle) // are gone - return removeLayer(layer); + sp<Layer> l = layer.promote(); + if (l == nullptr) { + // The layer has already been removed, carry on + return NO_ERROR; + } if (l->getParent() != nullptr) { + // If we have a parent, then we can continue to live as long as it does. + return NO_ERROR; + } + return removeLayer(l); } // --------------------------------------------------------------------------- diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index b4150788ca..0b3deef0e1 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -158,6 +158,9 @@ public: return *mRenderEngine; } + bool authenticateSurfaceTextureLocked( + const sp<IGraphicBufferProducer>& bufferProducer) const; + private: friend class Client; friend class DisplayEventConnection; @@ -327,7 +330,7 @@ private: status_t onLayerDestroyed(const wp<Layer>& layer); // remove a layer from SurfaceFlinger immediately - status_t removeLayer(const wp<Layer>& layer); + status_t removeLayer(const sp<Layer>& layer); // add a layer to SurfaceFlinger status_t addClientLayer(const sp<Client>& client, diff --git a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp index 6f686a634b..fe8dd0ced5 100644 --- a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp +++ b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp @@ -154,7 +154,7 @@ SurfaceFlinger::SurfaceFlinger() mLastTransactionTime(0), mBootFinished(false), mForceFullDamage(false), - mInterceptor(), + mInterceptor(this), mPrimaryDispSync("PrimaryDispSync"), mPrimaryHWVsyncEnabled(false), mHWVsyncAvailable(false), @@ -627,6 +627,11 @@ size_t SurfaceFlinger::getMaxViewportDims() const { bool SurfaceFlinger::authenticateSurfaceTexture( const sp<IGraphicBufferProducer>& bufferProducer) const { Mutex::Autolock _l(mStateLock); + return authenticateSurfaceTextureLocked(bufferProducer); +} + +bool SurfaceFlinger::authenticateSurfaceTextureLocked( + const sp<IGraphicBufferProducer>& bufferProducer) const { sp<IBinder> surfaceTextureBinder(IInterface::asBinder(bufferProducer)); return mGraphicBufferProducerList.indexOf(surfaceTextureBinder) >= 0; } @@ -2312,14 +2317,7 @@ status_t SurfaceFlinger::addClientLayer(const sp<Client>& client, return NO_ERROR; } -status_t SurfaceFlinger::removeLayer(const wp<Layer>& weakLayer) { - Mutex::Autolock _l(mStateLock); - sp<Layer> layer = weakLayer.promote(); - if (layer == nullptr) { - // The layer has already been removed, carry on - return NO_ERROR; - } - +status_t SurfaceFlinger::removeLayer(const sp<Layer>& layer) { const auto& p = layer->getParent(); const ssize_t index = (p != nullptr) ? p->removeChild(layer) : mCurrentState.layersSortedByZ.remove(layer); @@ -2581,7 +2579,19 @@ uint32_t SurfaceFlinger::setClientStateLocked( } } if (what & layer_state_t::eDeferTransaction) { - layer->deferTransactionUntil(s.handle, s.frameNumber); + if (s.barrierHandle != nullptr) { + layer->deferTransactionUntil(s.barrierHandle, s.frameNumber); + } else if (s.barrierGbp != nullptr) { + const sp<IGraphicBufferProducer>& gbp = s.barrierGbp; + if (authenticateSurfaceTextureLocked(gbp)) { + const auto& otherLayer = + (static_cast<MonitoredProducer*>(gbp.get()))->getLayer(); + layer->deferTransactionUntil(otherLayer, s.frameNumber); + } else { + ALOGE("Attempt to defer transaction to to an" + " unrecognized GraphicBufferProducer"); + } + } // We don't trigger a traversal here because if no other state is // changed, we don't want this to cause any more work } @@ -2590,6 +2600,9 @@ uint32_t SurfaceFlinger::setClientStateLocked( flags |= eTransactionNeeded|eTraversalNeeded; } } + if (what & layer_state_t::eDetachChildren) { + layer->detachChildren(); + } if (what & layer_state_t::eOverrideScalingModeChanged) { layer->setOverrideScalingMode(s.overrideScalingMode); // We don't trigger a traversal here because if no other state is @@ -2686,7 +2699,7 @@ status_t SurfaceFlinger::createDimLayer(const sp<Client>& client, status_t SurfaceFlinger::onLayerRemoved(const sp<Client>& client, const sp<IBinder>& handle) { - // called by the window manager when it wants to remove a Layer + // called by a client when it wants to remove a Layer status_t err = NO_ERROR; sp<Layer> l(client->getLayerUser(handle)); if (l != NULL) { @@ -2702,7 +2715,15 @@ status_t SurfaceFlinger::onLayerDestroyed(const wp<Layer>& layer) { // called by ~LayerCleaner() when all references to the IBinder (handle) // are gone - return removeLayer(layer); + sp<Layer> l = layer.promote(); + if (l == nullptr) { + // The layer has already been removed, carry on + return NO_ERROR; + } if (l->getParent() != nullptr) { + // If we have a parent, then we can continue to live as long as it does. + return NO_ERROR; + } + return removeLayer(l); } // --------------------------------------------------------------------------- diff --git a/services/surfaceflinger/SurfaceInterceptor.cpp b/services/surfaceflinger/SurfaceInterceptor.cpp index 2d6472a8ef..026fe803c0 100644 --- a/services/surfaceflinger/SurfaceInterceptor.cpp +++ b/services/surfaceflinger/SurfaceInterceptor.cpp @@ -31,6 +31,11 @@ namespace android { // ---------------------------------------------------------------------------- +SurfaceInterceptor::SurfaceInterceptor(SurfaceFlinger* flinger) + : mFlinger(flinger) +{ +} + void SurfaceInterceptor::enable(const SortedVector<sp<Layer>>& layers, const DefaultKeyedVector< wp<IBinder>, DisplayDeviceState>& displays) { @@ -97,8 +102,8 @@ void SurfaceInterceptor::addInitialSurfaceStateLocked(Increment* increment, addTransparentRegionLocked(transaction, layerId, layer->mCurrentState.activeTransparentRegion); addLayerStackLocked(transaction, layerId, layer->mCurrentState.layerStack); addCropLocked(transaction, layerId, layer->mCurrentState.crop); - if (layer->mCurrentState.handle != nullptr) { - addDeferTransactionLocked(transaction, layerId, layer->mCurrentState.handle, + if (layer->mCurrentState.barrierLayer != nullptr) { + addDeferTransactionLocked(transaction, layerId, layer->mCurrentState.barrierLayer.promote(), layer->mCurrentState.frameNumber); } addFinalCropLocked(transaction, layerId, layer->mCurrentState.finalCrop); @@ -287,10 +292,9 @@ void SurfaceInterceptor::addFinalCropLocked(Transaction* transaction, int32_t la } void SurfaceInterceptor::addDeferTransactionLocked(Transaction* transaction, int32_t layerId, - const wp<const IBinder>& weakHandle, uint64_t frameNumber) + const sp<const Layer>& layer, uint64_t frameNumber) { SurfaceChange* change(createSurfaceChangeLocked(transaction, layerId)); - const sp<const Layer> layer(getLayer(weakHandle)); if (layer == nullptr) { ALOGE("An existing layer could not be retrieved with the handle" " for the deferred transaction"); @@ -349,7 +353,18 @@ void SurfaceInterceptor::addSurfaceChangesLocked(Transaction* transaction, addCropLocked(transaction, layerId, state.crop); } if (state.what & layer_state_t::eDeferTransaction) { - addDeferTransactionLocked(transaction, layerId, state.handle, state.frameNumber); + sp<Layer> otherLayer = nullptr; + if (state.barrierHandle != nullptr) { + otherLayer = static_cast<Layer::Handle*>(state.barrierHandle.get())->owner.promote(); + } else if (state.barrierGbp != nullptr) { + auto const& gbp = state.barrierGbp; + if (mFlinger->authenticateSurfaceTextureLocked(gbp)) { + otherLayer = (static_cast<MonitoredProducer*>(gbp.get()))->getLayer(); + } else { + ALOGE("Attempt to defer transaction to to an unrecognized GraphicBufferProducer"); + } + } + addDeferTransactionLocked(transaction, layerId, otherLayer, state.frameNumber); } if (state.what & layer_state_t::eFinalCropChanged) { addFinalCropLocked(transaction, layerId, state.finalCrop); diff --git a/services/surfaceflinger/SurfaceInterceptor.h b/services/surfaceflinger/SurfaceInterceptor.h index 9af6e612ec..30ebcc6a1c 100644 --- a/services/surfaceflinger/SurfaceInterceptor.h +++ b/services/surfaceflinger/SurfaceInterceptor.h @@ -28,6 +28,7 @@ namespace android { class BufferItem; class Layer; +class SurfaceFlinger; struct DisplayState; struct layer_state_t; @@ -39,6 +40,7 @@ constexpr auto DEFAULT_FILENAME = "/data/SurfaceTrace.dat"; */ class SurfaceInterceptor { public: + SurfaceInterceptor(SurfaceFlinger* const flinger); // Both vectors are used to capture the current state of SF as the initial snapshot in the trace void enable(const SortedVector<sp<Layer>>& layers, const DefaultKeyedVector< wp<IBinder>, DisplayDeviceState>& displays); @@ -102,7 +104,7 @@ private: void addLayerStackLocked(Transaction* transaction, int32_t layerId, uint32_t layerStack); void addCropLocked(Transaction* transaction, int32_t layerId, const Rect& rect); void addDeferTransactionLocked(Transaction* transaction, int32_t layerId, - const wp<const IBinder>& weakHandle, uint64_t frameNumber); + const sp<const Layer>& layer, uint64_t frameNumber); void addFinalCropLocked(Transaction* transaction, int32_t layerId, const Rect& rect); void addOverrideScalingModeLocked(Transaction* transaction, int32_t layerId, int32_t overrideScalingMode); @@ -129,6 +131,7 @@ private: std::string mOutputFileName {DEFAULT_FILENAME}; std::mutex mTraceMutex {}; Trace mTrace {}; + SurfaceFlinger* const mFlinger; }; } diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp index 8bbb9744f7..aeb557aad3 100644 --- a/services/surfaceflinger/tests/Transaction_test.cpp +++ b/services/surfaceflinger/tests/Transaction_test.cpp @@ -628,4 +628,68 @@ TEST_F(ChildLayerTest, ChildLayerScaling) { mCapture->expectFGColor(20, 20); } } + +TEST_F(ChildLayerTest, ReparentChildren) { + SurfaceComposerClient::openGlobalTransaction(); + mChild->show(); + mChild->setPosition(10, 10); + mFGSurfaceControl->setPosition(64, 64); + SurfaceComposerClient::closeGlobalTransaction(true); + + { + ScreenCapture::captureScreen(&mCapture); + // Top left of foreground must now be visible + mCapture->expectFGColor(64, 64); + // But 10 pixels in we should see the child surface + mCapture->expectChildColor(74, 74); + // And 10 more pixels we should be back to the foreground surface + mCapture->expectFGColor(84, 84); + } + mFGSurfaceControl->reparentChildren(mBGSurfaceControl->getHandle()); + { + ScreenCapture::captureScreen(&mCapture); + mCapture->expectFGColor(64, 64); + // In reparenting we should have exposed the entire foreground surface. + mCapture->expectFGColor(74, 74); + // And the child layer should now begin at 10, 10 (since the BG + // layer is at (0, 0)). + mCapture->expectBGColor(9, 9); + mCapture->expectChildColor(10, 10); + } +} + +TEST_F(ChildLayerTest, DetachChildren) { + SurfaceComposerClient::openGlobalTransaction(); + mChild->show(); + mChild->setPosition(10, 10); + mFGSurfaceControl->setPosition(64, 64); + SurfaceComposerClient::closeGlobalTransaction(true); + + { + ScreenCapture::captureScreen(&mCapture); + // Top left of foreground must now be visible + mCapture->expectFGColor(64, 64); + // But 10 pixels in we should see the child surface + mCapture->expectChildColor(74, 74); + // And 10 more pixels we should be back to the foreground surface + mCapture->expectFGColor(84, 84); + } + + SurfaceComposerClient::openGlobalTransaction(); + mFGSurfaceControl->detachChildren(); + SurfaceComposerClient::closeGlobalTransaction(); + + SurfaceComposerClient::openGlobalTransaction(); + mChild->hide(); + SurfaceComposerClient::closeGlobalTransaction(); + + // Nothing should have changed. + { + ScreenCapture::captureScreen(&mCapture); + mCapture->expectFGColor(64, 64); + mCapture->expectChildColor(74, 74); + mCapture->expectFGColor(84, 84); + } +} + } |