gralloc: Support allocate buffer without import

Media allocates buffers but doesn't import until they absolutely
need to. In order to support codec2 moving to GraphicBufferAllocator,
add a function that allows them to allocate without import.

Bug: 145139476
Test: VtsHalMediaC2V1_0Host &&
    cherry pick ag/9741096 and run
    android.media.cts.MediaMetadataRetrieverTest#testThumbnailVP9Hdr

Change-Id: Icbd5943d45f20cb796204f816e5aac446d402979
diff --git a/libs/ui/Gralloc2.cpp b/libs/ui/Gralloc2.cpp
index 5dc4530..0e23ddf 100644
--- a/libs/ui/Gralloc2.cpp
+++ b/libs/ui/Gralloc2.cpp
@@ -381,7 +381,8 @@
 
 status_t Gralloc2Allocator::allocate(uint32_t width, uint32_t height, PixelFormat format,
                                      uint32_t layerCount, uint64_t usage, uint32_t bufferCount,
-                                     uint32_t* outStride, buffer_handle_t* outBufferHandles) const {
+                                     uint32_t* outStride, buffer_handle_t* outBufferHandles,
+                                     bool importBuffers) const {
     IMapper::BufferDescriptorInfo descriptorInfo = {};
     descriptorInfo.width = width;
     descriptorInfo.height = height;
@@ -404,19 +405,33 @@
                                             return;
                                         }
 
