Merge "Added tests for DumpFile."
diff --git a/include/gui/BufferQueueCore.h b/include/gui/BufferQueueCore.h
index 15b7dbe..b1c730a 100644
--- a/include/gui/BufferQueueCore.h
+++ b/include/gui/BufferQueueCore.h
@@ -185,8 +185,12 @@
     // 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 4a5ed46..e808bd3 100644
--- a/include/gui/IProducerListener.h
+++ b/include/gui/IProducerListener.h
@@ -41,6 +41,7 @@
     // 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,6 +55,7 @@
 public:
     virtual status_t onTransact(uint32_t code, const Parcel& data,
             Parcel* reply, uint32_t flags = 0);
+    virtual bool needsReleaseNotify();
 };
 
 class DummyProducerListener : public BnProducerListener
@@ -61,6 +63,7 @@
 public:
     virtual ~DummyProducerListener();
     virtual void onBufferReleased() {}
+    virtual bool needsReleaseNotify() { return false; }
 };
 
 } // namespace android
diff --git a/libs/gui/BufferQueueCore.cpp b/libs/gui/BufferQueueCore.cpp
index 13f4e1c..6e6cce2 100644
--- a/libs/gui/BufferQueueCore.cpp
+++ b/libs/gui/BufferQueueCore.cpp
@@ -62,6 +62,7 @@
     mConsumerListener(),
     mConsumerUsageBits(0),
     mConnectedApi(NO_CONNECTED_API),
+    mLinkedToDeath(),
     mConnectedProducerListener(),
     mSlots(),
     mQueue(),
diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp
index 13166f6..90b4b9d 100644
--- a/libs/gui/BufferQueueProducer.cpp
+++ b/libs/gui/BufferQueueProducer.cpp
@@ -1122,18 +1122,22 @@
                     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);
@@ -1195,9 +1199,9 @@
                     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(
@@ -1205,6 +1209,7 @@
                     }
                     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 855a488..62abfa8 100644
--- a/libs/gui/IProducerListener.cpp
+++ b/libs/gui/IProducerListener.cpp
@@ -22,6 +22,7 @@
 
 enum {
     ON_BUFFER_RELEASED = IBinder::FIRST_CALL_TRANSACTION,
+    NEEDS_RELEASE_NOTIFY,
 };
 
 class BpProducerListener : public BpInterface<IProducerListener>
@@ -37,6 +38,23 @@
         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,6 +70,10 @@
             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);
 }
@@ -60,4 +82,8 @@
 
 DummyProducerListener::~DummyProducerListener() = default;
 
+bool BnProducerListener::needsReleaseNotify() {
+    return true;
+}
+
 } // namespace android