diff options
-rw-r--r-- | include/gui/BufferQueueCore.h | 6 | ||||
-rw-r--r-- | include/gui/IProducerListener.h | 3 | ||||
-rw-r--r-- | libs/gui/BufferQueueCore.cpp | 1 | ||||
-rw-r--r-- | libs/gui/BufferQueueProducer.cpp | 29 | ||||
-rw-r--r-- | libs/gui/IProducerListener.cpp | 26 |
5 files changed, 52 insertions, 13 deletions
diff --git a/include/gui/BufferQueueCore.h b/include/gui/BufferQueueCore.h index cc5c536d13..1226feb59a 100644 --- a/include/gui/BufferQueueCore.h +++ b/include/gui/BufferQueueCore.h @@ -185,8 +185,12 @@ private: // PID of the process which last successfully called connect(...) pid_t mConnectedPid; - // mConnectedProducerToken is used to set a binder death notification on + // mLinkedToDeath is used to set a binder death notification on // the producer. + sp<IProducerListener> mLinkedToDeath; + + // mConnectedProducerListener is used to handle the onBufferReleased + // notification. sp<IProducerListener> mConnectedProducerListener; // mSlots is an array of buffer slots that must be mirrored on the producer diff --git a/include/gui/IProducerListener.h b/include/gui/IProducerListener.h index 3848a6c850..b7826c677f 100644 --- a/include/gui/IProducerListener.h +++ b/include/gui/IProducerListener.h @@ -41,6 +41,7 @@ public: // This is called without any lock held and can be called concurrently by // multiple threads. virtual void onBufferReleased() = 0; // Asynchronous + virtual bool needsReleaseNotify() = 0; }; class IProducerListener : public ProducerListener, public IInterface @@ -54,12 +55,14 @@ class BnProducerListener : public BnInterface<IProducerListener> public: virtual status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0); + virtual bool needsReleaseNotify(); }; class DummyProducerListener : public BnProducerListener { public: virtual void onBufferReleased() {} + virtual bool needsReleaseNotify() { return false; } }; } // namespace android diff --git a/libs/gui/BufferQueueCore.cpp b/libs/gui/BufferQueueCore.cpp index 9cb9c62401..fd85c43b6d 100644 --- a/libs/gui/BufferQueueCore.cpp +++ b/libs/gui/BufferQueueCore.cpp @@ -59,6 +59,7 @@ BufferQueueCore::BufferQueueCore(const sp<IGraphicBufferAlloc>& allocator) : mConsumerListener(), mConsumerUsageBits(0), mConnectedApi(NO_CONNECTED_API), + mLinkedToDeath(), mConnectedProducerListener(), mSlots(), mQueue(), diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp index 48b1db8f59..7020214238 100644 --- a/libs/gui/BufferQueueProducer.cpp +++ b/libs/gui/BufferQueueProducer.cpp @@ -1113,18 +1113,22 @@ status_t BufferQueueProducer::connect(const sp<IProducerListener>& listener, static_cast<uint32_t>(mCore->mQueue.size()), mCore->mFrameCounter + 1); - // Set up a death notification so that we can disconnect - // automatically if the remote producer dies - if (listener != NULL && - IInterface::asBinder(listener)->remoteBinder() != NULL) { - status = IInterface::asBinder(listener)->linkToDeath( - static_cast<IBinder::DeathRecipient*>(this)); - if (status != NO_ERROR) { - BQ_LOGE("connect: linkToDeath failed: %s (%d)", - strerror(-status), status); + if (listener != NULL) { + // Set up a death notification so that we can disconnect + // automatically if the remote producer dies + if (IInterface::asBinder(listener)->remoteBinder() != NULL) { + status = IInterface::asBinder(listener)->linkToDeath( + static_cast<IBinder::DeathRecipient*>(this)); + if (status != NO_ERROR) { + BQ_LOGE("connect: linkToDeath failed: %s (%d)", + strerror(-status), status); + } + mCore->mLinkedToDeath = listener; + } + if (listener->needsReleaseNotify()) { + mCore->mConnectedProducerListener = listener; } } - mCore->mConnectedProducerListener = listener; break; default: BQ_LOGE("connect: unknown API %d", api); @@ -1186,9 +1190,9 @@ status_t BufferQueueProducer::disconnect(int api, DisconnectMode mode) { mCore->freeAllBuffersLocked(); // Remove our death notification callback if we have one - if (mCore->mConnectedProducerListener != NULL) { + if (mCore->mLinkedToDeath != NULL) { sp<IBinder> token = - IInterface::asBinder(mCore->mConnectedProducerListener); + IInterface::asBinder(mCore->mLinkedToDeath); // This can fail if we're here because of the death // notification, but we just ignore it token->unlinkToDeath( @@ -1196,6 +1200,7 @@ status_t BufferQueueProducer::disconnect(int api, DisconnectMode mode) { } mCore->mSharedBufferSlot = BufferQueueCore::INVALID_BUFFER_SLOT; + mCore->mLinkedToDeath = NULL; mCore->mConnectedProducerListener = NULL; mCore->mConnectedApi = BufferQueueCore::NO_CONNECTED_API; mCore->mConnectedPid = -1; diff --git a/libs/gui/IProducerListener.cpp b/libs/gui/IProducerListener.cpp index 81adc95449..da54ce1c2b 100644 --- a/libs/gui/IProducerListener.cpp +++ b/libs/gui/IProducerListener.cpp @@ -22,6 +22,7 @@ namespace android { enum { ON_BUFFER_RELEASED = IBinder::FIRST_CALL_TRANSACTION, + NEEDS_RELEASE_NOTIFY, }; class BpProducerListener : public BpInterface<IProducerListener> @@ -37,6 +38,23 @@ public: data.writeInterfaceToken(IProducerListener::getInterfaceDescriptor()); remote()->transact(ON_BUFFER_RELEASED, data, &reply, IBinder::FLAG_ONEWAY); } + + virtual bool needsReleaseNotify() { + bool result; + Parcel data, reply; + data.writeInterfaceToken(IProducerListener::getInterfaceDescriptor()); + status_t err = remote()->transact(NEEDS_RELEASE_NOTIFY, data, &reply); + if (err != NO_ERROR) { + ALOGE("IProducerListener: binder call \'needsReleaseNotify\' failed"); + return true; + } + err = reply.readBool(&result); + if (err != NO_ERROR) { + ALOGE("IProducerListener: malformed binder reply"); + return true; + } + return result; + } }; // Out-of-line virtual method definition to trigger vtable emission in this @@ -52,8 +70,16 @@ status_t BnProducerListener::onTransact(uint32_t code, const Parcel& data, CHECK_INTERFACE(IProducerListener, data, reply); onBufferReleased(); return NO_ERROR; + case NEEDS_RELEASE_NOTIFY: + CHECK_INTERFACE(IProducerListener, data, reply); + reply->writeBool(needsReleaseNotify()); + return NO_ERROR; } return BBinder::onTransact(code, data, reply, flags); } +bool BnProducerListener::needsReleaseNotify() { + return true; +} + } // namespace android |