-                                        // import buffers
-                                        for (uint32_t i = 0; i < bufferCount; i++) {
-                                            error = mMapper.importBuffer(tmpBuffers[i],
-                                                                         &outBufferHandles[i]);
-                                            if (error != NO_ERROR) {
-                                                for (uint32_t j = 0; j < i; j++) {
-                                                    mMapper.freeBuffer(outBufferHandles[j]);
-                                                    outBufferHandles[j] = nullptr;
+                                        if (importBuffers) {
+                                            for (uint32_t i = 0; i < bufferCount; i++) {
+                                                error = mMapper.importBuffer(tmpBuffers[i],
+                                                                             &outBufferHandles[i]);
+                                                if (error != NO_ERROR) {
+                                                    for (uint32_t j = 0; j < i; j++) {
+                                                        mMapper.freeBuffer(outBufferHandles[j]);
+                                                        outBufferHandles[j] = nullptr;
+                                                    }
+                                                    return;
                                                 }
-                                                return;
+                                            }
+                                        } else {
+                                            for (uint32_t i = 0; i < bufferCount; i++) {
+                                                outBufferHandles[i] = native_handle_clone(
+                                                        tmpBuffers[i].getNativeHandle());
+                                                if (!outBufferHandles[i]) {
+                                                    for (uint32_t j = 0; j < i; j++) {
+                                                        auto buffer = const_cast<native_handle_t*>(
+                                                                outBufferHandles[j]);
+                                                        native_handle_close(buffer);
+                                                        native_handle_delete(buffer);
+                                                        outBufferHandles[j] = nullptr;
+                                                    }
+                                                }
                                             }
                                         }
-
                                         *outStride = tmpStride;
                                     });
 
diff --git a/libs/ui/Gralloc3.cpp b/libs/ui/Gralloc3.cpp
index eb43765..e189281 100644
--- a/libs/ui/Gralloc3.cpp
+++ b/libs/ui/Gralloc3.cpp
@@ -362,7 +362,8 @@
 
 status_t Gralloc3Allocator::allocate(uint32_t width, uint32_t height, android::PixelFormat format,
                                      uint32_t layerCount, uint64_t usage, uint32_t bufferCount,
-                                     uint32_t* outStride, buffer_handle_t* outBufferHandles) const {
+                                     uint32_t* outStride, buffer_handle_t* outBufferHandles,
+                                     bool importBuffers) const {
     IMapper::BufferDescriptorInfo descriptorInfo;
     sBufferDescriptorInfo(width, height, format, layerCount, usage, &descriptorInfo);
 
@@ -381,16 +382,31 @@
                                             return;
                                         }
 
-                                        // import buffers
-                                        for (uint32_t i = 0; i < bufferCount; i++) {
-                                            error = mMapper.importBuffer(tmpBuffers[i],
-                                                                         &outBufferHandles[i]);
-                                            if (error != NO_ERROR) {
-                                                for (uint32_t j = 0; j < i; j++) {
-                                                    mMapper.freeBuffer(outBufferHandles[j]);
-                                                    outBufferHandles[j] = nullptr;
+                                        if (importBuffers) {
+                                            for (uint32_t i = 0; i < bufferCount; i++) {
+                                                error = mMapper.importBuffer(tmpBuffers[i],
+                                                                             &outBufferHandles[i]);
+                                                if (error != NO_ERROR) {
+                                                    for (uint32_t j = 0; j < i; j++) {
+                                                        mMapper.freeBuffer(outBufferHandles[j]);
+                                                        outBufferHandles[j] = nullptr;
+                                                    }
+                                                    return;
                                                 }
-                                                return;
+                                            }
+                                        } else {
+                                            for (uint32_t i = 0; i < bufferCount; i++) {
+                                                outBufferHandles[i] = native_handle_clone(
+                                                        tmpBuffers[i].getNativeHandle());
+                                                if (!outBufferHandles[i]) {
+                                                    for (uint32_t j = 0; j < i; j++) {
+                                                        auto buffer = const_cast<native_handle_t*>(
+                                                                outBufferHandles[j]);
+                                                        native_handle_close(buffer);
+                                                        native_handle_delete(buffer);
+                                                        outBufferHandles[j] = nullptr;
+                                                    }
+                                                }
                                             }
                                         }
                                         *outStride = tmpStride;
diff --git a/libs/ui/Gralloc4.cpp b/libs/ui/Gralloc4.cpp
index 73945cf..afe26b7 100644
--- a/libs/ui/Gralloc4.cpp
+++ b/libs/ui/Gralloc4.cpp
@@ -327,7 +327,8 @@
 
 status_t Gralloc4Allocator::allocate(uint32_t width, uint32_t height, android::PixelFormat format,
                                      uint32_t layerCount, uint64_t usage, uint32_t bufferCount,
-                                     uint32_t* outStride, buffer_handle_t* outBufferHandles) const {
+                                     uint32_t* outStride, buffer_handle_t* outBufferHandles,
+                                     bool importBuffers) const {
     IMapper::BufferDescriptorInfo descriptorInfo;
     sBufferDescriptorInfo(width, height, format, layerCount, usage, &descriptorInfo);
 
@@ -346,16 +347,31 @@
                                             return;
                                         }
 
-                                        // import buffers
-                                        for (uint32_t i = 0; i < bufferCount; i++) {
-                                            error = mMapper.importBuffer(tmpBuffers[i],
-                                                                         &outBufferHandles[i]);
-                                            if (error != NO_ERROR) {
-                                                for (uint32_t j = 0; j < i; j++) {
-                                                    mMapper.freeBuffer(outBufferHandles[j]);
-                                                    outBufferHandles[j] = nullptr;
+                                        if (importBuffers) {
+                                            for (uint32_t i = 0; i < bufferCount; i++) {
+                                                error = mMapper.importBuffer(tmpBuffers[i],
+                                                                             &outBufferHandles[i]);
+                                                if (error != NO_ERROR) {
+                                                    for (uint32_t j = 0; j < i; j++) {
+                                                        mMapper.freeBuffer(outBufferHandles[j]);
+                                                        outBufferHandles[j] = nullptr;
+                                                    }
+                                                    return;
                                                 }
-                                                return;
+                                            }
+                                        } else {
+                                            for (uint32_t i = 0; i < bufferCount; i++) {
+                                                outBufferHandles[i] = native_handle_clone(
+                                                        tmpBuffers[i].getNativeHandle());
+                                                if (!outBufferHandles[i]) {
+                                                    for (uint32_t j = 0; j < i; j++) {
+                                                        auto buffer = const_cast<native_handle_t*>(
+                                                                outBufferHandles[j]);
+                                                        native_handle_close(buffer);
+                                                        native_handle_delete(buffer);
+                                                        outBufferHandles[j] = nullptr;
+                                                    }
+                                                }
                                             }
                                         }
                                         *outStride = tmpStride;
diff --git a/libs/ui/GraphicBufferAllocator.cpp b/libs/ui/GraphicBufferAllocator.cpp
index efe0931..b2b9680 100644
--- a/libs/ui/GraphicBufferAllocator.cpp
+++ b/libs/ui/GraphicBufferAllocator.cpp
@@ -111,10 +111,10 @@
     ALOGD("%s", s.c_str());
 }
 
-status_t GraphicBufferAllocator::allocate(uint32_t width, uint32_t height, PixelFormat format,
-                                          uint32_t layerCount, uint64_t usage,
-                                          buffer_handle_t* handle, uint32_t* stride,
-                                          std::string requestorName) {
+status_t GraphicBufferAllocator::allocateHelper(uint32_t width, uint32_t height, PixelFormat format,
+                                                uint32_t layerCount, uint64_t usage,
+                                                buffer_handle_t* handle, uint32_t* stride,
+                                                std::string requestorName, bool importBuffer) {
     ATRACE_CALL();
 
     // make sure to not allocate a N x 0 or 0 x N buffer, since this is
@@ -137,8 +137,18 @@
     // TODO(b/72323293, b/72703005): Remove these invalid bits from callers
     usage &= ~static_cast<uint64_t>((1 << 10) | (1 << 13));
 
-    status_t error =
-            mAllocator->allocate(width, height, format, layerCount, usage, 1, stride, handle);
+    status_t error = mAllocator->allocate(width, height, format, layerCount, usage, 1, stride,
+                                          handle, importBuffer);
+    if (error != NO_ERROR) {
+        ALOGE("Failed to allocate (%u x %u) layerCount %u format %d "
+              "usage %" PRIx64 ": %d",
+              width, height, layerCount, format, usage, error);
+        return NO_MEMORY;
+    }
+
+    if (!importBuffer) {
+        return NO_ERROR;
+    }
     size_t bufSize;
 
     // if stride has no meaning or is too large,
@@ -150,35 +160,44 @@
         bufSize = static_cast<size_t>((*stride)) * height * bpp;
     }
 
-    if (error == NO_ERROR) {
-        Mutex::Autolock _l(sLock);
-        KeyedVector<buffer_handle_t, alloc_rec_t>& list(sAllocList);
-        alloc_rec_t rec;
-        rec.width = width;
-        rec.height = height;
-        rec.stride = *stride;
-        rec.format = format;
-        rec.layerCount = layerCount;
-        rec.usage = usage;
-        rec.size = bufSize;
-        rec.requestorName = std::move(requestorName);
-        list.add(*handle, rec);
+    Mutex::Autolock _l(sLock);
+    KeyedVector<buffer_handle_t, alloc_rec_t>& list(sAllocList);
+    alloc_rec_t rec;
+    rec.width = width;
+    rec.height = height;
+    rec.stride = *stride;
+    rec.format = format;
+    rec.layerCount = layerCount;
+    rec.usage = usage;
+    rec.size = bufSize;
+    rec.requestorName = std::move(requestorName);
+    list.add(*handle, rec);
 
-        return NO_ERROR;
-    } else {
-        ALOGE("Failed to allocate (%u x %u) layerCount %u format %d "
-                "usage %" PRIx64 ": %d",
-                width, height, layerCount, format, usage,
-                error);
-        return NO_MEMORY;
-    }
+    return NO_ERROR;
+}
+status_t GraphicBufferAllocator::allocate(uint32_t width, uint32_t height, PixelFormat format,
+                                          uint32_t layerCount, uint64_t usage,
+                                          buffer_handle_t* handle, uint32_t* stride,
+                                          std::string requestorName) {
+    return allocateHelper(width, height, format, layerCount, usage, handle, stride, requestorName,
+                          true);
 }
 
+status_t GraphicBufferAllocator::allocateRawHandle(uint32_t width, uint32_t height,
+                                                   PixelFormat format, uint32_t layerCount,
+                                                   uint64_t usage, buffer_handle_t* handle,
+                                                   uint32_t* stride, std::string requestorName) {
+    return allocateHelper(width, height, format, layerCount, usage, handle, stride, requestorName,
+                          false);
+}
+
+// DEPRECATED
 status_t GraphicBufferAllocator::allocate(uint32_t width, uint32_t height, PixelFormat format,
                                           uint32_t layerCount, uint64_t usage,
                                           buffer_handle_t* handle, uint32_t* stride,
                                           uint64_t /*graphicBufferId*/, std::string requestorName) {
-    return allocate(width, height, format, layerCount, usage, handle, stride, requestorName);
+    return allocateHelper(width, height, format, layerCount, usage, handle, stride, requestorName,
+                          true);
 }
 
 status_t GraphicBufferAllocator::free(buffer_handle_t handle)
diff --git a/libs/ui/include/ui/Gralloc.h b/libs/ui/include/ui/Gralloc.h
index 6cc23f0..c28f7a5 100644
--- a/libs/ui/include/ui/Gralloc.h
+++ b/libs/ui/include/ui/Gralloc.h
@@ -94,7 +94,8 @@
      */
     virtual status_t allocate(uint32_t width, uint32_t height, PixelFormat format,
                               uint32_t layerCount, uint64_t usage, uint32_t bufferCount,
-                              uint32_t* outStride, buffer_handle_t* outBufferHandles) const = 0;
+                              uint32_t* outStride, buffer_handle_t* outBufferHandles,
+                              bool importBuffers = true) const = 0;
 };
 
 } // namespace android
diff --git a/libs/ui/include/ui/Gralloc2.h b/libs/ui/include/ui/Gralloc2.h
index 948f597..12c772a 100644
--- a/libs/ui/include/ui/Gralloc2.h
+++ b/libs/ui/include/ui/Gralloc2.h
@@ -85,7 +85,7 @@
 
     status_t allocate(uint32_t width, uint32_t height, PixelFormat format, uint32_t layerCount,
                       uint64_t usage, uint32_t bufferCount, uint32_t* outStride,
-                      buffer_handle_t* outBufferHandles) const override;
+                      buffer_handle_t* outBufferHandles, bool importBuffers = true) const override;
 
 private:
     const Gralloc2Mapper& mMapper;
diff --git a/libs/ui/include/ui/Gralloc3.h b/libs/ui/include/ui/Gralloc3.h
index 0965f52..bfbc2aa 100644
--- a/libs/ui/include/ui/Gralloc3.h
+++ b/libs/ui/include/ui/Gralloc3.h
@@ -83,7 +83,7 @@
 
     status_t allocate(uint32_t width, uint32_t height, PixelFormat format, uint32_t layerCount,
                       uint64_t usage, uint32_t bufferCount, uint32_t* outStride,
-                      buffer_handle_t* outBufferHandles) const override;
+                      buffer_handle_t* outBufferHandles, bool importBuffers = true) const override;
 
 private:
     const Gralloc3Mapper& mMapper;
diff --git a/libs/ui/include/ui/Gralloc4.h b/libs/ui/include/ui/Gralloc4.h
index 14b65bc..60115f9 100644
--- a/libs/ui/include/ui/Gralloc4.h
+++ b/libs/ui/include/ui/Gralloc4.h
@@ -83,7 +83,7 @@
 
     status_t allocate(uint32_t width, uint32_t height, PixelFormat format, uint32_t layerCount,
                       uint64_t usage, uint32_t bufferCount, uint32_t* outStride,
-                      buffer_handle_t* outBufferHandles) const override;
+                      buffer_handle_t* outBufferHandles, bool importBuffers = true) const override;
 
 private:
     const Gralloc4Mapper& mMapper;
