diff options
author | 2013-09-17 21:31:13 +0000 | |
---|---|---|
committer | 2013-09-17 21:31:14 +0000 | |
commit | 02b62df7119b27c89d91d96938d8f4f5232b296b (patch) | |
tree | 0ad1b98a6e21f05e571e37da588dc82bad297fdc /libs/gui/BufferQueue.cpp | |
parent | fca43392b755b34c83c3abbfea216bafa9cd8171 (diff) | |
parent | 365857df8b94c959dea984a63013f6e7730ef976 (diff) |
Merge "Make sure do disconnect from a BQ when its client dies." into klp-dev
Diffstat (limited to 'libs/gui/BufferQueue.cpp')
-rw-r--r-- | libs/gui/BufferQueue.cpp | 32 |
1 files changed, 29 insertions, 3 deletions
diff --git a/libs/gui/BufferQueue.cpp b/libs/gui/BufferQueue.cpp index 57a41f25c4..50e3079267 100644 --- a/libs/gui/BufferQueue.cpp +++ b/libs/gui/BufferQueue.cpp @@ -635,7 +635,9 @@ void BufferQueue::cancelBuffer(int buf, const sp<Fence>& fence) { mDequeueCondition.broadcast(); } -status_t BufferQueue::connect(int api, bool producerControlledByApp, QueueBufferOutput* output) { + +status_t BufferQueue::connect(const sp<IBinder>& token, + int api, bool producerControlledByApp, QueueBufferOutput* output) { ATRACE_CALL(); ST_LOGV("connect: api=%d producerControlledByApp=%s", api, producerControlledByApp ? "true" : "false"); @@ -663,8 +665,14 @@ status_t BufferQueue::connect(int api, bool producerControlledByApp, QueueBuffer err = -EINVAL; } else { mConnectedApi = api; - output->inflate(mDefaultWidth, mDefaultHeight, mTransformHint, - mQueue.size()); + output->inflate(mDefaultWidth, mDefaultHeight, mTransformHint, mQueue.size()); + + // set-up a death notification so that we can disconnect automatically + // when/if the remote producer dies. + // This will fail with INVALID_OPERATION if the "token" is local to our process. + if (token->linkToDeath(static_cast<IBinder::DeathRecipient*>(this)) == NO_ERROR) { + mConnectedProducerToken = token; + } } break; default: @@ -678,6 +686,16 @@ status_t BufferQueue::connect(int api, bool producerControlledByApp, QueueBuffer return err; } +void BufferQueue::binderDied(const wp<IBinder>& who) { + // If we're here, it means that a producer we were connected to died. + // We're GUARANTEED that we still are connected to it because it has no other way + // to get disconnected -- or -- we wouldn't be here because we're removing this + // callback upon disconnect. Therefore, it's okay to read mConnectedApi without + // synchronization here. + int api = mConnectedApi; + this->disconnect(api); +} + status_t BufferQueue::disconnect(int api) { ATRACE_CALL(); ST_LOGV("disconnect: api=%d", api); @@ -701,6 +719,14 @@ status_t BufferQueue::disconnect(int api) { case NATIVE_WINDOW_API_CAMERA: if (mConnectedApi == api) { freeAllBuffersLocked(); + // remove our death notification callback if we have one + sp<IBinder> token = mConnectedProducerToken; + if (token != NULL) { + // this can fail if we're here because of the death notification + // either way, we just ignore. + token->unlinkToDeath(static_cast<IBinder::DeathRecipient*>(this)); + } + mConnectedProducerToken = NULL; mConnectedApi = NO_CONNECTED_API; mDequeueCondition.broadcast(); listener = mConsumerListener; |