dvrapi: Pass layer_count down

* We were missing layer count, which would prevent multiview
  from working

Bug: 37245304
Test: MultiLayerBufferQueue
Change-Id: I88b41f1aa7665df01e89a7386cbc23b15c9a79b0
diff --git a/libs/vr/libbufferhub/buffer_hub_client.cpp b/libs/vr/libbufferhub/buffer_hub_client.cpp
index 0326084..a09a7a1 100644
--- a/libs/vr/libbufferhub/buffer_hub_client.cpp
+++ b/libs/vr/libbufferhub/buffer_hub_client.cpp
@@ -59,10 +59,8 @@
     ALOGE("BufferHubBuffer::ImportBuffer: Failed to get buffer: %s",
           status.GetErrorMessage().c_str());
     return -status.error();
-  } else if (status.get().id() >= 0) {
-    ALOGE(
-        "BufferHubBuffer::ImportBuffer: Expected to receive a buffer handle "
-        "but got null!");
+  } else if (status.get().id() < 0) {
+    ALOGE("BufferHubBuffer::ImportBuffer: Received an invalid id!");
     return -EIO;
   }
 
diff --git a/libs/vr/libbufferhub/include/private/dvr/bufferhub_rpc.h b/libs/vr/libbufferhub/include/private/dvr/bufferhub_rpc.h
index 6fee7a0..ffdc9e2 100644
--- a/libs/vr/libbufferhub/include/private/dvr/bufferhub_rpc.h
+++ b/libs/vr/libbufferhub/include/private/dvr/bufferhub_rpc.h
@@ -23,6 +23,7 @@
         stride_(buffer.stride()),
         width_(buffer.width()),
         height_(buffer.height()),
+        layer_count_(buffer.layer_count()),
         format_(buffer.format()),
         usage_(buffer.usage()) {
     // Populate the fd and int vectors: native_handle->data[] is an array of fds
@@ -47,9 +48,10 @@
     for (const auto& fd : fds_)
       fd_ints.push_back(fd.Get());
 
-    const int ret = buffer->Import(fd_ints.data(), fd_ints.size(),
-                                   opaque_ints_.data(), opaque_ints_.size(),
-                                   width_, height_, stride_, format_, usage_);
+    const int ret =
+        buffer->Import(fd_ints.data(), fd_ints.size(), opaque_ints_.data(),
+                       opaque_ints_.size(), width_, height_, layer_count_,
+                       stride_, format_, usage_);
     if (ret < 0)
       return ret;
 
@@ -72,6 +74,7 @@
   uint32_t stride_;
   uint32_t width_;
   uint32_t height_;
+  uint32_t layer_count_;
   uint32_t format_;
   uint64_t usage_;
   std::vector<int> opaque_ints_;
@@ -83,8 +86,8 @@
   }
 
   PDX_SERIALIZABLE_MEMBERS(NativeBufferHandle<FileHandleType>, id_, stride_,
-                           width_, height_, format_, usage_, opaque_ints_,
-                           fds_);
+                           width_, height_, layer_count_, format_, usage_,
+                           opaque_ints_, fds_);
 
   NativeBufferHandle(const NativeBufferHandle&) = delete;
   void operator=(const NativeBufferHandle&) = delete;
@@ -224,8 +227,8 @@
   PDX_REMOTE_METHOD(ProducerQueueAllocateBuffers,
                     kOpProducerQueueAllocateBuffers,
                     std::vector<std::pair<LocalChannelHandle, size_t>>(
-                        uint32_t width, uint32_t height, uint32_t format,
-                        uint64_t usage, size_t buffer_count));
+                        uint32_t width, uint32_t height, uint32_t layer_count,
+                        uint32_t format, uint64_t usage, size_t buffer_count));
   PDX_REMOTE_METHOD(ProducerQueueDetachBuffer, kOpProducerQueueDetachBuffer,
                     void(size_t slot));
   PDX_REMOTE_METHOD(ConsumerQueueImportBuffers, kOpConsumerQueueImportBuffers,
diff --git a/libs/vr/libbufferhub/include/private/dvr/ion_buffer.h b/libs/vr/libbufferhub/include/private/dvr/ion_buffer.h
index 72c8d81..0d337f7 100644
--- a/libs/vr/libbufferhub/include/private/dvr/ion_buffer.h
+++ b/libs/vr/libbufferhub/include/private/dvr/ion_buffer.h
@@ -16,8 +16,8 @@
   IonBuffer(buffer_handle_t handle, uint32_t width, uint32_t height,
             uint32_t stride, uint32_t format, uint64_t usage);
   IonBuffer(buffer_handle_t handle, uint32_t width, uint32_t height,
-            uint32_t layer_count, uint32_t stride, uint32_t layer_stride,
-            uint32_t format, uint64_t usage);
+            uint32_t layer_count, uint32_t stride, uint32_t format,
+            uint64_t usage);
   ~IonBuffer();
 
   IonBuffer(IonBuffer&& other);
