Revert "libgui: Change BufferQueue to use free lists"

This reverts commit 8dddc990103b71137be2a6365a26b1ac36598e68.

Change-Id: I0b0fed9f1394c6f6ae812f6c562ead4473a8226e
diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp
index b54641e..6452cdd 100644
--- a/libs/gui/BufferQueueProducer.cpp
+++ b/libs/gui/BufferQueueProducer.cpp
@@ -161,6 +161,8 @@
             }
         }
 
+        // Look for a free buffer to give to the client
+        *found = BufferQueueCore::INVALID_BUFFER_SLOT;
         int dequeuedCount = 0;
         int acquiredCount = 0;
         for (int s = 0; s < maxBufferCount; ++s) {
@@ -171,6 +173,15 @@
                 case BufferSlot::ACQUIRED:
                     ++acquiredCount;
                     break;
+                case BufferSlot::FREE:
+                    // We return the oldest of the free buffers to avoid
+                    // stalling the producer if possible, since the consumer
+                    // may still have pending reads of in-flight buffers
+                    if (*found == BufferQueueCore::INVALID_BUFFER_SLOT ||
+                            mSlots[s].mFrameNumber < mSlots[*found].mFrameNumber) {
+                        *found = s;
+                    }
+                    break;
                 default:
                     break;
             }
@@ -203,8 +214,6 @@
             }
         }
 
-        *found = BufferQueueCore::INVALID_BUFFER_SLOT;
-
         // If we disconnect and reconnect quickly, we can be in a state where
         // our slots are empty but we have many buffers in the queue. This can
         // cause us to run out of memory if we outrun the consumer. Wait here if
@@ -214,16 +223,6 @@
         if (tooManyBuffers) {
             BQ_LOGV("%s: queue size is %zu, waiting", caller,
                     mCore->mQueue.size());
-        } else {
-            if (!mCore->mFreeBuffers.empty()) {
-                auto slot = mCore->mFreeBuffers.begin();
-                *found = *slot;
-                mCore->mFreeBuffers.erase(slot);
-            } else if (!mCore->mFreeSlots.empty()) {
-                auto slot = mCore->mFreeSlots.begin();
-                *found = *slot;
-                mCore->mFreeSlots.erase(slot);
-            }
         }
 
         // If no buffer is found, or if the queue has too many buffers
@@ -336,8 +335,6 @@
         *outFence = mSlots[found].mFence;
         mSlots[found].mEglFence = EGL_NO_SYNC_KHR;
         mSlots[found].mFence = Fence::NO_FENCE;
-
-        mCore->validateConsistencyLocked();
     } // Autolock scope
 
     if (returnFlags & BUFFER_NEEDS_REALLOCATION) {
@@ -358,6 +355,7 @@
                 return NO_INIT;
             }
 
+            mSlots[*outSlot].mFrameNumber = UINT32_MAX;
             mSlots[*outSlot].mGraphicBuffer = graphicBuffer;
         } // Autolock scope
     }
@@ -416,7 +414,6 @@
 
     mCore->freeBufferLocked(slot);
     mCore->mDequeueCondition.broadcast();
-    mCore->validateConsistencyLocked();
 
     return NO_ERROR;
 }
@@ -441,19 +438,27 @@
         return NO_INIT;
     }
 
-    if (mCore->mFreeBuffers.empty()) {
-        return NO_MEMORY;
+    // Find the oldest valid slot
+    int found = BufferQueueCore::INVALID_BUFFER_SLOT;
+    for (int s = 0; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) {
+        if (mSlots[s].mBufferState == BufferSlot::FREE &&
+                mSlots[s].mGraphicBuffer != NULL) {
+            if (found == BufferQueueCore::INVALID_BUFFER_SLOT ||
+                    mSlots[s].mFrameNumber < mSlots[found].mFrameNumber) {
+                found = s;
+            }
+        }
     }
 
-    int found = mCore->mFreeBuffers.front();
-    mCore->mFreeBuffers.remove(found);
+    if (found == BufferQueueCore::INVALID_BUFFER_SLOT) {
+        return NO_MEMORY;
+    }
 
     BQ_LOGV("detachNextBuffer detached slot %d", found);
 
     *outBuffer = mSlots[found].mGraphicBuffer;
     *outFence = mSlots[found].mFence;
     mCore->freeBufferLocked(found);
-    mCore->validateConsistencyLocked();
 
     return NO_ERROR;
 }
@@ -501,8 +506,6 @@
     mSlots[*outSlot].mFence = Fence::NO_FENCE;
     mSlots[*outSlot].mRequestBufferCalled = true;
 
-    mCore->validateConsistencyLocked();
-
     return returnFlags;
 }
 
@@ -637,7 +640,9 @@
                 // mark it as freed
                 if (mCore->stillTracking(front)) {
                     mSlots[front->mSlot].mBufferState = BufferSlot::FREE;
-                    mCore->mFreeBuffers.push_front(front->mSlot);
+                    // Reset the frame number of the freed buffer so that it is
+                    // the first in line to be dequeued again
+                    mSlots[front->mSlot].mFrameNumber = 0;
                 }
                 // Overwrite the droppable buffer with the incoming one
                 *front = item;
@@ -659,8 +664,6 @@
 
         // Take a ticket for the callback functions
         callbackTicket = mNextCallbackTicket++;
-
-        mCore->validateConsistencyLocked();
     } // Autolock scope
 
     // Wait without lock held
@@ -721,11 +724,10 @@
         return;
     }
 
-    mCore->mFreeBuffers.push_front(slot);
     mSlots[slot].mBufferState = BufferSlot::FREE;
+    mSlots[slot].mFrameNumber = 0;
     mSlots[slot].mFence = fence;
     mCore->mDequeueCondition.broadcast();
-    mCore->validateConsistencyLocked();
 }
 
 int BufferQueueProducer::query(int what, int *outValue) {
@@ -1007,19 +1009,13 @@
                 }
                 mCore->freeBufferLocked(slot); // Clean up the slot first
                 mSlots[slot].mGraphicBuffer = buffers[i];
+                mSlots[slot].mFrameNumber = 0;
                 mSlots[slot].mFence = Fence::NO_FENCE;
-
-                // freeBufferLocked puts this slot on the free slots list. Since
-                // we then attached a buffer, move the slot to free buffer list.
-                mCore->mFreeSlots.erase(slot);
-                mCore->mFreeBuffers.push_front(slot);
-
                 BQ_LOGV("allocateBuffers: allocated a new buffer in slot %d", slot);
             }
 
             mCore->mIsAllocating = false;
             mCore->mIsAllocatingCondition.broadcast();
-            mCore->validateConsistencyLocked();
         } // Autolock scope
     }
 }