Add layered buffer support to libui and libgui.

Bug: 31686534
Test: manual
Change-Id: Ia40270701467f4b785660324cad883e7da08989a
diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp
index 90b4b9d..9241c7c 100644
--- a/libs/gui/BufferQueueProducer.cpp
+++ b/libs/gui/BufferQueueProducer.cpp
@@ -42,6 +42,8 @@
 
 namespace android {
 
+static constexpr uint32_t BQ_LAYER_COUNT = 1;
+
 BufferQueueProducer::BufferQueueProducer(const sp<BufferQueueCore>& core,
         bool consumerIsSurfaceFlinger) :
     mCore(core),
@@ -414,7 +416,8 @@
             // buffer. If this buffer would require reallocation to meet the
             // requested attributes, we free it and attempt to get another one.
             if (!mCore->mAllowAllocation) {
-                if (buffer->needsReallocation(width, height, format, usage)) {
+                if (buffer->needsReallocation(width, height, format,
+                        BQ_LAYER_COUNT, usage)) {
                     if (mCore->mSharedBufferSlot == found) {
                         BQ_LOGE("dequeueBuffer: cannot re-allocate a shared"
                                 "buffer");
@@ -430,7 +433,8 @@
 
         const sp<GraphicBuffer>& buffer(mSlots[found].mGraphicBuffer);
         if (mCore->mSharedBufferSlot == found &&
-                buffer->needsReallocation(width,  height, format, usage)) {
+                buffer->needsReallocation(width, height, format,
+                        BQ_LAYER_COUNT, usage)) {
             BQ_LOGE("dequeueBuffer: cannot re-allocate a shared"
                     "buffer");
 
@@ -449,7 +453,8 @@
         mSlots[found].mBufferState.dequeue();
 
         if ((buffer == NULL) ||
-                buffer->needsReallocation(width, height, format, usage))
+                buffer->needsReallocation(width, height, format, BQ_LAYER_COUNT,
+                usage))
         {
             mSlots[found].mAcquireCalled = false;
             mSlots[found].mGraphicBuffer = NULL;
@@ -500,7 +505,7 @@
         status_t error;
         BQ_LOGV("dequeueBuffer: allocating a new buffer for slot %d", *outSlot);
         sp<GraphicBuffer> graphicBuffer(mCore->mAllocator->createGraphicBuffer(
-                width, height, format, usage,
+                width, height, format, BQ_LAYER_COUNT, usage,
                 {mConsumerName.string(), mConsumerName.size()}, &error));
         { // Autolock scope
             Mutex::Autolock lock(mCore->mMutex);
@@ -1039,6 +1044,10 @@
         case NATIVE_WINDOW_FORMAT:
             value = static_cast<int32_t>(mCore->mDefaultBufferFormat);
             break;
+        case NATIVE_WINDOW_LAYER_COUNT:
+            // All BufferQueue buffers have a single layer.
+            value = BQ_LAYER_COUNT;
+            break;
         case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS:
             value = mCore->getMinUndequeuedBufferCountLocked();
             break;
@@ -1287,8 +1296,9 @@
         for (size_t i = 0; i <  newBufferCount; ++i) {
             status_t result = NO_ERROR;
             sp<GraphicBuffer> graphicBuffer(mCore->mAllocator->createGraphicBuffer(
-                    allocWidth, allocHeight, allocFormat, allocUsage,
-                    {mConsumerName.string(), mConsumerName.size()}, &result));
+                    allocWidth, allocHeight, allocFormat, BQ_LAYER_COUNT,
+                    allocUsage, {mConsumerName.string(), mConsumerName.size()},
+                    &result));
             if (result != NO_ERROR) {
                 BQ_LOGE("allocateBuffers: failed to allocate buffer (%u x %u, format"
                         " %u, usage %u)", width, height, format, usage);
diff --git a/libs/gui/GraphicBufferAlloc.cpp b/libs/gui/GraphicBufferAlloc.cpp
index e6150f4..9d045dd 100644
--- a/libs/gui/GraphicBufferAlloc.cpp
+++ b/libs/gui/GraphicBufferAlloc.cpp
@@ -32,19 +32,21 @@
 }
 
 sp<GraphicBuffer> GraphicBufferAlloc::createGraphicBuffer(uint32_t width,
-        uint32_t height, PixelFormat format, uint32_t usage,
-        std::string requestorName, status_t* error) {
+        uint32_t height, PixelFormat format, uint32_t layerCount,
+        uint32_t usage, std::string requestorName, status_t* error) {
     sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(
-            width, height, format, usage, std::move(requestorName)));
+            width, height, format, layerCount, usage,
+            std::move(requestorName)));
     status_t err = graphicBuffer->initCheck();
     *error = err;
     if (err != 0 || graphicBuffer->handle == 0) {
         if (err == NO_MEMORY) {
             GraphicBuffer::dumpAllocationsToSystemLog();
         }
-        ALOGE("GraphicBufferAlloc::createGraphicBuffer(w=%d, h=%d) "
+        ALOGE("GraphicBufferAlloc::createGraphicBuffer(w=%u, h=%u, lc=%u) "
              "failed (%s), handle=%p",
-                width, height, strerror(-err), graphicBuffer->handle);
+                width, height, layerCount, strerror(-err),
+                graphicBuffer->handle);
         return 0;
     }
     return graphicBuffer;
diff --git a/libs/gui/IGraphicBufferAlloc.cpp b/libs/gui/IGraphicBufferAlloc.cpp
index 2fb380c..a3d3b74 100644
--- a/libs/gui/IGraphicBufferAlloc.cpp
+++ b/libs/gui/IGraphicBufferAlloc.cpp
@@ -45,13 +45,14 @@
     virtual ~BpGraphicBufferAlloc();
 
     virtual sp<GraphicBuffer> createGraphicBuffer(uint32_t width,
-            uint32_t height, PixelFormat format, uint32_t usage,
-            std::string requestorName, status_t* error) {
+            uint32_t height, PixelFormat format, uint32_t layerCount,
+            uint32_t usage, std::string requestorName, status_t* error) {
         Parcel data, reply;
         data.writeInterfaceToken(IGraphicBufferAlloc::getInterfaceDescriptor());
         data.writeUint32(width);
         data.writeUint32(height);
         data.writeInt32(static_cast<int32_t>(format));
+        data.writeUint32(layerCount);
         data.writeUint32(usage);
         if (requestorName.empty()) {
             requestorName += "[PID ";
@@ -106,12 +107,13 @@
             uint32_t width = data.readUint32();
             uint32_t height = data.readUint32();
             PixelFormat format = static_cast<PixelFormat>(data.readInt32());
+            uint32_t layerCount = data.readUint32();
             uint32_t usage = data.readUint32();
             status_t error = NO_ERROR;
             std::string requestorName;
             data.readUtf8FromUtf16(&requestorName);
             sp<GraphicBuffer> result = createGraphicBuffer(width, height,
-                    format, usage, requestorName, &error);
+                    format, layerCount, usage, requestorName, &error);
             reply->writeInt32(error);
             if (result != 0) {
                 reply->write(*result);
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index 0de60c9..1aa03a5 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -140,6 +140,14 @@
     EXPECT_EQ(NATIVE_WINDOW_SURFACE, result);
 }
 
+TEST_F(SurfaceTest, LayerCountIsOne) {
+    sp<ANativeWindow> anw(mSurface);
+    int result = -123;
+    int err = anw->query(anw.get(), NATIVE_WINDOW_LAYER_COUNT, &result);
+    EXPECT_EQ(NO_ERROR, err);
+    EXPECT_EQ(1, result);
+}
+
 TEST_F(SurfaceTest, QueryConsumerUsage) {
     const int TEST_USAGE_FLAGS =
             GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_HW_RENDER;
diff --git a/libs/ui/Gralloc1.cpp b/libs/ui/Gralloc1.cpp
index 4c73ce4..367d1ce 100644
--- a/libs/ui/Gralloc1.cpp
+++ b/libs/ui/Gralloc1.cpp
@@ -77,6 +77,17 @@
             mShimDevice.mDevice, mDeviceId, format, &mFormat);
 }
 
+gralloc1_error_t Descriptor::setLayerCount(uint32_t layerCount)
+{
+    if (mShimDevice.hasCapability(GRALLOC1_CAPABILITY_LAYERED_BUFFERS)) {
+        return setHelper<uint32_t>(mShimDevice.mFunctions.setLayerCount.pfn,
+                mShimDevice.mDevice, mDeviceId, layerCount, &mLayerCount);
+    } else {
+        // Layered buffers are not supported on this device.
+        return GRALLOC1_ERROR_UNSUPPORTED;
+    }
+}
+
 gralloc1_error_t Descriptor::setProducerUsage(gralloc1_producer_usage_t usage)
 {
     return setHelper<uint64_t>(mShimDevice.mFunctions.setProducerUsage.pfn,
@@ -366,6 +377,15 @@
         mFunctions.allocate.load(mDevice, false);
     }
 
+    if (hasCapability(GRALLOC1_CAPABILITY_LAYERED_BUFFERS)) {
+        if (!mFunctions.setLayerCount.load(mDevice, true)) {
+            return false;
+        }
+        if (!mFunctions.getLayerCount.load(mDevice, true)) {
+            return false;
+        }
+    }
+
     return true;
 }
 
diff --git a/libs/ui/Gralloc1On0Adapter.cpp b/libs/ui/Gralloc1On0Adapter.cpp
index d5b88de..111879a 100644
--- a/libs/ui/Gralloc1On0Adapter.cpp
+++ b/libs/ui/Gralloc1On0Adapter.cpp
@@ -97,6 +97,8 @@
             return asFP<GRALLOC1_PFN_SET_DIMENSIONS>(setDimensionsHook);
         case GRALLOC1_FUNCTION_SET_FORMAT:
             return asFP<GRALLOC1_PFN_SET_FORMAT>(setFormatHook);
+        case GRALLOC1_FUNCTION_SET_LAYER_COUNT:
+            return asFP<GRALLOC1_PFN_SET_LAYER_COUNT>(setLayerCountHook);
         case GRALLOC1_FUNCTION_SET_PRODUCER_USAGE:
             return asFP<GRALLOC1_PFN_SET_PRODUCER_USAGE>(setProducerUsageHook);
         case GRALLOC1_FUNCTION_GET_BACKING_STORE:
@@ -113,6 +115,10 @@
             return asFP<GRALLOC1_PFN_GET_FORMAT>(
                     bufferHook<decltype(&Buffer::getFormat),
                     &Buffer::getFormat, int32_t*>);
+        case GRALLOC1_FUNCTION_GET_LAYER_COUNT:
+            return asFP<GRALLOC1_PFN_GET_LAYER_COUNT>(
+                    bufferHook<decltype(&Buffer::getLayerCount),
+                    &Buffer::getLayerCount, uint32_t*>);
         case GRALLOC1_FUNCTION_GET_PRODUCER_USAGE:
             return asFP<GRALLOC1_PFN_GET_PRODUCER_USAGE>(getProducerUsageHook);
         case GRALLOC1_FUNCTION_GET_STRIDE:
diff --git a/libs/ui/GraphicBuffer.cpp b/libs/ui/GraphicBuffer.cpp
index 6d72900..07164a4 100644
--- a/libs/ui/GraphicBuffer.cpp
+++ b/libs/ui/GraphicBuffer.cpp
@@ -50,6 +50,7 @@
     height =
     stride =
     format =
+    layerCount =
     usage  = 0;
     handle = NULL;
 }
@@ -63,15 +64,33 @@
     height =
     stride =
     format =
+    layerCount =
     usage  = 0;
     handle = NULL;
-    mInitCheck = initSize(inWidth, inHeight, inFormat, inUsage,
+    mInitCheck = initSize(inWidth, inHeight, inFormat, 1, inUsage,
             std::move(requestorName));
 }
 
 GraphicBuffer::GraphicBuffer(uint32_t inWidth, uint32_t inHeight,
-        PixelFormat inFormat, uint32_t inUsage, uint32_t inStride,
-        native_handle_t* inHandle, bool keepOwnership)
+        PixelFormat inFormat, uint32_t inLayerCount, uint32_t inUsage,
+        std::string requestorName)
+    : BASE(), mOwner(ownData), mBufferMapper(GraphicBufferMapper::get()),
+      mInitCheck(NO_ERROR), mId(getUniqueId()), mGenerationNumber(0)
+{
+    width  =
+    height =
+    stride =
+    format =
+    layerCount =
+    usage  = 0;
+    handle = NULL;
+    mInitCheck = initSize(inWidth, inHeight, inFormat, inLayerCount, inUsage,
+            std::move(requestorName));
+}
+
+GraphicBuffer::GraphicBuffer(uint32_t inWidth, uint32_t inHeight,
+        PixelFormat inFormat, uint32_t inLayerCount, uint32_t inUsage,
+        uint32_t inStride, native_handle_t* inHandle, bool keepOwnership)
     : BASE(), mOwner(keepOwnership ? ownHandle : ownNone),
       mBufferMapper(GraphicBufferMapper::get()),
       mInitCheck(NO_ERROR), mId(getUniqueId()), mGenerationNumber(0)
@@ -80,6 +99,7 @@
     height = static_cast<int>(inHeight);
     stride = static_cast<int>(inStride);
     format = inFormat;
+    layerCount = inLayerCount;
     usage  = static_cast<int>(inUsage);
     handle = inHandle;
 }
@@ -94,6 +114,7 @@
     height = buffer->height;
     stride = buffer->stride;
     format = buffer->format;
+    layerCount = buffer->layerCount;
     usage  = buffer->usage;
     handle = buffer->handle;
 }