@@ -31,25 +31,29 @@
   // previous native handle if necessary. Returns 0 on success or a negative
   // errno code otherwise. If allocation fails the previous native handle is
   // left intact.
-  int Alloc(uint32_t width, uint32_t height, uint32_t format, uint64_t usage);
+  int Alloc(uint32_t width, uint32_t height, uint32_t layer_count,
+            uint32_t format, uint64_t usage);
 
   // Resets the underlying native handle and parameters, freeing the previous
   // native handle if necessary.
   void Reset(buffer_handle_t handle, uint32_t width, uint32_t height,
-             uint32_t stride, uint32_t format, uint64_t usage);
+             uint32_t layer_count, uint32_t stride, uint32_t format,
+             uint64_t usage);
 
   // Like Reset but also registers the native handle, which is necessary for
   // native handles received over IPC. Returns 0 on success or a negative errno
   // code otherwise. If import fails the previous native handle is left intact.
   int Import(buffer_handle_t handle, uint32_t width, uint32_t height,
-             uint32_t stride, uint32_t format, uint64_t usage);
+             uint32_t layer_count, uint32_t stride, uint32_t format,
+             uint64_t usage);
 
   // Like Reset but imports a native handle from raw fd and int arrays. Returns
   // 0 on success or a negative errno code otherwise. If import fails the
   // previous native handle is left intact.
   int Import(const int* fd_array, int fd_count, const int* int_array,
-             int int_count, uint32_t width, uint32_t height, uint32_t stride,
-             uint32_t format, uint64_t usage);
+             int int_count, uint32_t width, uint32_t height,
+             uint32_t layer_count, uint32_t stride, uint32_t format,
+             uint64_t usage);
 
   // Duplicates the native handle underlying |other| and then imports it. This
   // is useful for creating multiple, independent views of the same Ion/Gralloc
@@ -72,7 +76,6 @@
     return buffer_.get() ? buffer_->getLayerCount() : 0;
   }
   uint32_t stride() const { return buffer_.get() ? buffer_->getStride() : 0; }
-  uint32_t layer_stride() const { return 0; }
   uint32_t format() const {
     return buffer_.get() ? buffer_->getPixelFormat() : 0;
   }
diff --git a/libs/vr/libbufferhub/ion_buffer.cpp b/libs/vr/libbufferhub/ion_buffer.cpp
index 716ab42..cbaa24a 100644
--- a/libs/vr/libbufferhub/ion_buffer.cpp
+++ b/libs/vr/libbufferhub/ion_buffer.cpp
@@ -15,36 +15,36 @@
 namespace android {
 namespace dvr {
 
-IonBuffer::IonBuffer() : IonBuffer(nullptr, 0, 0, 0, 0, 0, 0, 0) {}
+IonBuffer::IonBuffer() : IonBuffer(nullptr, 0, 0, 0, 0, 0, 0) {}
 
 IonBuffer::IonBuffer(uint32_t width, uint32_t height, uint32_t format,
                      uint64_t usage)
     : IonBuffer() {
-  Alloc(width, height, format, usage);
+  Alloc(width, height, kDefaultGraphicBufferLayerCount, format, usage);
 }
 
 IonBuffer::IonBuffer(buffer_handle_t handle, uint32_t width, uint32_t height,
                      uint32_t stride, uint32_t format, uint64_t usage)
-    : IonBuffer(handle, width, height, 1, stride, 0, format, usage) {}
+    : IonBuffer(handle, width, height, kDefaultGraphicBufferLayerCount, stride,
+                format, usage) {}
 
 IonBuffer::IonBuffer(buffer_handle_t handle, uint32_t width, uint32_t height,
-                     uint32_t layer_count, uint32_t stride,
-                     uint32_t layer_stride, uint32_t format, uint64_t usage)
+                     uint32_t layer_count, uint32_t stride, uint32_t format,
+                     uint64_t usage)
     : buffer_(nullptr) {
   ALOGD_IF(TRACE,
            "IonBuffer::IonBuffer: handle=%p width=%u height=%u layer_count=%u "
-           "stride=%u layer stride=%u format=%u usage=%" PRIx64,
-           handle, width, height, layer_count, stride, layer_stride, format,
-           usage);
+           "stride=%u format=%u usage=%" PRIx64,
+           handle, width, height, layer_count, stride, format, usage);
   if (handle != 0) {
-    Import(handle, width, height, stride, format, usage);
+    Import(handle, width, height, layer_count, stride, format, usage);
   }
 }
 
 IonBuffer::~IonBuffer() {
   ALOGD_IF(TRACE,
            "IonBuffer::~IonBuffer: handle=%p width=%u height=%u stride=%u "
-           "format=%u usage=%x",
+           "format=%u usage=%" PRIx64,
            handle(), width(), height(), stride(), format(), usage());
   FreeHandle();
 }
@@ -71,14 +71,14 @@
   }
 }
 
