CpuConsumer: Properly track acquired buffers

CpuConsumer cannot simply assume a slot's buffer is the same buffer
between acquire and release, and therefore it could be possible for
the same slot to get used for a second acquired buffer, if there's a
producer disconnect in between. This would cause a problem when the
first buffer is released by the consumer.

Instead, use an independent list of acquired buffers to properly track
their state.

Bug: 8291751
Change-Id: I0241ad8704e53d47318c7179b13daed8181b1fab
diff --git a/include/gui/CpuConsumer.h b/include/gui/CpuConsumer.h
index 93dff32..4b956c7 100644
--- a/include/gui/CpuConsumer.h
+++ b/include/gui/CpuConsumer.h
@@ -37,7 +37,7 @@
  * This queue is synchronous by default.
  */
 
-class CpuConsumer: public ConsumerBase
+class CpuConsumer : public ConsumerBase
 {
   public:
     typedef ConsumerBase::FrameAvailableListener FrameAvailableListener;
@@ -88,14 +88,25 @@
     // Maximum number of buffers that can be locked at a time
     uint32_t mMaxLockedBuffers;
 
+    status_t releaseAcquiredBufferLocked(int lockedIdx);
+
     virtual void freeBufferLocked(int slotIndex);
 
-    // Array for tracking pointers passed to the consumer, matching the
-    // mSlots indexing
-    struct LockedSlot {
+    // Tracking for buffers acquired by the user
+    struct AcquiredBuffer {
+        // Need to track the original mSlot index and the buffer itself because
+        // the mSlot entry may be freed/reused before the acquired buffer is
+        // released.
+        int mSlot;
         sp<GraphicBuffer> mGraphicBuffer;
         void *mBufferPointer;
-    } mLockedSlots[BufferQueue::NUM_BUFFER_SLOTS];
+
+        AcquiredBuffer() :
+                mSlot(BufferQueue::INVALID_BUFFER_SLOT),
+                mBufferPointer(NULL) {
+        }
+    };
+    Vector<AcquiredBuffer> mAcquiredBuffers;
 
     // Count of currently locked buffers
     uint32_t mCurrentLockedBuffers;