Fix unexpected FrameEvents on BufferQueue reconnect

Helps reduce the number of ALOGE's being hit
when switching between apps.

* Notify Layer when the Producer disconnects.
* Avoid sending event deltas from a previous connection.
* Avoid releasing a frame more than once.

Test: adb shell /data/nativetest/libgui_test/libgui_test
    --gtest_filter=*GetFrameTimestamps*

Change-Id: I64f314be72ddb154b584d726ac382cd468e345bf
diff --git a/libs/gui/BufferQueue.cpp b/libs/gui/BufferQueue.cpp
index f76a282..13692eb 100644
--- a/libs/gui/BufferQueue.cpp
+++ b/libs/gui/BufferQueue.cpp
@@ -31,6 +31,13 @@
 
 BufferQueue::ProxyConsumerListener::~ProxyConsumerListener() {}
 
+void BufferQueue::ProxyConsumerListener::onDisconnect() {
+    sp<ConsumerListener> listener(mConsumerListener.promote());
+    if (listener != NULL) {
+        listener->onDisconnect();
+    }
+}
+
 void BufferQueue::ProxyConsumerListener::onFrameAvailable(
         const BufferItem& item) {
     sp<ConsumerListener> listener(mConsumerListener.promote());
diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp
index 3f69b1f..be0dc20 100644
--- a/libs/gui/BufferQueueProducer.cpp
+++ b/libs/gui/BufferQueueProducer.cpp
@@ -1272,6 +1272,7 @@
     // Call back without lock held
     if (listener != NULL) {
         listener->onBuffersReleased();
+        listener->onDisconnect();
     }
 
     return status;
diff --git a/libs/gui/FrameTimestamps.cpp b/libs/gui/FrameTimestamps.cpp
index f427e68..019a11e 100644
--- a/libs/gui/FrameTimestamps.cpp
+++ b/libs/gui/FrameTimestamps.cpp
@@ -329,7 +329,7 @@
 
 void ProducerFrameEventHistory::applyFenceDelta(FenceTimeline* timeline,
         std::shared_ptr<FenceTime>* dst, const FenceTime::Snapshot& src) const {
-    if (CC_UNLIKELY(dst == nullptr)) {
+    if (CC_UNLIKELY(dst == nullptr || dst->get() == nullptr)) {
         ALOGE("applyFenceDelta: dst is null.");
         return;
     }
@@ -364,6 +364,11 @@
 
 ConsumerFrameEventHistory::~ConsumerFrameEventHistory() = default;
 
+void ConsumerFrameEventHistory::onDisconnect() {
+    mCurrentConnectId++;
+    mProducerWantsEvents = false;
+}
+
 void ConsumerFrameEventHistory::initializeCompositorTiming(
         const CompositorTiming& compositorTiming) {
     mCompositorTiming = compositorTiming;
@@ -372,6 +377,7 @@
 void ConsumerFrameEventHistory::addQueue(const NewFrameEventsEntry& newEntry) {
     // Overwrite all fields of the frame with default values unless set here.
     FrameEvents newTimestamps;
+    newTimestamps.connectId = mCurrentConnectId;
     newTimestamps.frameNumber = newEntry.frameNumber;
     newTimestamps.postedTime = newEntry.postedTime;
     newTimestamps.requestedPresentTime = newEntry.requestedPresentTime;
@@ -453,8 +459,8 @@
 void ConsumerFrameEventHistory::addRelease(uint64_t frameNumber,
         nsecs_t dequeueReadyTime, std::shared_ptr<FenceTime>&& release) {
     FrameEvents* frame = getFrame(frameNumber, &mReleaseOffset);
-    if (CC_UNLIKELY(frame == nullptr)) {
-        ALOGE("addRelease: Did not find frame (%" PRIu64 ").", frameNumber);
+    if (frame == nullptr) {
+        ALOGE_IF(mProducerWantsEvents, "addRelease: Did not find frame.");
         return;
     }
     frame->addReleaseCalled = true;
@@ -469,13 +475,19 @@
     mProducerWantsEvents = true;
     size_t i = static_cast<size_t>(std::distance(mFrames.begin(), frame));
     if (mFramesDirty[i].anyDirty()) {
-        delta->mDeltas.emplace_back(i, *frame, mFramesDirty[i]);
+        // Make sure only to send back deltas for the current connection
+        // since the producer won't have the correct state to apply a delta
+        // from a previous connection.
+        if (mFrames[i].connectId == mCurrentConnectId) {
+            delta->mDeltas.emplace_back(i, *frame, mFramesDirty[i]);
+        }
         mFramesDirty[i].reset();
     }
 }
 
 void ConsumerFrameEventHistory::getAndResetDelta(
         FrameEventHistoryDelta* delta) {
+    mProducerWantsEvents = true;
     delta->mCompositorTiming = mCompositorTiming;
 
     // Write these in order of frame number so that it is easy to
diff --git a/libs/gui/IConsumerListener.cpp b/libs/gui/IConsumerListener.cpp
index 3d893b1..8cadc4d 100644
--- a/libs/gui/IConsumerListener.cpp
+++ b/libs/gui/IConsumerListener.cpp
@@ -28,7 +28,8 @@
 // ---------------------------------------------------------------------------
 
 enum {
-    ON_FRAME_AVAILABLE = IBinder::FIRST_CALL_TRANSACTION,
+    ON_DISCONNECT = IBinder::FIRST_CALL_TRANSACTION,
+    ON_FRAME_AVAILABLE,
     ON_BUFFER_RELEASED,
     ON_SIDEBAND_STREAM_CHANGED,
     GET_FRAME_TIMESTAMPS
@@ -43,6 +44,12 @@
 
     virtual ~BpConsumerListener();
 
+    virtual void onDisconnect() {
+        Parcel data, reply;
+        data.writeInterfaceToken(IConsumerListener::getInterfaceDescriptor());
+        remote()->transact(ON_DISCONNECT, data, &reply, IBinder::FLAG_ONEWAY);
+    }
+
     virtual void onFrameAvailable(const BufferItem& item) {
         Parcel data, reply;
         data.writeInterfaceToken(IConsumerListener::getInterfaceDescriptor());
@@ -75,6 +82,10 @@
     uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
 {
     switch(code) {
+        case ON_DISCONNECT: {
+            CHECK_INTERFACE(IConsumerListener, data, reply);
+            onDisconnect();
+            return NO_ERROR; }
         case ON_FRAME_AVAILABLE: {
             CHECK_INTERFACE(IConsumerListener, data, reply);
             BufferItem item;
diff --git a/libs/gui/tests/DummyConsumer.h b/libs/gui/tests/DummyConsumer.h
index 0511e16..502bdf9 100644
--- a/libs/gui/tests/DummyConsumer.h
+++ b/libs/gui/tests/DummyConsumer.h
@@ -19,9 +19,9 @@
 namespace android {
 
 struct DummyConsumer : public BnConsumerListener {
-    virtual void onFrameAvailable(const BufferItem& /* item */) {}
-    virtual void onBuffersReleased() {}
-    virtual void onSidebandStreamChanged() {}
+    void onFrameAvailable(const BufferItem& /* item */) override {}
+    void onBuffersReleased() override {}
+    void onSidebandStreamChanged() override {}
 };
 
 } // namespace android
diff --git a/libs/gui/tests/IGraphicBufferProducer_test.cpp b/libs/gui/tests/IGraphicBufferProducer_test.cpp
index 0329a6d..aa071f6 100644
--- a/libs/gui/tests/IGraphicBufferProducer_test.cpp
+++ b/libs/gui/tests/IGraphicBufferProducer_test.cpp
@@ -17,6 +17,8 @@
 #define LOG_TAG "IGraphicBufferProducer_test"
 //#define LOG_NDEBUG 0
 
+#include "DummyConsumer.h"
+
 #include <gtest/gtest.h>
 
 #include <utils/String8.h>
@@ -64,12 +66,6 @@
     const sp<Fence> QUEUE_BUFFER_INPUT_FENCE = Fence::NO_FENCE;
 }; // namespace anonymous
 
-struct DummyConsumer : public BnConsumerListener {
-    virtual void onFrameAvailable(const BufferItem& /* item */) {}
-    virtual void onBuffersReleased() {}
-    virtual void onSidebandStreamChanged() {}
-};
-
 class IGraphicBufferProducerTest : public ::testing::Test {
 protected: