Add allocator-v2 extended options to BufferQueue

Bug: 268382490
Test: libgui_test
Change-Id: If43b31eede87cddfcbfe4b24b53c1bafb453ebf2
diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp
index fb69fda..69345a9 100644
--- a/libs/gui/BufferQueueProducer.cpp
+++ b/libs/gui/BufferQueueProducer.cpp
@@ -423,6 +423,11 @@
     sp<IConsumerListener> listener;
     bool callOnFrameDequeued = false;
     uint64_t bufferId = 0; // Only used if callOnFrameDequeued == true
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_EXTENDEDALLOCATE)
+    std::vector<gui::AdditionalOptions> allocOptions;
+    uint32_t allocOptionsGenId = 0;
+#endif
+
     { // Autolock scope
         std::unique_lock<std::mutex> lock(mCore->mMutex);
 
@@ -486,11 +491,17 @@
         }
 
         const sp<GraphicBuffer>& buffer(mSlots[found].mGraphicBuffer);
-        if (mCore->mSharedBufferSlot == found &&
-                buffer->needsReallocation(width, height, format, BQ_LAYER_COUNT, usage)) {
-            BQ_LOGE("dequeueBuffer: cannot re-allocate a shared"
-                    "buffer");
 
+        bool needsReallocation = buffer == nullptr ||
+                buffer->needsReallocation(width, height, format, BQ_LAYER_COUNT, usage);
+
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_EXTENDEDALLOCATE)
+        needsReallocation |= mSlots[found].mAdditionalOptionsGenerationId !=
+                mCore->mAdditionalOptionsGenerationId;
+#endif
+
+        if (mCore->mSharedBufferSlot == found && needsReallocation) {
+            BQ_LOGE("dequeueBuffer: cannot re-allocate a shared buffer");
             return BAD_VALUE;
         }
 
@@ -505,9 +516,7 @@
 
         mSlots[found].mBufferState.dequeue();
 
-        if ((buffer == nullptr) ||
-                buffer->needsReallocation(width, height, format, BQ_LAYER_COUNT, usage))
-        {
+        if (needsReallocation) {
             if (CC_UNLIKELY(ATRACE_ENABLED())) {
                 if (buffer == nullptr) {
                     ATRACE_FORMAT_INSTANT("%s buffer reallocation: null", mConsumerName.c_str());
@@ -530,6 +539,10 @@
             mSlots[found].mFence = Fence::NO_FENCE;
             mCore->mBufferAge = 0;
             mCore->mIsAllocating = true;
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_EXTENDEDALLOCATE)
+            allocOptions = mCore->mAdditionalOptions;
+            allocOptionsGenId = mCore->mAdditionalOptionsGenerationId;
+#endif
 
             returnFlags |= BUFFER_NEEDS_REALLOCATION;
         } else {
@@ -575,9 +588,29 @@
 
     if (returnFlags & BUFFER_NEEDS_REALLOCATION) {
         BQ_LOGV("dequeueBuffer: allocating a new buffer for slot %d", *outSlot);
+
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_EXTENDEDALLOCATE)
+        std::vector<GraphicBufferAllocator::AdditionalOptions> tempOptions;
+        tempOptions.reserve(allocOptions.size());
+        for (const auto& it : allocOptions) {
+            tempOptions.emplace_back(it.name.c_str(), it.value);
+        }
+        const GraphicBufferAllocator::AllocationRequest allocRequest = {
+                .importBuffer = true,
+                .width = width,
+                .height = height,
+                .format = format,
+                .layerCount = BQ_LAYER_COUNT,
+                .usage = usage,
+                .requestorName = {mConsumerName.c_str(), mConsumerName.size()},
+                .extras = std::move(tempOptions),
+        };
+        sp<GraphicBuffer> graphicBuffer = new GraphicBuffer(allocRequest);
+#else
         sp<GraphicBuffer> graphicBuffer =
                 new GraphicBuffer(width, height, format, BQ_LAYER_COUNT, usage,
                                   {mConsumerName.c_str(), mConsumerName.size()});
+#endif
 
         status_t error = graphicBuffer->initCheck();
 
@@ -587,6 +620,9 @@
             if (error == NO_ERROR && !mCore->mIsAbandoned) {
                 graphicBuffer->setGenerationNumber(mCore->mGenerationNumber);
                 mSlots[*outSlot].mGraphicBuffer = graphicBuffer;
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_EXTENDEDALLOCATE)
+                mSlots[*outSlot].mAdditionalOptionsGenerationId = allocOptionsGenId;
+#endif
                 callOnFrameDequeued = true;
                 bufferId = mSlots[*outSlot].mGraphicBuffer->getId();
             }
@@ -1342,6 +1378,9 @@
     }
 
     mCore->mAllowAllocation = true;
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_EXTENDEDALLOCATE)
+    mCore->mAdditionalOptions.clear();
+#endif
     VALIDATE_CONSISTENCY();
     return status;
 }
