BufferQueue: release mutex while allocating. DO NOT MERGE

BufferQueueProducer::allocateBuffers used to keep the BufferQueueCore
mutex while doing the buffer allocation, which would cause the consumer
(which also needs the mutex) to block if the allocation takes a long
time.
Instead, release the mutex while doing the allocation, and grab it again
before filling the slots. Keep a bool state and a condvar to prevent
other producers from trying to allocate the slots while the mutex is
released.

Bug: 11792166

Change-Id: I4ab1319995ef892be2beba892f1fdbf50ce0416d
(cherry picked from commit ea96044470a29133321c681080870b9d31f81a19)
diff --git a/include/gui/BufferQueueCore.h b/include/gui/BufferQueueCore.h
index cfcb7a5..1050e3b 100644
--- a/include/gui/BufferQueueCore.h
+++ b/include/gui/BufferQueueCore.h
@@ -120,6 +120,9 @@
     // in one of the slots.
     bool stillTracking(const BufferItem* item) const;
 
+    // waitWhileAllocatingLocked blocks until mIsAllocating is false.
+    void waitWhileAllocatingLocked() const;
+
     // mAllocator is the connection to SurfaceFlinger that is used to allocate
     // new GraphicBuffer objects.
     sp<IGraphicBufferAlloc> mAllocator;
@@ -234,6 +237,15 @@
     // mSidebandStream is a handle to the sideband buffer stream, if any
     sp<NativeHandle> mSidebandStream;
 
+    // mIsAllocating indicates whether a producer is currently trying to allocate buffers (which
+    // releases mMutex while doing the allocation proper). Producers should not modify any of the
+    // FREE slots while this is true. mIsAllocatingCondition is signaled when this value changes to
+    // false.
+    bool mIsAllocating;
+
+    // mIsAllocatingCondition is a condition variable used by producers to wait until mIsAllocating
+    // becomes false.
+    mutable Condition mIsAllocatingCondition;
 }; // class BufferQueueCore
 
 } // namespace android