@@ -138,7 +159,7 @@
 }
 
 status_t GraphicBuffer::reallocate(uint32_t inWidth, uint32_t inHeight,
-        PixelFormat inFormat, uint32_t inUsage)
+        PixelFormat inFormat, uint32_t inLayerCount, uint32_t inUsage)
 {
     if (mOwner != ownData)
         return INVALID_OPERATION;
@@ -147,6 +168,7 @@
             static_cast<int>(inWidth) == width &&
             static_cast<int>(inHeight) == height &&
             inFormat == format &&
+            inLayerCount == layerCount &&
             static_cast<int>(inUsage) == usage)
         return NO_ERROR;
 
@@ -155,30 +177,34 @@
         allocator.free(handle);
         handle = 0;
     }
-    return initSize(inWidth, inHeight, inFormat, inUsage, "[Reallocation]");
+    return initSize(inWidth, inHeight, inFormat, inLayerCount, inUsage,
+            "[Reallocation]");
 }
 
 bool GraphicBuffer::needsReallocation(uint32_t inWidth, uint32_t inHeight,
-        PixelFormat inFormat, uint32_t inUsage)
+        PixelFormat inFormat, uint32_t inLayerCount, uint32_t inUsage)
 {
     if (static_cast<int>(inWidth) != width) return true;
     if (static_cast<int>(inHeight) != height) return true;
     if (inFormat != format) return true;
+    if (inLayerCount != layerCount) return true;
     if ((static_cast<uint32_t>(usage) & inUsage) != inUsage) return true;
     return false;
 }
 
 status_t GraphicBuffer::initSize(uint32_t inWidth, uint32_t inHeight,
-        PixelFormat inFormat, uint32_t inUsage, std::string requestorName)
+        PixelFormat inFormat, uint32_t inLayerCount, uint32_t inUsage,
+        std::string requestorName)
 {
     GraphicBufferAllocator& allocator = GraphicBufferAllocator::get();
     uint32_t outStride = 0;
-    status_t err = allocator.allocate(inWidth, inHeight, inFormat, inUsage,
-            &handle, &outStride, mId, std::move(requestorName));
+    status_t err = allocator.allocate(inWidth, inHeight, inFormat, inLayerCount,
+            inUsage, &handle, &outStride, mId, std::move(requestorName));
     if (err == NO_ERROR) {
         width = static_cast<int>(inWidth);
         height = static_cast<int>(inHeight);
         format = inFormat;
+        layerCount = inLayerCount;
         usage = static_cast<int>(inUsage);
         stride = static_cast<int>(outStride);
     }
@@ -284,7 +310,7 @@
 }
 
 size_t GraphicBuffer::getFlattenedSize() const {
-    return static_cast<size_t>(11 + (handle ? handle->numInts : 0)) * sizeof(int);
+    return static_cast<size_t>(12 + (handle ? handle->numInts : 0)) * sizeof(int);
 }
 
 size_t GraphicBuffer::getFdCount() const {
@@ -304,19 +330,20 @@
     buf[2] = height;
     buf[3] = stride;
     buf[4] = format;
-    buf[5] = usage;
-    buf[6] = static_cast<int32_t>(mId >> 32);
-    buf[7] = static_cast<int32_t>(mId & 0xFFFFFFFFull);
-    buf[8] = static_cast<int32_t>(mGenerationNumber);
-    buf[9] = 0;
+    buf[5] = static_cast<int32_t>(layerCount);
+    buf[6] = usage;
+    buf[7] = static_cast<int32_t>(mId >> 32);
+    buf[8] = static_cast<int32_t>(mId & 0xFFFFFFFFull);
+    buf[9] = static_cast<int32_t>(mGenerationNumber);
     buf[10] = 0;
+    buf[11] = 0;
 
     if (handle) {
-        buf[9] = handle->numFds;
-        buf[10] = handle->numInts;
+        buf[10] = handle->numFds;
+        buf[11] = handle->numInts;
         memcpy(fds, handle->data,
                 static_cast<size_t>(handle->numFds) * sizeof(int));
-        memcpy(&buf[11], handle->data + handle->numFds,
+        memcpy(&buf[12], handle->data + handle->numFds,
                 static_cast<size_t>(handle->numInts) * sizeof(int));
     }
 
@@ -332,28 +359,28 @@
 
 status_t GraphicBuffer::unflatten(
         void const*& buffer, size_t& size, int const*& fds, size_t& count) {
-    if (size < 11 * sizeof(int)) return NO_MEMORY;
+    if (size < 12 * sizeof(int)) return NO_MEMORY;
 
     int const* buf = static_cast<int const*>(buffer);
     if (buf[0] != 'GBFR') return BAD_TYPE;
 
-    const size_t numFds  = static_cast<size_t>(buf[9]);
-    const size_t numInts = static_cast<size_t>(buf[10]);
+    const size_t numFds  = static_cast<size_t>(buf[10]);
+    const size_t numInts = static_cast<size_t>(buf[11]);
 
     // Limit the maxNumber to be relatively small. The number of fds or ints
     // should not come close to this number, and the number itself was simply
     // chosen to be high enough to not cause issues and low enough to prevent
     // overflow problems.
     const size_t maxNumber = 4096;
-    if (numFds >= maxNumber || numInts >= (maxNumber - 11)) {
-        width = height = stride = format = usage = 0;
+    if (numFds >= maxNumber || numInts >= (maxNumber - 12)) {
+        width = height = stride = format = layerCount = usage = 0;
         handle = NULL;
         ALOGE("unflatten: numFds or numInts is too large: %zd, %zd",
                 numFds, numInts);
         return BAD_VALUE;
     }
 
-    const size_t sizeNeeded = (11 + numInts) * sizeof(int);
+    const size_t sizeNeeded = (12 + numInts) * sizeof(int);
     if (size < sizeNeeded) return NO_MEMORY;
 
     size_t fdCountNeeded = numFds;
@@ -369,34 +396,35 @@
         height = buf[2];
         stride = buf[3];
         format = buf[4];
-        usage  = buf[5];
+        layerCount = static_cast<uintptr_t>(buf[5]);
+        usage  = buf[6];
         native_handle* h = native_handle_create(
                 static_cast<int>(numFds), static_cast<int>(numInts));
         if (!h) {
-            width = height = stride = format = usage = 0;
+            width = height = stride = format = layerCount = usage = 0;
             handle = NULL;
             ALOGE("unflatten: native_handle_create failed");
             return NO_MEMORY;
         }
         memcpy(h->data, fds, numFds * sizeof(int));
-        memcpy(h->data + numFds, &buf[11], numInts * sizeof(int));
+        memcpy(h->data + numFds, &buf[12], numInts * sizeof(int));
         handle = h;
     } else {
-        width = height = stride = format = usage = 0;
+        width = height = stride = format = layerCount = usage = 0;
         handle = NULL;
     }
 
-    mId = static_cast<uint64_t>(buf[6]) << 32;
-    mId |= static_cast<uint32_t>(buf[7]);
+    mId = static_cast<uint64_t>(buf[7]) << 32;
+    mId |= static_cast<uint32_t>(buf[8]);
 
-    mGenerationNumber = static_cast<uint32_t>(buf[8]);
+    mGenerationNumber = static_cast<uint32_t>(buf[9]);
 
     mOwner = ownHandle;
 
     if (handle != 0) {
         status_t err = mBufferMapper.registerBuffer(this);
         if (err != NO_ERROR) {
-            width = height = stride = format = usage = 0;
+            width = height = stride = format = layerCount = usage = 0;
             handle = NULL;
             ALOGE("unflatten: registerBuffer failed: %s (%d)",
                     strerror(-err), err);
diff --git a/libs/ui/GraphicBufferAllocator.cpp b/libs/ui/GraphicBufferAllocator.cpp
index 693c7cb..e333bc1 100644
--- a/libs/ui/GraphicBufferAllocator.cpp
+++ b/libs/ui/GraphicBufferAllocator.cpp
@@ -64,15 +64,15 @@
     for (size_t i=0 ; i<c ; i++) {
         const alloc_rec_t& rec(list.valueAt(i));
         if (rec.size) {
-            snprintf(buffer, SIZE, "%10p: %7.2f KiB | %4u (%4u) x %4u | %8X | 0x%08x | %s\n",
+            snprintf(buffer, SIZE, "%10p: %7.2f KiB | %4u (%4u) x %4u | %4u | %8X | 0x%08x | %s\n",
                     list.keyAt(i), rec.size/1024.0f,
-                    rec.width, rec.stride, rec.height, rec.format, rec.usage,
-                    rec.requestorName.c_str());
+                    rec.width, rec.stride, rec.height, rec.layerCount, rec.format,
+                    rec.usage, rec.requestorName.c_str());
         } else {
-            snprintf(buffer, SIZE, "%10p: unknown     | %4u (%4u) x %4u | %8X | 0x%08x | %s\n",
+            snprintf(buffer, SIZE, "%10p: unknown     | %4u (%4u) x %4u | %4u | %8X | 0x%08x | %s\n",
                     list.keyAt(i),
-                    rec.width, rec.stride, rec.height, rec.format, rec.usage,
-                    rec.requestorName.c_str());
+                    rec.width, rec.stride, rec.height, rec.layerCount, rec.format,
+                    rec.usage, rec.requestorName.c_str());
         }
         result.append(buffer);
         total += rec.size;
@@ -103,21 +103,22 @@
 public:
     HalBuffer(const Gralloc2::Allocator* allocator,
             uint32_t width, uint32_t height,
-            PixelFormat format, uint32_t usage)
+            PixelFormat format, uint32_t layerCount, uint32_t usage)
         : mAllocator(allocator), mBufferValid(false)
     {
         Gralloc2::IAllocator::BufferDescriptorInfo info = {};
         info.width = width;
         info.height = height;
         info.format = static_cast<Gralloc2::PixelFormat>(format);
+        info.layerCount = layerCount;
         info.producerUsageMask = usage;
         info.consumerUsageMask = usage;
 
         Gralloc2::BufferDescriptor descriptor;
         auto error = mAllocator->createBufferDescriptor(info, descriptor);
         if (error != Gralloc2::Error::NONE) {
-            ALOGE("Failed to create desc (%u x %u) format %d usage %u: %d",
-                    width, height, format, usage, error);
+            ALOGE("Failed to create desc (%u x %u) layerCount %u format %d usage %u: %d",
+                    width, height, layerCount, format, usage, error);
             return;
         }
 
@@ -127,8 +128,8 @@
         }
 
         if (error != Gralloc2::Error::NONE) {
-            ALOGE("Failed to allocate (%u x %u) format %d usage %u: %d",
-                    width, height, format, usage, error);
+            ALOGE("Failed to allocate (%u x %u) layerCount %u format %d usage %u: %d",
+                    width, height, layerCount, format, usage, error);
             mAllocator->destroyBufferDescriptor(descriptor);
             return;
         }
@@ -195,8 +196,9 @@
 } // namespace
 
 status_t GraphicBufferAllocator::allocate(uint32_t width, uint32_t height,
-        PixelFormat format, uint32_t usage, buffer_handle_t* handle,
-        uint32_t* stride, uint64_t graphicBufferId, std::string requestorName)
+        PixelFormat format, uint32_t layerCount, uint32_t usage,
+        buffer_handle_t* handle, uint32_t* stride, uint64_t graphicBufferId,
+        std::string requestorName)
 {
     ATRACE_CALL();
 
@@ -205,12 +207,17 @@
     if (!width || !height)
         width = height = 1;
 
+    // Ensure that layerCount is valid.
+    if (layerCount < 1)
+        layerCount = 1;
+
     // Filter out any usage bits that should not be passed to the gralloc module
     usage &= GRALLOC_USAGE_ALLOC_MASK;
 
     gralloc1_error_t error;
     if (mAllocator->valid()) {
-        HalBuffer buffer(mAllocator.get(), width, height, format, usage);
+        HalBuffer buffer(mAllocator.get(), width, height, format, layerCount,
+                usage);
         if (!buffer.exportHandle(mMapper, handle, stride)) {
             return NO_MEMORY;
         }
@@ -229,6 +236,17 @@
             ALOGE("Failed to set format to %d: %d", format, error);
             return BAD_VALUE;
         }
+        if (mDevice->hasCapability(GRALLOC1_CAPABILITY_LAYERED_BUFFERS)) {
+            error = descriptor->setLayerCount(layerCount);
+            if (error != GRALLOC1_ERROR_NONE) {
+                ALOGE("Failed to set layer count to %u: %d", layerCount, error);
+                return BAD_VALUE;
+            }
+        } else if (layerCount > 1) {
+            ALOGE("Failed to set layer count to %u: capability unsupported",
+                    layerCount);
+            return BAD_VALUE;
+        }
         error = descriptor->setProducerUsage(
                 static_cast<gralloc1_producer_usage_t>(usage));
         if (error != GRALLOC1_ERROR_NONE) {
@@ -244,8 +262,8 @@
 
         error = mDevice->allocate(descriptor, graphicBufferId, handle);
         if (error != GRALLOC1_ERROR_NONE) {
-            ALOGE("Failed to allocate (%u x %u) format %d usage %u: %d",
-                    width, height, format, usage, error);
+            ALOGE("Failed to allocate (%u x %u) layerCount %u format %d usage %u: %d",
+                    width, height, layerCount, format, usage, error);
             return NO_MEMORY;
         }
 
@@ -264,6 +282,7 @@
         rec.height = height;
         rec.stride = *stride;
         rec.format = format;
+        rec.layerCount = layerCount;
         rec.usage = usage;
         rec.size = static_cast<size_t>(height * (*stride) * bpp);
         rec.requestorName = std::move(requestorName);