@@ -1410,6 +1449,9 @@
                     mCore->mSidebandStream.clear();
                     mCore->mDequeueCondition.notify_all();
                     mCore->mAutoPrerotation = false;
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_EXTENDEDALLOCATE)
+                    mCore->mAdditionalOptions.clear();
+#endif
                     listener = mCore->mConsumerListener;
                 } else if (mCore->mConnectedApi == BufferQueueCore::NO_CONNECTED_API) {
                     BQ_LOGE("disconnect: not connected (req=%d)", api);
@@ -1462,6 +1504,10 @@
         PixelFormat allocFormat = PIXEL_FORMAT_UNKNOWN;
         uint64_t allocUsage = 0;
         std::string allocName;
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_EXTENDEDALLOCATE)
+        std::vector<gui::AdditionalOptions> allocOptions;
+        uint32_t allocOptionsGenId = 0;
+#endif
         { // Autolock scope
             std::unique_lock<std::mutex> lock(mCore->mMutex);
             mCore->waitWhileAllocatingLocked(lock);
@@ -1490,14 +1536,42 @@
             allocUsage = usage | mCore->mConsumerUsageBits;
             allocName.assign(mCore->mConsumerName.c_str(), mCore->mConsumerName.size());
 
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_EXTENDEDALLOCATE)
+            allocOptions = mCore->mAdditionalOptions;
+            allocOptionsGenId = mCore->mAdditionalOptionsGenerationId;
+#endif
+
             mCore->mIsAllocating = true;
+
         } // Autolock scope
 
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_EXTENDEDALLOCATE)
+        std::vector<GraphicBufferAllocator::AdditionalOptions> tempOptions;
+        tempOptions.reserve(allocOptions.size());
+        for (const auto& it : allocOptions) {
+            tempOptions.emplace_back(it.name.c_str(), it.value);
+        }
+        const GraphicBufferAllocator::AllocationRequest allocRequest = {
+                .importBuffer = true,
+                .width = allocWidth,
+                .height = allocHeight,
+                .format = allocFormat,
+                .layerCount = BQ_LAYER_COUNT,
+                .usage = allocUsage,
+                .requestorName = allocName,
+                .extras = std::move(tempOptions),
+        };
+#endif
+
         Vector<sp<GraphicBuffer>> buffers;
         for (size_t i = 0; i < newBufferCount; ++i) {
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_EXTENDEDALLOCATE)
+            sp<GraphicBuffer> graphicBuffer = new GraphicBuffer(allocRequest);
+#else
             sp<GraphicBuffer> graphicBuffer = new GraphicBuffer(
                     allocWidth, allocHeight, allocFormat, BQ_LAYER_COUNT,
                     allocUsage, allocName);
+#endif
 
             status_t result = graphicBuffer->initCheck();
 
@@ -1524,8 +1598,12 @@
             PixelFormat checkFormat = format != 0 ?
                     format : mCore->mDefaultBufferFormat;
             uint64_t checkUsage = usage | mCore->mConsumerUsageBits;
+            bool allocOptionsChanged = false;
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_EXTENDEDALLOCATE)
+            allocOptionsChanged = allocOptionsGenId != mCore->mAdditionalOptionsGenerationId;
+#endif
             if (checkWidth != allocWidth || checkHeight != allocHeight ||
-                checkFormat != allocFormat || checkUsage != allocUsage) {
+                checkFormat != allocFormat || checkUsage != allocUsage || allocOptionsChanged) {
                 // Something changed while we released the lock. Retry.
                 BQ_LOGV("allocateBuffers: size/format/usage changed while allocating. Retrying.");
                 mCore->mIsAllocating = false;
@@ -1543,6 +1621,9 @@
                 mCore->clearBufferSlotLocked(*slot); // Clean up the slot first
                 mSlots[*slot].mGraphicBuffer = buffers[i];
                 mSlots[*slot].mFence = Fence::NO_FENCE;
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_EXTENDEDALLOCATE)
+                mSlots[*slot].mAdditionalOptionsGenerationId = allocOptionsGenId;
+#endif
 
                 // freeBufferLocked puts this slot on the free slots list. Since
                 // we then attached a buffer, move the slot to free buffer list.
@@ -1778,4 +1859,29 @@
 }
 #endif
 
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_EXTENDEDALLOCATE)
+status_t BufferQueueProducer::setAdditionalOptions(
+        const std::vector<gui::AdditionalOptions>& options) {
+    ATRACE_CALL();
+    BQ_LOGV("setAdditionalOptions, size = %zu", options.size());
+
+    if (!GraphicBufferAllocator::get().supportsAdditionalOptions()) {
+        return INVALID_OPERATION;
+    }
+
+    std::lock_guard<std::mutex> lock(mCore->mMutex);
+
+    if (mCore->mConnectedApi == BufferQueueCore::NO_CONNECTED_API) {
+        BQ_LOGE("setAdditionalOptions: BufferQueue not connected, cannot set additional options");
+        return NO_INIT;
+    }
+
+    if (mCore->mAdditionalOptions != options) {
+        mCore->mAdditionalOptions = options;
+        mCore->mAdditionalOptionsGenerationId++;
+    }
+    return NO_ERROR;
+}
+#endif
+
 } // namespace android