diff --git a/libs/ui/include/ui/GraphicBufferAllocator.h b/libs/ui/include/ui/GraphicBufferAllocator.h
index 9f6159a..34a5b17 100644
--- a/libs/ui/include/ui/GraphicBufferAllocator.h
+++ b/libs/ui/include/ui/GraphicBufferAllocator.h
@@ -42,16 +42,34 @@
 public:
     static inline GraphicBufferAllocator& get() { return getInstance(); }
 
-    // DEPRECATED: GraphicBufferAllocator does not use the graphicBufferId
+    /**
+     * Allocates and imports a gralloc buffer.
+     *
+     * The handle must be freed with GraphicBufferAllocator::free() when no longer needed.
+     */
+    status_t allocate(uint32_t w, uint32_t h, PixelFormat format, uint32_t layerCount,
+                      uint64_t usage, buffer_handle_t* handle, uint32_t* stride,
+                      std::string requestorName);
+
+    /**
+     * Allocates and does NOT import a gralloc buffer. Buffers cannot be used until they have
+     * been imported. This function is for advanced use cases only.
+     *
+     * The raw native handle must be freed by calling native_handle_close() followed by
+     * native_handle_delete().
+     */
+    status_t allocateRawHandle(uint32_t w, uint32_t h, PixelFormat format, uint32_t layerCount,
+                               uint64_t usage, buffer_handle_t* handle, uint32_t* stride,
+                               std::string requestorName);
+
+    /**
+     * DEPRECATED: GraphicBufferAllocator does not use the graphicBufferId.
+     */
     status_t allocate(uint32_t w, uint32_t h, PixelFormat format,
             uint32_t layerCount, uint64_t usage,
             buffer_handle_t* handle, uint32_t* stride, uint64_t graphicBufferId,
             std::string requestorName);
 
