diff options
author | Mathias Agopian <mathias@google.com> | 2013-09-17 14:33:09 -0700 |
---|---|---|
committer | Android Git Automerger <android-git-automerger@android.com> | 2013-09-17 14:33:09 -0700 |
commit | 3f342c113360eacc1e9c1ff481cb03f700a50117 (patch) | |
tree | 90c9213b924a5f2bcf053f4cab9f43ecd9599c80 /libs/gui | |
parent | 30480ac9f9cb102095e6bfec2226b48e5d1f4060 (diff) | |
parent | 02b62df7119b27c89d91d96938d8f4f5232b296b (diff) | |
download | frameworks_native-3f342c113360eacc1e9c1ff481cb03f700a50117.zip frameworks_native-3f342c113360eacc1e9c1ff481cb03f700a50117.tar.gz frameworks_native-3f342c113360eacc1e9c1ff481cb03f700a50117.tar.bz2 |
am 02b62df7: Merge "Make sure do disconnect from a BQ when its client dies." into klp-dev
* commit '02b62df7119b27c89d91d96938d8f4f5232b296b':
Make sure do disconnect from a BQ when its client dies.
Diffstat (limited to 'libs/gui')
-rw-r--r-- | libs/gui/BufferQueue.cpp | 32 | ||||
-rw-r--r-- | libs/gui/IGraphicBufferProducer.cpp | 8 | ||||
-rw-r--r-- | libs/gui/Surface.cpp | 4 |
3 files changed, 37 insertions, 7 deletions
diff --git a/libs/gui/BufferQueue.cpp b/libs/gui/BufferQueue.cpp index 57a41f2..50e3079 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; diff --git a/libs/gui/IGraphicBufferProducer.cpp b/libs/gui/IGraphicBufferProducer.cpp index 704fa50..0f461e5 100644 --- a/libs/gui/IGraphicBufferProducer.cpp +++ b/libs/gui/IGraphicBufferProducer.cpp @@ -41,7 +41,6 @@ enum { DISCONNECT, }; - class BpGraphicBufferProducer : public BpInterface<IGraphicBufferProducer> { public: @@ -143,9 +142,11 @@ public: return result; } - virtual status_t connect(int api, bool producerControlledByApp, QueueBufferOutput* output) { + virtual status_t connect(const sp<IBinder>& token, + int api, bool producerControlledByApp, QueueBufferOutput* output) { Parcel data, reply; data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor()); + data.writeStrongBinder(token); data.writeInt32(api); data.writeInt32(producerControlledByApp); status_t result = remote()->transact(CONNECT, data, &reply); @@ -245,12 +246,13 @@ status_t BnGraphicBufferProducer::onTransact( } break; case CONNECT: { CHECK_INTERFACE(IGraphicBufferProducer, data, reply); + sp<IBinder> token = data.readStrongBinder(); int api = data.readInt32(); bool producerControlledByApp = data.readInt32(); QueueBufferOutput* const output = reinterpret_cast<QueueBufferOutput *>( reply->writeInplace(sizeof(QueueBufferOutput))); - status_t res = connect(api, producerControlledByApp, output); + status_t res = connect(token, api, producerControlledByApp, output); reply->writeInt32(res); return NO_ERROR; } break; diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp index 1bae0fe..27dbc4e 100644 --- a/libs/gui/Surface.cpp +++ b/libs/gui/Surface.cpp @@ -490,9 +490,10 @@ int Surface::dispatchUnlockAndPost(va_list args) { int Surface::connect(int api) { ATRACE_CALL(); ALOGV("Surface::connect"); + static sp<BBinder> sLife = new BBinder(); Mutex::Autolock lock(mMutex); IGraphicBufferProducer::QueueBufferOutput output; - int err = mGraphicBufferProducer->connect(api, mProducerControlledByApp, &output); + int err = mGraphicBufferProducer->connect(sLife, api, mProducerControlledByApp, &output); if (err == NO_ERROR) { uint32_t numPendingBuffers = 0; output.deflate(&mDefaultWidth, &mDefaultHeight, &mTransformHint, @@ -505,6 +506,7 @@ int Surface::connect(int api) { return err; } + int Surface::disconnect(int api) { ATRACE_CALL(); ALOGV("Surface::disconnect"); |