-int IonBuffer::Alloc(uint32_t width, uint32_t height, uint32_t format,
-                     uint64_t usage) {
+int IonBuffer::Alloc(uint32_t width, uint32_t height, uint32_t layer_count,
+                     uint32_t format, uint64_t usage) {
   ALOGD_IF(TRACE,
-           "IonBuffer::Alloc: width=%u height=%u format=%u usage=%" PRIx64,
-           width, height, format, usage);
+           "IonBuffer::Alloc: width=%u height=%u layer_count=%u format=%u "
+           "usage=%" PRIx64, width, height, layer_count, format, usage);
 
-  sp<GraphicBuffer> buffer = new GraphicBuffer(
-      width, height, format, kDefaultGraphicBufferLayerCount, usage);
+  sp<GraphicBuffer> buffer =
+      new GraphicBuffer(width, height, format, layer_count, usage);
   if (buffer->initCheck() != OK) {
     ALOGE("IonBuffer::Aloc: Failed to allocate buffer");
     return -EINVAL;
@@ -89,26 +89,27 @@
 }
 
 void IonBuffer::Reset(buffer_handle_t handle, uint32_t width, uint32_t height,
-                      uint32_t stride, uint32_t format, uint64_t usage) {
+                      uint32_t layer_count, uint32_t stride, uint32_t format,
+                      uint64_t usage) {
   ALOGD_IF(TRACE,
-           "IonBuffer::Reset: handle=%p width=%u height=%u stride=%u format=%u "
-           "usage=%" PRIx64,
-           handle, width, height, stride, format, usage);
-  Import(handle, width, height, stride, format, usage);
+           "IonBuffer::Reset: handle=%p width=%u height=%u layer_count=%u "
+           "stride=%u format=%u usage=%" PRIx64,
+           handle, width, height, layer_count, stride, format, usage);
+  Import(handle, width, height, layer_count, stride, format, usage);
 }
 
 int IonBuffer::Import(buffer_handle_t handle, uint32_t width, uint32_t height,
-                      uint32_t stride, uint32_t format, uint64_t usage) {
+                      uint32_t layer_count, uint32_t stride, uint32_t format,
+                      uint64_t usage) {
   ATRACE_NAME("IonBuffer::Import1");
-  ALOGD_IF(
-      TRACE,
-      "IonBuffer::Import: handle=%p width=%u height=%u stride=%u format=%u "
-      "usage=%" PRIx64,
-      handle, width, height, stride, format, usage);
+  ALOGD_IF(TRACE,
+           "IonBuffer::Import: handle=%p width=%u height=%u layer_count=%u "
+           "stride=%u format=%u usage=%" PRIx64,
+           handle, width, height, layer_count, stride, format, usage);
   FreeHandle();
-  sp<GraphicBuffer> buffer = new GraphicBuffer(
-      handle, GraphicBuffer::TAKE_UNREGISTERED_HANDLE, width, height, format,
-      kDefaultGraphicBufferLayerCount, usage, stride);
+  sp<GraphicBuffer> buffer =
+      new GraphicBuffer(handle, GraphicBuffer::TAKE_UNREGISTERED_HANDLE, width,
+                        height, format, layer_count, usage, stride);
   if (buffer->initCheck() != OK) {
     ALOGE("IonBuffer::Import: Failed to import buffer");
     return -EINVAL;
@@ -120,12 +121,14 @@
 
 int IonBuffer::Import(const int* fd_array, int fd_count, const int* int_array,
                       int int_count, uint32_t width, uint32_t height,
-                      uint32_t stride, uint32_t format, uint64_t usage) {
+                      uint32_t layer_count, uint32_t stride, uint32_t format,
+                      uint64_t usage) {
   ATRACE_NAME("IonBuffer::Import2");
   ALOGD_IF(TRACE,
            "IonBuffer::Import: fd_count=%d int_count=%d width=%u height=%u "
-           "stride=%u format=%u usage=%" PRIx64,
-           fd_count, int_count, width, height, stride, format, usage);
+           "layer_count=%u stride=%u format=%u usage=%" PRIx64,
+           fd_count, int_count, width, height, layer_count, stride, format,
+           usage);
 
   if (fd_count < 0 || int_count < 0) {
     ALOGE("IonBuffer::Import: invalid arguments.");
@@ -143,7 +146,8 @@
   memcpy(handle->data, fd_array, sizeof(int) * fd_count);
   memcpy(handle->data + fd_count, int_array, sizeof(int) * int_count);
 
-  const int ret = Import(handle, width, height, stride, format, usage);
+  const int ret =
+      Import(handle, width, height, layer_count, stride, format, usage);
   if (ret < 0) {
     ALOGE("IonBuffer::Import: failed to import raw native handle: %s",
           strerror(-ret));
@@ -179,8 +183,8 @@
          sizeof(int) * int_count);
 
   const int ret =
-      Import(handle, other->width(), other->height(), other->stride(),
-             other->format(), other->usage());
+      Import(handle, other->width(), other->height(), other->layer_count(),
+             other->stride(), other->format(), other->usage());
   if (ret < 0) {
     ALOGE("IonBuffer::Duplicate: Failed to import duplicate native handle: %s",
           strerror(-ret));
diff --git a/libs/vr/libbufferhub/mocks/ion_buffer/private/dvr/ion_buffer.h b/libs/vr/libbufferhub/mocks/ion_buffer/private/dvr/ion_buffer.h
index fac6db0..8929c95 100644
--- a/libs/vr/libbufferhub/mocks/ion_buffer/private/dvr/ion_buffer.h
+++ b/libs/vr/libbufferhub/mocks/ion_buffer/private/dvr/ion_buffer.h
@@ -17,10 +17,11 @@
   IonBufferMock() {}
   MOCK_METHOD0(GetGrallocModuleImpl, gralloc_module_t const*());
   MOCK_METHOD6(Import, int(buffer_handle_t handle, int width, int height,
-                           int stride, int format, int usage));
-  MOCK_METHOD9(Import, int(const int* fd_array, int fd_count,
-                           const int* int_array, int int_count, int width,
-                           int height, int stride, int format, int usage));
+                           int layer_count, int stride, int format, int usage));
+  MOCK_METHOD9(Import,
+               int(const int* fd_array, int fd_count, const int* int_array,
+                   int int_count, int width, int height, int layer_count,
+                   int stride, int format, int usage));
   MOCK_METHOD6(Lock, int(int usage, int x, int y, int width, int height,
                          void** address));
   MOCK_METHOD0(Unlock, int());
@@ -29,7 +30,6 @@
   MOCK_CONST_METHOD0(height, int());
   MOCK_CONST_METHOD0(layer_count, int());
   MOCK_CONST_METHOD0(stride, int());
-  MOCK_CONST_METHOD0(layer_stride, int());
   MOCK_CONST_METHOD0(format, int());
   MOCK_CONST_METHOD0(usage, int());
 };
@@ -46,15 +46,16 @@
   static gralloc_module_t const* GetGrallocModule() {
     return staticObject->GetGrallocModuleImpl();
   }
-  int Import(buffer_handle_t handle, int width, int height, int stride,
-             int format, int usage) {
-    return mock_->Import(handle, width, height, stride, format, usage);
+  int Import(buffer_handle_t handle, int width, int height, int layer_count,
+             int stride, int format, int usage) {
+    return mock_->Import(handle, width, height, layer_count, stride, format,
+                         usage);
   }
   int Import(const int* fd_array, int fd_count, const int* int_array,
-             int int_count, int width, int height, int stride, int format,
-             int usage) {
+             int int_count, int width, int height, int layer_count, int stride,
+             int format, int usage) {
     return mock_->Import(fd_array, fd_count, int_array, int_count, width,
-                         height, stride, format, usage);
+                         height, layer_count, stride, format, usage);
   }
   int Lock(int usage, int x, int y, int width, int height, void** address) {
     return mock_->Lock(usage, x, y, width, height, address);
@@ -65,7 +66,6 @@
   int height() const { return mock_->height(); }
   int layer_count() const { return mock_->layer_count(); }
   int stride() const { return mock_->stride(); }
-  int layer_stride() const { return mock_->layer_stride(); }
   int format() const { return mock_->format(); }
   int usage() const { return mock_->usage(); }
   std::unique_ptr<IonBufferMock> mock_;
diff --git a/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp b/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp
index a081af0..012a4e7 100644
--- a/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp
+++ b/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp
@@ -389,8 +389,8 @@
 }
 
 int ProducerQueue::AllocateBuffer(uint32_t width, uint32_t height,
-                                  uint32_t format, uint64_t usage,
-                                  size_t* out_slot) {
+                                  uint32_t layer_count, uint32_t format,
+                                  uint64_t usage, size_t* out_slot) {
   if (out_slot == nullptr) {
     ALOGE("ProducerQueue::AllocateBuffer: Parameter out_slot cannot be null.");
     return -EINVAL;
@@ -405,7 +405,7 @@
   const size_t kBufferCount = 1U;
   Status<std::vector<std::pair<LocalChannelHandle, size_t>>> status =
       InvokeRemoteMethod<BufferHubRPC::ProducerQueueAllocateBuffers>(
-          width, height, format, usage, kBufferCount);
+          width, height, layer_count, format, usage, kBufferCount);
   if (!status) {
     ALOGE("ProducerQueue::AllocateBuffer failed to create producer buffer: %s",
           status.GetErrorMessage().c_str());
diff --git a/libs/vr/libbufferhubqueue/buffer_hub_queue_core.cpp b/libs/vr/libbufferhubqueue/buffer_hub_queue_core.cpp
index 8e9501a..31cccf0 100644
--- a/libs/vr/libbufferhubqueue/buffer_hub_queue_core.cpp
+++ b/libs/vr/libbufferhubqueue/buffer_hub_queue_core.cpp
@@ -33,13 +33,15 @@
       unique_id_(getUniqueId()) {}
 
 status_t BufferHubQueueCore::AllocateBuffer(uint32_t width, uint32_t height,
+                                            uint32_t layer_count,
                                             PixelFormat format,
-                                            uint32_t usage) {
+                                            uint64_t usage) {
   size_t slot;
 
   // Allocate new buffer through BufferHub and add it into |producer_| queue for
   // bookkeeping.
-  if (producer_->AllocateBuffer(width, height, format, usage, &slot) < 0) {
+  if (producer_->AllocateBuffer(width, height, layer_count, format, usage,
+                                &slot) < 0) {
     ALOGE("Failed to allocate new buffer in BufferHub.");
     return NO_MEMORY;
   }
diff --git a/libs/vr/libbufferhubqueue/buffer_hub_queue_producer.cpp b/libs/vr/libbufferhubqueue/buffer_hub_queue_producer.cpp
index c886c27..64a7944 100644
--- a/libs/vr/libbufferhubqueue/buffer_hub_queue_producer.cpp
+++ b/libs/vr/libbufferhubqueue/buffer_hub_queue_producer.cpp
@@ -121,6 +121,7 @@
     return NO_INIT;
   }
 
+  const uint32_t kLayerCount = 1;
   if (static_cast<int32_t>(core_->producer_->capacity()) <
       max_dequeued_buffer_count_ +
           BufferHubQueueCore::kDefaultUndequeuedBuffers) {
@@ -128,7 +129,7 @@
     // |max_dequeued_buffer_count_|, allocate new buffer.
     // TODO(jwcai) To save memory, the really reasonable thing to do is to go
     // over existing slots and find first existing one to dequeue.
-    ret = core_->AllocateBuffer(width, height, format, usage);
+    ret = core_->AllocateBuffer(width, height, kLayerCount, format, usage);
     if (ret < 0)
       return ret;
   }
@@ -172,7 +173,7 @@
     // there are already multiple buffers in the queue, the next one returned
     // from |core_->producer_->Dequeue| may not be the new buffer we just
     // reallocated. Retry up to BufferHubQueue::kMaxQueueCapacity times.
-    ret = core_->AllocateBuffer(width, height, format, usage);
+    ret = core_->AllocateBuffer(width, height, kLayerCount, format, usage);
     if (ret < 0)
       return ret;
   }
diff --git a/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_client.h b/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_client.h
index f9f742e..ed67f79 100644
--- a/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_client.h
+++ b/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_client.h
@@ -336,8 +336,8 @@
   // use (i.e. in |Gain|'ed mode).
   // Returns Zero on success and negative error code when buffer allocation
   // fails.
-  int AllocateBuffer(uint32_t width, uint32_t height, uint32_t format,
-                     uint64_t usage, size_t* out_slot);
+  int AllocateBuffer(uint32_t width, uint32_t height, uint32_t layer_count,
+                     uint32_t format, uint64_t usage, size_t* out_slot);
 
   // Add a producer buffer to populate the queue. Once added, a producer buffer
   // is available to use (i.e. in |Gain|'ed mode).
diff --git a/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_core.h b/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_core.h
index e48b014..180906b 100644
--- a/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_core.h
+++ b/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_core.h
@@ -118,8 +118,8 @@
   BufferHubQueueCore();
 
   // Allocate a new buffer producer through BufferHub.
-  int AllocateBuffer(uint32_t width, uint32_t height, PixelFormat format,
-                     uint32_t usage);
+  int AllocateBuffer(uint32_t width, uint32_t height, uint32_t layer_count,
+                     PixelFormat format, uint64_t usage);
 
   // Detach a buffer producer through BufferHub.
   int DetachBuffer(size_t slot);
diff --git a/libs/vr/libbufferhubqueue/tests/buffer_hub_queue-test.cpp b/libs/vr/libbufferhubqueue/tests/buffer_hub_queue-test.cpp
index dcfefa4..fe0b12a 100644
--- a/libs/vr/libbufferhubqueue/tests/buffer_hub_queue-test.cpp
+++ b/libs/vr/libbufferhubqueue/tests/buffer_hub_queue-test.cpp
@@ -15,6 +15,7 @@
 
 constexpr int kBufferWidth = 100;
 constexpr int kBufferHeight = 1;
+constexpr int kBufferLayerCount = 1;
 constexpr int kBufferFormat = HAL_PIXEL_FORMAT_BLOB;
 constexpr int kBufferUsage = GRALLOC_USAGE_SW_READ_RARELY;
 
@@ -54,7 +55,8 @@
     // Create producer buffer.
     size_t slot;
     int ret = producer_queue_->AllocateBuffer(kBufferWidth, kBufferHeight,
-                                              kBufferFormat, kBufferUsage, &slot);
+                                              kBufferLayerCount, kBufferFormat,
+                                              kBufferUsage, &slot);
     ASSERT_EQ(ret, 0);
   }
 
@@ -345,9 +347,9 @@
 
   // When allocation, leave out |set_mask| from usage bits on purpose.
   size_t slot;
-  int ret = producer_queue_->AllocateBuffer(
-      kBufferWidth, kBufferHeight, kBufferFormat, kBufferUsage & ~set_mask,
-      &slot);
+  int ret = producer_queue_->AllocateBuffer(kBufferWidth, kBufferHeight,
+                                            kBufferFormat, kBufferLayerCount,
+                                            kBufferUsage & ~set_mask, &slot);
   ASSERT_EQ(0, ret);
 
   LocalHandle fence;
@@ -363,9 +365,9 @@
 
   // When allocation, add |clear_mask| into usage bits on purpose.
   size_t slot;
-  int ret = producer_queue_->AllocateBuffer(
-      kBufferWidth, kBufferHeight, kBufferFormat, kBufferUsage | clear_mask,
-      &slot);
+  int ret = producer_queue_->AllocateBuffer(kBufferWidth, kBufferHeight,
+                                            kBufferLayerCount, kBufferFormat,
+                                            kBufferUsage | clear_mask, &slot);
   ASSERT_EQ(0, ret);
 
   LocalHandle fence;
@@ -383,14 +385,14 @@
   // be able to succeed.
   size_t slot;
   int ret = producer_queue_->AllocateBuffer(
-      kBufferWidth, kBufferHeight, kBufferFormat, kBufferUsage & ~deny_set_mask,
-      &slot);
+      kBufferWidth, kBufferHeight, kBufferLayerCount, kBufferFormat,
+      kBufferUsage & ~deny_set_mask, &slot);
   ASSERT_EQ(ret, 0);
 
   // While allocation with those bits should fail.