-    status_t allocate(uint32_t w, uint32_t h, PixelFormat format, uint32_t layerCount,
-                      uint64_t usage, buffer_handle_t* handle, uint32_t* stride,
-                      std::string requestorName);
-
     status_t free(buffer_handle_t handle);
 
     size_t getTotalSize() const;
@@ -71,6 +89,10 @@
         std::string requestorName;
     };
 
+    status_t allocateHelper(uint32_t w, uint32_t h, PixelFormat format, uint32_t layerCount,
+                            uint64_t usage, buffer_handle_t* handle, uint32_t* stride,
+                            std::string requestorName, bool importBuffer);
+
     static Mutex sLock;
     static KeyedVector<buffer_handle_t, alloc_rec_t> sAllocList;
 
diff --git a/libs/ui/tests/mock/MockGrallocAllocator.h b/libs/ui/tests/mock/MockGrallocAllocator.h
index 22c80a4..7660e9f 100644
--- a/libs/ui/tests/mock/MockGrallocAllocator.h
+++ b/libs/ui/tests/mock/MockGrallocAllocator.h
@@ -36,7 +36,7 @@
     MOCK_METHOD(status_t, allocate,
                 (uint32_t width, uint32_t height, PixelFormat format, uint32_t layerCount,
                  uint64_t usage, uint32_t bufferCount, uint32_t* outStride,
-                 buffer_handle_t* outBufferHandles),
+                 buffer_handle_t* outBufferHandles, bool less),
                 (const, override));
 };