From de84eb6b823ff143f3465ce8f291f1100ce42168 Mon Sep 17 00:00:00 2001 From: Dan Stoza Date: Tue, 9 Aug 2016 13:21:03 -0700 Subject: SF: Fix a couple of Layer ref count issues This is an attempt at fixing two reference counting issues for Layers. The first issue is that since we were holding an sp (really a reference to a LayerCleaner) inside the layer state for deferred transactions, there was a possibility that it could end up being the last strong reference to the LayerCleaner such that when it was destroyed while applying a non-deferred transaction, it would attempt to grab the SurfaceFlinger main lock to destroy its Layer. Since this occurred in the main SurfaceFlinger loop, which was already holding the lock to process transactions, this would cause a deadlock. To fix this, the sp inside the layer state was changed to a wp, only being promoted when it actually needs to be accessed (i.e., when the deferred transaction is created). The second issue is that we were promoting and holding a strong reference to a Layer before calling into SurfaceFlinger to destroy it on the onLayerDestroyed path (triggered when a LayerCleaner is destroyed). After returning from the attempt to grab the SurfaceFlinger main lock, it was possible that this strong reference was the last one keeping the Layer alive, and destroying it at this point could cause the HWC2 version of the layer to be destroyed at effectively any point, even between validate/present. To fix this, the promotion of the weak Layer reference was moved inside the critical section where the SurfaceFlinger main lock is held. Test: Cherry-pick from internal branch Bug: 30503916 Bug: 30281222 Change-Id: I1c6a271f9a7b5d6eea9a9db61d971f262d0cfe84 --- services/surfaceflinger/Layer.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index a512acc1c9..9173165d0c 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -1289,9 +1289,14 @@ 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 handle = static_cast(mCurrentState.handle.get()); - sp handleLayer = handle->owner.promote(); - if (handleLayer == nullptr) { + sp strongBinder = mCurrentState.handle.promote(); + sp handle = nullptr; + sp handleLayer = nullptr; + if (strongBinder != nullptr) { + handle = static_cast(strongBinder.get()); + handleLayer = handle->owner.promote(); + } + if (strongBinder == nullptr || handleLayer == nullptr) { ALOGE("[%s] Unable to promote Layer handle", 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 -- cgit v1.2.3-59-g8ed1b