-  ret = producer_queue_->AllocateBuffer(
-      kBufferWidth, kBufferHeight, kBufferFormat, kBufferUsage | deny_set_mask,
-      &slot);
+  ret = producer_queue_->AllocateBuffer(kBufferWidth, kBufferHeight,
+                                        kBufferLayerCount, kBufferFormat,
+                                        kBufferUsage | deny_set_mask, &slot);
   ASSERT_EQ(ret, -EINVAL);
 }
 
@@ -402,14 +404,14 @@
   // mandatory), allocation with those bits should be able to succeed.
   size_t slot;
   int ret = producer_queue_->AllocateBuffer(
-      kBufferWidth, kBufferHeight, kBufferFormat,
+      kBufferWidth, kBufferHeight, kBufferLayerCount, kBufferFormat,
       kBufferUsage | deny_clear_mask, &slot);
   ASSERT_EQ(ret, 0);
 
   // While allocation without those bits should fail.
-  ret = producer_queue_->AllocateBuffer(
-      kBufferWidth, kBufferHeight, kBufferFormat,
-      kBufferUsage & ~deny_clear_mask, &slot);
+  ret = producer_queue_->AllocateBuffer(kBufferWidth, kBufferHeight,
+                                        kBufferLayerCount, kBufferFormat,
+                                        kBufferUsage & ~deny_clear_mask, &slot);
   ASSERT_EQ(ret, -EINVAL);
 }
 
