diff options
| -rw-r--r-- | libs/gui/LayerState.cpp | 3 | ||||
| -rw-r--r-- | libs/gui/SurfaceComposerClient.cpp | 11 | ||||
| -rw-r--r-- | libs/gui/include/gui/LayerState.h | 3 | ||||
| -rw-r--r-- | libs/gui/include/gui/SurfaceComposerClient.h | 2 | ||||
| -rw-r--r-- | services/surfaceflinger/SurfaceFlinger.cpp | 96 | ||||
| -rw-r--r-- | services/surfaceflinger/SurfaceFlinger.h | 5 |
6 files changed, 89 insertions, 31 deletions
diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp index b5295f2801..01acc2de20 100644 --- a/libs/gui/LayerState.cpp +++ b/libs/gui/LayerState.cpp @@ -231,6 +231,9 @@ void layer_state_t::merge(const layer_state_t& other) { what |= eReparent; parentHandleForChild = other.parentHandleForChild; } + if (other.what & eDestroySurface) { + what |= eDestroySurface; + } } }; // namespace android diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index c40cad3e99..0722038c5b 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -472,6 +472,17 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setGeome return *this; } +SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::destroySurface( + const sp<SurfaceControl>& sc) { + layer_state_t* s = getLayerStateLocked(sc); + if (!s) { + mStatus = BAD_INDEX; + return *this; + } + s->what |= layer_state_t::eDestroySurface; + return *this; +} + // --------------------------------------------------------------------------- DisplayState& SurfaceComposerClient::Transaction::getDisplayStateLocked(const sp<IBinder>& token) { diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h index f3fb82feb3..788962e490 100644 --- a/libs/gui/include/gui/LayerState.h +++ b/libs/gui/include/gui/LayerState.h @@ -62,7 +62,8 @@ struct layer_state_t { eDetachChildren = 0x00004000, eRelativeLayerChanged = 0x00008000, eReparent = 0x00010000, - eColorChanged = 0x00020000 + eColorChanged = 0x00020000, + eDestroySurface = 0x00040000 }; layer_state_t() diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 55b96ac93d..10caa76281 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -229,6 +229,8 @@ public: // freezing the total geometry of a surface until a resize is completed. Transaction& setGeometryAppliesWithResize(const sp<SurfaceControl>& sc); + Transaction& destroySurface(const sp<SurfaceControl>& sc); + status_t setDisplaySurface(const sp<IBinder>& token, const sp<IGraphicBufferProducer>& bufferProducer); diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 03f6bdc583..135bfbefa9 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -2901,7 +2901,11 @@ status_t SurfaceFlinger::addClientLayer(const sp<Client>& client, status_t SurfaceFlinger::removeLayer(const sp<Layer>& layer, bool topLevelOnly) { Mutex::Autolock _l(mStateLock); + return removeLayerLocked(mStateLock, layer, topLevelOnly); +} +status_t SurfaceFlinger::removeLayerLocked(const Mutex&, const sp<Layer>& layer, + bool topLevelOnly) { if (layer->isPendingRemoval()) { return NO_ERROR; } @@ -2965,8 +2969,30 @@ uint32_t SurfaceFlinger::setTransactionFlags(uint32_t flags) { return old; } +bool SurfaceFlinger::containsAnyInvalidClientState(const Vector<ComposerState>& states) { + for (const ComposerState& state : states) { + // Here we need to check that the interface we're given is indeed + // one of our own. A malicious client could give us a nullptr + // IInterface, or one of its own or even one of our own but a + // different type. All these situations would cause us to crash. + if (state.client == nullptr) { + return true; + } + + sp<IBinder> binder = IInterface::asBinder(state.client); + if (binder == nullptr) { + return true; + } + + if (binder->queryLocalInterface(ISurfaceComposerClient::descriptor) == nullptr) { + return true; + } + } + return false; +} + void SurfaceFlinger::setTransactionState( - const Vector<ComposerState>& state, + const Vector<ComposerState>& states, const Vector<DisplayState>& displays, uint32_t flags) { @@ -2974,6 +3000,10 @@ void SurfaceFlinger::setTransactionState( Mutex::Autolock _l(mStateLock); uint32_t transactionFlags = 0; + if (containsAnyInvalidClientState(states)) { + return; + } + if (flags & eAnimation) { // For window updates that are part of an animation we must wait for // previous animation "frames" to be handled. @@ -2990,31 +3020,20 @@ void SurfaceFlinger::setTransactionState( } } - size_t count = displays.size(); - for (size_t i=0 ; i<count ; i++) { - const DisplayState& s(displays[i]); - transactionFlags |= setDisplayStateLocked(s); + for (const DisplayState& display : displays) { + transactionFlags |= setDisplayStateLocked(display); } - count = state.size(); - for (size_t i=0 ; i<count ; i++) { - const ComposerState& s(state[i]); - // Here we need to check that the interface we're given is indeed - // one of our own. A malicious client could give us a nullptr - // IInterface, or one of its own or even one of our own but a - // different type. All these situations would cause us to crash. - // - // NOTE: it would be better to use RTTI as we could directly check - // that we have a Client*. however, RTTI is disabled in Android. - if (s.client != nullptr) { - sp<IBinder> binder = IInterface::asBinder(s.client); - if (binder != nullptr) { - if (binder->queryLocalInterface(ISurfaceComposerClient::descriptor) != nullptr) { - sp<Client> client( static_cast<Client *>(s.client.get()) ); - transactionFlags |= setClientStateLocked(client, s.state); - } - } - } + for (const ComposerState& state : states) { + transactionFlags |= setClientStateLocked(state); + } + + // Iterate through all layers again to determine if any need to be destroyed. Marking layers + // as destroyed should only occur after setting all other states. This is to allow for a + // child re-parent to happen before marking its original parent as destroyed (which would + // then mark the child as destroyed). + for (const ComposerState& state : states) { + setDestroyStateLocked(state); } // If a synchronous transaction is explicitly requested without any changes, force a transaction @@ -3028,7 +3047,7 @@ void SurfaceFlinger::setTransactionState( if (transactionFlags) { if (mInterceptor.isEnabled()) { - mInterceptor.saveTransaction(state, mCurrentState.displays, displays, flags); + mInterceptor.saveTransaction(states, mCurrentState.displays, displays, flags); } // this triggers the transaction @@ -3105,10 +3124,10 @@ uint32_t SurfaceFlinger::setDisplayStateLocked(const DisplayState& s) return flags; } -uint32_t SurfaceFlinger::setClientStateLocked( - const sp<Client>& client, - const layer_state_t& s) -{ +uint32_t SurfaceFlinger::setClientStateLocked(const ComposerState& composerState) { + const layer_state_t& s = composerState.state; + sp<Client> client(static_cast<Client*>(composerState.client.get())); + sp<Layer> layer(client->getLayerUser(s.surface)); if (layer == nullptr) { return 0; @@ -3259,6 +3278,25 @@ uint32_t SurfaceFlinger::setClientStateLocked( return flags; } +void SurfaceFlinger::setDestroyStateLocked(const ComposerState& composerState) { + const layer_state_t& state = composerState.state; + sp<Client> client(static_cast<Client*>(composerState.client.get())); + + sp<Layer> layer(client->getLayerUser(state.surface)); + if (layer == nullptr) { + return; + } + + if (layer->isPendingRemoval()) { + ALOGW("Attempting to destroy on removed layer: %s", layer->getName().string()); + return; + } + + if (state.what & layer_state_t::eDestroySurface) { + removeLayerLocked(mStateLock, layer); + } +} + status_t SurfaceFlinger::createLayer( const String8& name, const sp<Client>& client, diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index b7ebb1bcf3..08c4a5e3b1 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -473,8 +473,10 @@ private: // Can only be called from the main thread or with mStateLock held uint32_t setTransactionFlags(uint32_t flags); void commitTransaction(); - uint32_t setClientStateLocked(const sp<Client>& client, const layer_state_t& s); + bool containsAnyInvalidClientState(const Vector<ComposerState>& states); + uint32_t setClientStateLocked(const ComposerState& composerState); uint32_t setDisplayStateLocked(const DisplayState& s); + void setDestroyStateLocked(const ComposerState& composerState); /* ------------------------------------------------------------------------ * Layer management @@ -506,6 +508,7 @@ private: // remove a layer from SurfaceFlinger immediately status_t removeLayer(const sp<Layer>& layer, bool topLevelOnly = false); + status_t removeLayerLocked(const Mutex&, const sp<Layer>& layer, bool topLevelOnly = false); // add a layer to SurfaceFlinger status_t addClientLayer(const sp<Client>& client, |