diff --git a/libs/vr/libdisplay/display_client.cpp b/libs/vr/libdisplay/display_client.cpp
index eaf919e..5c9ebd4 100644
--- a/libs/vr/libdisplay/display_client.cpp
+++ b/libs/vr/libdisplay/display_client.cpp
@@ -123,15 +123,13 @@
   return {std::move(producer_queue)};
 }
 
-Status<std::unique_ptr<ProducerQueue>> Surface::CreateQueue(uint32_t width,
-                                                            uint32_t height,
-                                                            uint32_t format,
-                                                            uint64_t usage,
-                                                            size_t capacity) {
+Status<std::unique_ptr<ProducerQueue>> Surface::CreateQueue(
+    uint32_t width, uint32_t height, uint32_t layer_count, uint32_t format,
+    uint64_t usage, size_t capacity) {
   ALOGD_IF(TRACE,
-           "Surface::CreateQueue: width=%u height=%u format=%u usage=%" PRIx64
-           " capacity=%zu",
-           width, height, format, usage, capacity);
+           "Surface::CreateQueue: width=%u height=%u layer_count=%u format=%u "
+           "usage=%" PRIx64 " capacity=%zu",
+           width, height, layer_count, format, usage, capacity);
   auto status = CreateQueue();
   if (!status)
     return status.error_status();
@@ -141,8 +139,8 @@
   ALOGD_IF(TRACE, "Surface::CreateQueue: Allocating %zu buffers...", capacity);
   for (size_t i = 0; i < capacity; i++) {
     size_t slot;
-    const int ret =
-        producer_queue->AllocateBuffer(width, height, format, usage, &slot);
+    const int ret = producer_queue->AllocateBuffer(width, height, layer_count,
+                                                   format, usage, &slot);
     if (ret < 0) {
       ALOGE(
           "Surface::CreateQueue: Failed to allocate buffer on queue_id=%d: %s",
diff --git a/libs/vr/libdisplay/graphics.cpp b/libs/vr/libdisplay/graphics.cpp
index 58a906e..36f8095 100644
--- a/libs/vr/libdisplay/graphics.cpp
+++ b/libs/vr/libdisplay/graphics.cpp
@@ -310,7 +310,7 @@
 
   if (!direct_surface) {
     auto queue_status = surface->CreateQueue(
-        sizeof(DisplaySurfaceMetadata), 1, HAL_PIXEL_FORMAT_BLOB,
+        sizeof(DisplaySurfaceMetadata), 1, 1, HAL_PIXEL_FORMAT_BLOB,
         GRALLOC1_PRODUCER_USAGE_GPU_RENDER_TARGET |
             GRALLOC1_PRODUCER_USAGE_CPU_WRITE_OFTEN |
             GRALLOC1_CONSUMER_USAGE_GPU_DATA_BUFFER,
diff --git a/libs/vr/libdisplay/include/private/dvr/display_client.h b/libs/vr/libdisplay/include/private/dvr/display_client.h
index 668532d..7a7f670 100644
--- a/libs/vr/libdisplay/include/private/dvr/display_client.h
+++ b/libs/vr/libdisplay/include/private/dvr/display_client.h
@@ -42,6 +42,7 @@
   // parameters.
   pdx::Status<std::unique_ptr<ProducerQueue>> CreateQueue(uint32_t width,
                                                           uint32_t height,
+                                                          uint32_t layer_count,
                                                           uint32_t format,
                                                           uint64_t usage,
                                                           size_t capacity);
diff --git a/libs/vr/libdisplay/native_buffer_queue.cpp b/libs/vr/libdisplay/native_buffer_queue.cpp
index 6d81975..1bb05d8 100644
--- a/libs/vr/libdisplay/native_buffer_queue.cpp
+++ b/libs/vr/libdisplay/native_buffer_queue.cpp
@@ -27,7 +27,7 @@
   for (size_t i = 0; i < capacity; i++) {
     size_t slot;
     // TODO(jwcai) Should change to use BufferViewPort's spec to config.
-    const int ret = producer_queue_->AllocateBuffer(width_, height_, format_,
+    const int ret = producer_queue_->AllocateBuffer(width_, height_, 1, format_,
                                                     usage_, &slot);
     if (ret < 0) {
       ALOGE(
diff --git a/libs/vr/libdvr/dvr_surface.cpp b/libs/vr/libdvr/dvr_surface.cpp
index b70f726..67e2ae8 100644
--- a/libs/vr/libdvr/dvr_surface.cpp
+++ b/libs/vr/libdvr/dvr_surface.cpp
@@ -133,7 +133,8 @@
 
 int dvrSurfaceCreateWriteBufferQueue(DvrSurface* surface, uint32_t width,
                                      uint32_t height, uint32_t format,
-                                     uint64_t usage, size_t capacity,
+                                     uint32_t layer_count, uint64_t usage,
+                                     size_t capacity,
                                      DvrWriteBufferQueue** out_writer) {
   if (surface == nullptr || out_writer == nullptr) {
     ALOGE(
@@ -143,8 +144,8 @@
     return -EINVAL;
   }
 
-  auto status =
-      surface->surface->CreateQueue(width, height, format, usage, capacity);
+  auto status = surface->surface->CreateQueue(width, height, layer_count,
+                                              format, usage, capacity);
   if (!status) {
     ALOGE("dvrSurfaceCreateWriteBufferQueue: Failed to create queue: %s",
           status.GetErrorMessage().c_str());
diff --git a/libs/vr/libdvr/include/dvr/dvr_api.h b/libs/vr/libdvr/include/dvr/dvr_api.h
index 7124bee..bb9d8d8 100644
--- a/libs/vr/libdvr/include/dvr/dvr_api.h
+++ b/libs/vr/libdvr/include/dvr/dvr_api.h
@@ -162,7 +162,8 @@
                                           size_t attribute_count);
 typedef int (*DvrSurfaceCreateWriteBufferQueuePtr)(
     DvrSurface* surface, uint32_t width, uint32_t height, uint32_t format,
-    uint64_t usage, size_t capacity, DvrWriteBufferQueue** queue_out);
+    uint32_t layer_count, uint64_t usage, size_t capacity,
+    DvrWriteBufferQueue** queue_out);
 
 // vsync_client_api.h
 typedef int (*DvrVSyncClientCreatePtr)(DvrVSyncClient** client_out);
diff --git a/libs/vr/libdvr/include/dvr/dvr_surface.h b/libs/vr/libdvr/include/dvr/dvr_surface.h
index 58f2a10..361488e 100644
--- a/libs/vr/libdvr/include/dvr/dvr_surface.h
+++ b/libs/vr/libdvr/include/dvr/dvr_surface.h
@@ -78,7 +78,8 @@
 // @return 0 on success. Otherwise returns a negative error value.
 int dvrSurfaceCreateWriteBufferQueue(DvrSurface* surface, uint32_t width,
                                      uint32_t height, uint32_t format,
-                                     uint64_t usage, size_t capacity,
+                                     uint32_t layer_count, uint64_t usage,
+                                     size_t capacity,
                                      DvrWriteBufferQueue** queue_out);
 
 // Get a named buffer from the display service.
diff --git a/libs/vr/libdvr/tests/dvr_buffer_queue-test.cpp b/libs/vr/libdvr/tests/dvr_buffer_queue-test.cpp
index c38a1b8..474e968 100644
--- a/libs/vr/libdvr/tests/dvr_buffer_queue-test.cpp
+++ b/libs/vr/libdvr/tests/dvr_buffer_queue-test.cpp
@@ -15,6 +15,7 @@
 
 static constexpr int kBufferWidth = 100;
 static constexpr int kBufferHeight = 1;
+static constexpr int kLayerCount = 1;
 static constexpr int kBufferFormat = HAL_PIXEL_FORMAT_BLOB;
 static constexpr int kBufferUsage = GRALLOC_USAGE_SW_READ_RARELY;
 static constexpr size_t kQueueCapacity = 3;
@@ -40,8 +41,8 @@
     size_t out_slot;
     for (size_t i = 0; i < buffer_count; i++) {
       int ret = GetProducerQueueFromDvrWriteBufferQueue(write_queue_)
-                    ->AllocateBuffer(kBufferWidth, kBufferHeight, kBufferFormat,
-                                     kBufferUsage, &out_slot);
+                    ->AllocateBuffer(kBufferWidth, kBufferHeight, kLayerCount,
+                                     kBufferFormat, kBufferUsage, &out_slot);
       ASSERT_EQ(0, ret);
     }
   }
diff --git a/libs/vr/libdvr/tests/dvr_display_manager-test.cpp b/libs/vr/libdvr/tests/dvr_display_manager-test.cpp
index 0150984..a2414d6 100644
--- a/libs/vr/libdvr/tests/dvr_display_manager-test.cpp
+++ b/libs/vr/libdvr/tests/dvr_display_manager-test.cpp
@@ -56,10 +56,11 @@
 
 Status<UniqueDvrWriteBufferQueue> CreateSurfaceQueue(
     const UniqueDvrSurface& surface, uint32_t width, uint32_t height,
-    uint32_t format, uint64_t usage, size_t capacity) {
+    uint32_t format, uint32_t layer_count, uint64_t usage, size_t capacity) {
   DvrWriteBufferQueue* queue;
-  const int ret = dvrSurfaceCreateWriteBufferQueue(
-      surface.get(), width, height, format, usage, capacity, &queue);
+  const int ret =
+      dvrSurfaceCreateWriteBufferQueue(surface.get(), width, height, format,
+                                       layer_count, usage, capacity, &queue);
   if (ret < 0)
     return ErrorStatus(-ret);
   else
@@ -484,7 +485,7 @@
 
   // Create a new queue in the surface.
   auto write_queue_status = CreateSurfaceQueue(
-      surface, 320, 240, AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM,
+      surface, 320, 240, AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM, 1,
       AHARDWAREBUFFER_USAGE_CPU_READ_RARELY, 1);
   ASSERT_STATUS_OK(write_queue_status);
   UniqueDvrWriteBufferQueue write_queue = write_queue_status.take();
@@ -533,6 +534,45 @@
   ASSERT_EQ(0u, queue_ids.size());
 }
 
+TEST_F(DvrDisplayManagerTest, MultiLayerBufferQueue) {
+  // Create an application surface.
+  auto surface_status = CreateApplicationSurface();
+  ASSERT_STATUS_OK(surface_status);
+  UniqueDvrSurface surface = surface_status.take();
+  ASSERT_NE(nullptr, surface.get());
+
+  // Get surface state and verify there is one surface.
+  ASSERT_STATUS_OK(manager_->WaitForUpdate());
+  ASSERT_STATUS_EQ(1u, manager_->GetSurfaceCount());
+
+  // Create a new queue in the surface.
+  const uint32_t kLayerCount = 3;
+  auto write_queue_status = CreateSurfaceQueue(
+      surface, 320, 240, AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM, kLayerCount,
+      AHARDWAREBUFFER_USAGE_CPU_READ_RARELY, 1);
+  ASSERT_STATUS_OK(write_queue_status);
+  UniqueDvrWriteBufferQueue write_queue = write_queue_status.take();
+  ASSERT_NE(nullptr, write_queue.get());
+
+  DvrWriteBuffer* buffer = nullptr;
+  dvrWriteBufferCreateEmpty(&buffer);
+  int fence_fd = -1;
+  int error =
+      dvrWriteBufferQueueDequeue(write_queue.get(), 1000, buffer, &fence_fd);
+  ASSERT_EQ(0, error);
+
+  AHardwareBuffer* hardware_buffer = nullptr;
+  error = dvrWriteBufferGetAHardwareBuffer(buffer, &hardware_buffer);
+  ASSERT_EQ(0, error);
+
+  AHardwareBuffer_Desc desc = {};
+  AHardwareBuffer_describe(hardware_buffer, &desc);
+  ASSERT_EQ(kLayerCount, desc.layers);
+
+  AHardwareBuffer_release(hardware_buffer);
+  dvrWriteBufferDestroy(buffer);
+}
+
 }  // namespace
 
 }  // namespace dvr