Merge remote-tracking branch 'aosp/upstream-main'

Bring in from upstream:
* d30ea066 (crrev/c/6394316) intel_defines: Add ADL-N PCI ids

Get these earlier missed changes from upstream:
* 3dd534cc Add padding for i915 cursor buffers
* aec65367 virtgpu_cross_domain: Hold a lock for all of bo_create

Bug: 403278247
Test: CI

Change-Id: I0abfa7707032a4601dc456628b20a30ea498e8ea
diff --git a/Android.bp b/Android.bp
new file mode 100644
index 0000000..3a8cf22
--- /dev/null
+++ b/Android.bp
@@ -0,0 +1,324 @@
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package {
+    default_applicable_licenses: ["external_minigbm_license"],
+}
+
+// Added automatically by a large-scale-change that took the approach of
+// 'apply every license found to every target'. While this makes sure we respect
+// every license restriction, it may not be entirely correct.
+//
+// e.g. GPL in an MIT project might only apply to the contrib/ directory.
+//
+// Please consider splitting the single license below into multiple licenses,
+// taking care not to lose any license_kind information, and overriding the
+// default license using the 'licenses: [...]' property on targets as needed.
+//
+// For unused files, consider creating a 'fileGroup' with "//visibility:private"
+// to attach the license to, and including a comment whether the files may be
+// used in the current project.
+// See: http://go/android-license-faq
+license {
+    name: "external_minigbm_license",
+    visibility: [":__subpackages__"],
+    license_kinds: [
+        "SPDX-license-identifier-Apache-2.0",
+        "SPDX-license-identifier-BSD",
+        "SPDX-license-identifier-MIT",
+    ],
+    license_text: [
+        "LICENSE",
+    ],
+}
+
+filegroup {
+    name: "minigbm_core_files",
+
+    srcs: [
+        "amdgpu.c",
+        "backend_mock.c",
+        "drv.c",
+        "drv_array_helpers.c",
+        "drv_helpers.c",
+        "dumb_driver.c",
+        "i915.c",
+        "mediatek.c",
+        "msm.c",
+        "rockchip.c",
+        "vc4.c",
+        "virtgpu.c",
+        "virtgpu_cross_domain.c",
+        "virtgpu_virgl.c",
+        "xe.c",
+    ],
+}
+
+filegroup {
+    name: "minigbm_gralloc_common_files",
+
+    srcs: [
+        "cros_gralloc/cros_gralloc_buffer.cc",
+        "cros_gralloc/cros_gralloc_helpers.cc",
+        "cros_gralloc/cros_gralloc_driver.cc",
+    ],
+}
+
+filegroup {
+    name: "minigbm_gralloc0_files",
+    srcs: ["cros_gralloc/gralloc0/gralloc0.cc"],
+}
+
+generic_cflags = ["-DHAS_DMABUF_SYSTEM_HEAP"]
+intel_cflags = [
+    "-DDRV_I915",
+    "-DDRV_XE",
+]
+meson_cflags = ["-DDRV_MESON"]
+msm_cflags = [
+    "-DDRV_MSM",
+    "-DQCOM_DISABLE_COMPRESSED_NV12",
+    "-DHAS_DMABUF_SYSTEM_HEAP",
+]
+arcvm_cflags = ["-DVIRTIO_GPU_NEXT"]
+
+cc_defaults {
+    name: "minigbm_defaults",
+
+    cflags: [
+        "-D_GNU_SOURCE=1",
+        "-D_FILE_OFFSET_BITS=64",
+        "-Wall",
+        "-Wsign-compare",
+        "-Wpointer-arith",
+        "-Wcast-qual",
+        "-Wcast-align",
+        "-Wno-unused-parameter",
+    ] + select(soong_config_variable("minigbm", "platform"), {
+        "generic": generic_cflags,
+        "intel": intel_cflags,
+        "meson": meson_cflags,
+        "msm": msm_cflags,
+        "arcvm": arcvm_cflags,
+        default: [],
+    }),
+
+    product_variables: {
+        platform_sdk_version: {
+            cflags: ["-DANDROID_API_LEVEL=%d"],
+        },
+    },
+}
+
+cc_library_headers {
+    name: "minigbm_headers",
+    host_supported: true,
+    vendor_available: true,
+    export_include_dirs: ["."],
+}
+
+cc_defaults {
+    name: "minigbm_cros_gralloc_defaults",
+
+    defaults: ["minigbm_defaults"],
+
+    header_libs: [
+        "libhardware_headers",
+        "libnativebase_headers",
+        "libsystem_headers",
+        "minigbm_headers",
+    ],
+
+    static_libs: ["libarect"],
+
+    vendor: true,
+
+    shared_libs: [
+        "libcutils",
+        "libdmabufheap",
+        "libdrm",
+        "libgralloctypes",
+        "libnativewindow",
+        "libsync",
+        "liblog",
+    ],
+}
+
+cc_defaults {
+    name: "minigbm_cros_gralloc_library_defaults",
+
+    defaults: ["minigbm_cros_gralloc_defaults"],
+    srcs: [
+        ":minigbm_core_files",
+        ":minigbm_gralloc_common_files",
+    ],
+}
+
+cc_defaults {
+    name: "minigbm_cros_gralloc0_defaults",
+
+    defaults: ["minigbm_cros_gralloc_defaults"],
+    relative_install_path: "hw",
+
+    srcs: [":minigbm_gralloc0_files"],
+}
+
+cc_library {
+    name: "libgbm",
+    defaults: ["minigbm_defaults"],
+    host_supported: true,
+
+    srcs: [
+        ":minigbm_core_files",
+        "gbm.c",
+        "gbm_helpers.c",
+        "minigbm_helpers.c",
+    ],
+
+    target: {
+        host: {
+            // Avoid linking to another host copy of libdrm; this library will cause
+            // binary GPU drivers to be loaded from the host, which might be linked
+            // to a system copy of libdrm, which conflicts with the AOSP one
+            allow_undefined_symbols: true,
+            header_libs: ["libdrm_headers"],
+        },
+        android: {
+            shared_libs: [
+                "libcutils",
+                "liblog",
+            ],
+            static_libs: [
+                "libdrm",
+            ],
+        },
+    },
+    apex_available: [
+        "//apex_available:platform",
+        "//apex_available:anyapex",
+    ],
+    vendor_available: true,
+    product_available: true,
+
+    export_include_dirs: ["."],
+}
+
+// Rust bindings to minigbm, generated in a way compatible with gbm crate.
+rust_bindgen {
+    name: "libgbm_sys",
+    crate_name: "gbm_sys",
+    wrapper_src: "rust/gbm_wrapper.h",
+    source_stem: "bindings",
+    bindgen_flags: [
+        "--blocklist-type=__BINDGEN_TMP_.*",
+        "--allowlist-type=^gbm_.*$",
+        "--allowlist-function=^gbm_.*$",
+        "--allowlist-var=GBM_.*|gbm_.*$",
+        "--constified-enum-module=^gbm_.*$",
+    ],
+    shared_libs: ["libgbm"],
+    host_supported: true,
+    vendor_available: true,
+    product_available: true,
+    apex_available: [
+        "//apex_available:anyapex",
+        "//apex_available:platform",
+    ],
+    visibility: [
+        "//external/rust/android-crates-io/crates/gbm",
+        "//system/cros-codecs",
+    ],
+}
+
+// Generic
+cc_library_shared {
+    name: "libminigbm_gralloc",
+    defaults: ["minigbm_cros_gralloc_library_defaults"],
+    cflags: generic_cflags,
+}
+
+cc_library_shared {
+    name: "gralloc.minigbm",
+    defaults: ["minigbm_cros_gralloc0_defaults"],
+    shared_libs: ["libminigbm_gralloc"],
+}
+
+cc_library_headers {
+    name: "libminigbm_gralloc_headers",
+    host_supported: true,
+    vendor_available: true,
+    export_include_dirs: ["cros_gralloc"],
+    visibility: [
+        "//device/generic/goldfish-opengl/system/hwc3:__subpackages__",
+    ],
+}
+
+// Intel
+cc_library_shared {
+    name: "libminigbm_gralloc_intel",
+    defaults: ["minigbm_cros_gralloc_library_defaults"],
+    cflags: intel_cflags,
+    enabled: false,
+    arch: {
+        x86: {
+            enabled: true,
+        },
+        x86_64: {
+            enabled: true,
+        },
+    },
+}
+
+cc_library_shared {
+    name: "gralloc.minigbm_intel",
+    defaults: ["minigbm_cros_gralloc0_defaults"],
+    shared_libs: ["libminigbm_gralloc_intel"],
+    enabled: false,
+    arch: {
+        x86: {
+            enabled: true,
+        },
+        x86_64: {
+            enabled: true,
+        },
+    },
+}
+
+// Meson
+cc_library_shared {
+    name: "libminigbm_gralloc_meson",
+    defaults: ["minigbm_cros_gralloc_library_defaults"],
+    cflags: meson_cflags,
+}
+
+cc_library_shared {
+    name: "gralloc.minigbm_meson",
+    defaults: ["minigbm_cros_gralloc0_defaults"],
+    shared_libs: ["libminigbm_gralloc_meson"],
+}
+
+// MSM
+cc_library_shared {
+    name: "libminigbm_gralloc_msm",
+    defaults: ["minigbm_cros_gralloc_library_defaults"],
+    cflags: msm_cflags,
+}
+
+cc_library_shared {
+    name: "gralloc.minigbm_msm",
+    defaults: ["minigbm_cros_gralloc0_defaults"],
+    shared_libs: ["libminigbm_gralloc_msm"],
+}
+
+// ARCVM
+cc_library_shared {
+    name: "libminigbm_gralloc_arcvm",
+    defaults: ["minigbm_cros_gralloc_library_defaults"],
+    cflags: arcvm_cflags,
+}
+
+cc_library_shared {
+    name: "gralloc.minigbm_arcvm",
+    defaults: ["minigbm_cros_gralloc0_defaults"],
+    shared_libs: ["libminigbm_gralloc_arcvm"],
+}
diff --git a/METADATA b/METADATA
new file mode 100644
index 0000000..033bcb8
--- /dev/null
+++ b/METADATA
@@ -0,0 +1,16 @@
+name: "minigbm"
+description: ""
+third_party {
+  license_type: NOTICE
+  last_upgrade_date {
+    year: 2024
+    month: 3
+    day: 12
+  }
+  homepage: "https://www.chromium.org/"
+  identifier {
+    type: "Git"
+    value: "https://chromium.googlesource.com/chromiumos/platform/minigbm/"
+    version: "40b28f098a29589b3f72de1ba6753d46a616c48b"
+  }
+}
diff --git a/MODULE_LICENSE_BSD b/MODULE_LICENSE_BSD
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/MODULE_LICENSE_BSD
diff --git a/OWNERS.android b/OWNERS.android
new file mode 100644
index 0000000..54e65dc
--- /dev/null
+++ b/OWNERS.android
@@ -0,0 +1,3 @@
+adelva@google.com
+natsu@google.com
+include platform/system/core:main:/janitors/OWNERS
diff --git a/cros_gralloc/aidl/Allocator.cpp b/cros_gralloc/aidl/Allocator.cpp
index 89c439e..199c7f1 100644
--- a/cros_gralloc/aidl/Allocator.cpp
+++ b/cros_gralloc/aidl/Allocator.cpp
@@ -28,137 +28,9 @@
     return ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(error));
 }
 
-}  // namespace
-
-bool Allocator::init() {
-    mDriver = cros_gralloc_driver::get_instance();
-    return mDriver != nullptr;
-}
-
-// TODO(natsu): deduplicate with CrosGralloc4Allocator after the T release.
-ndk::ScopedAStatus Allocator::initializeMetadata(
-        cros_gralloc_handle_t crosHandle,
-        const struct cros_gralloc_buffer_descriptor& crosDescriptor,
-        Dataspace initialDataspace) {
-    if (!mDriver) {
-        ALOGE("Failed to initializeMetadata. Driver is uninitialized.\n");
-        return ToBinderStatus(AllocationError::NO_RESOURCES);
-    }
-
-    if (!crosHandle) {
-        ALOGE("Failed to initializeMetadata. Invalid handle.\n");
-        return ToBinderStatus(AllocationError::NO_RESOURCES);
-    }
-
-    void* addr;
-    uint64_t size;
-    int ret = mDriver->get_reserved_region(crosHandle, &addr, &size);
-    if (ret) {
-        ALOGE("Failed to getReservedRegion.\n");
-        return ToBinderStatus(AllocationError::NO_RESOURCES);
-    }
-
-    CrosGralloc4Metadata* crosMetadata = reinterpret_cast<CrosGralloc4Metadata*>(addr);
-
-    snprintf(crosMetadata->name, CROS_GRALLOC4_METADATA_MAX_NAME_SIZE, "%s",
-             crosDescriptor.name.c_str());
-    crosMetadata->dataspace = initialDataspace;
-    crosMetadata->blendMode = common::BlendMode::INVALID;
-
-    return ndk::ScopedAStatus::ok();
-}
-
-void Allocator::releaseBufferAndHandle(native_handle_t* handle) {
-    mDriver->release(handle);
-    native_handle_close(handle);
-    native_handle_delete(handle);
-}
-
-ndk::ScopedAStatus Allocator::allocate(const std::vector<uint8_t>& descriptor, int32_t count,
-                                       allocator::AllocationResult* outResult) {
-    if (!mDriver) {
-        ALOGE("Failed to allocate. Driver is uninitialized.\n");
-        return ToBinderStatus(AllocationError::NO_RESOURCES);
-    }
-
-    BufferDescriptorInfoV4 description;
-
-    int ret = ::android::gralloc4::decodeBufferDescriptorInfo(descriptor, &description);
-    if (ret) {
-        ALOGE("Failed to allocate. Failed to decode buffer descriptor: %d.\n", ret);
-        return ToBinderStatus(AllocationError::BAD_DESCRIPTOR);
-    }
-
-    std::vector<native_handle_t*> handles;
-    handles.resize(count, nullptr);
-
-    for (int32_t i = 0; i < count; i++) {
-        ndk::ScopedAStatus status = allocate(description, &outResult->stride, &handles[i]);
-        if (!status.isOk()) {
-            for (int32_t j = 0; j < i; j++) {
-                releaseBufferAndHandle(handles[j]);
-            }
-            return status;
-        }
-    }
-
-    outResult->buffers.resize(count);
-    for (int32_t i = 0; i < count; i++) {
-        auto handle = handles[i];
-        outResult->buffers[i] = ::android::dupToAidl(handle);
-        releaseBufferAndHandle(handle);
-    }
-
-    return ndk::ScopedAStatus::ok();
-}
-
-ndk::ScopedAStatus Allocator::allocate(const BufferDescriptorInfoV4& descriptor, int32_t* outStride,
-                                       native_handle_t** outHandle, Dataspace initialDataspace) {
-    if (!mDriver) {
-        ALOGE("Failed to allocate. Driver is uninitialized.\n");
-        return ToBinderStatus(AllocationError::NO_RESOURCES);
-    }
-
-    struct cros_gralloc_buffer_descriptor crosDescriptor;
-    if (convertToCrosDescriptor(descriptor, &crosDescriptor)) {
-        return ToBinderStatus(AllocationError::UNSUPPORTED);
-    }
-
-    crosDescriptor.reserved_region_size += sizeof(CrosGralloc4Metadata);
-
-    if (!mDriver->is_supported(&crosDescriptor)) {
-        const std::string drmFormatString = get_drm_format_string(crosDescriptor.drm_format);
-        const std::string pixelFormatString = getPixelFormatString(descriptor.format);
-        const std::string usageString = getUsageString(descriptor.usage);
-        ALOGE("Failed to allocate. Unsupported combination: pixel format:%s, drm format:%s, "
-              "usage:%s\n",
-              pixelFormatString.c_str(), drmFormatString.c_str(), usageString.c_str());
-        return ToBinderStatus(AllocationError::UNSUPPORTED);
-    }
-
-    native_handle_t* handle;
-    int ret = mDriver->allocate(&crosDescriptor, &handle);
-    if (ret) {
-        return ToBinderStatus(AllocationError::NO_RESOURCES);
-    }
-
-    cros_gralloc_handle_t crosHandle = cros_gralloc_convert_handle(handle);
-
-    auto status = initializeMetadata(crosHandle, crosDescriptor, initialDataspace);
-    if (!status.isOk()) {
-        ALOGE("Failed to allocate. Failed to initialize gralloc buffer metadata.");
-        releaseBufferAndHandle(handle);
-        return status;
-    }
-
-    *outStride = static_cast<int32_t>(crosHandle->pixel_stride);
-    *outHandle = handle;
-
-    return ndk::ScopedAStatus::ok();
-}
-
-static BufferDescriptorInfoV4 convertAidlToIMapperV4Descriptor(const BufferDescriptorInfo& info) {
-    return BufferDescriptorInfoV4 {
+ndk::ScopedAStatus convertToCrosDescriptor(const BufferDescriptorInfo& info,
+                                           struct cros_gralloc_buffer_descriptor& crosDescriptor) {
+    const BufferDescriptorInfoV4 mapperV4Descriptor = {
         .name{reinterpret_cast<const char*>(info.name.data())},
         .width = static_cast<uint32_t>(info.width),
         .height = static_cast<uint32_t>(info.height),
@@ -167,6 +39,54 @@
         .usage = static_cast<uint64_t>(info.usage),
         .reservedSize = 0,
     };
+    if (convertToCrosDescriptor(mapperV4Descriptor, &crosDescriptor)) {
+        return ToBinderStatus(AllocationError::UNSUPPORTED);
+    }
+
+    for (const auto& option : info.additionalOptions) {
+        if (option.name != STANDARD_METADATA_DATASPACE) {
+            return ToBinderStatus(AllocationError::UNSUPPORTED);
+        }
+        crosDescriptor.dataspace = static_cast<common::Dataspace>(option.value);
+    }
+
+    return ndk::ScopedAStatus::ok();
+}
+
+}  // namespace
+
+bool Allocator::init() {
+    mDriver = cros_gralloc_driver::get_instance();
+    return mDriver != nullptr;
+}
+
+void Allocator::releaseBufferAndHandle(native_handle_t* handle) {
+    mDriver->release(handle);
+    native_handle_close(handle);
+    native_handle_delete(handle);
+}
+
+ndk::ScopedAStatus Allocator::allocate(const std::vector<uint8_t>& encodedDescriptor, int32_t count,
+                                       allocator::AllocationResult* outResult) {
+    if (!mDriver) {
+        ALOGE("Failed to allocate. Driver is uninitialized.\n");
+        return ToBinderStatus(AllocationError::NO_RESOURCES);
+    }
+
+    BufferDescriptorInfoV4 mapperV4Descriptor;
+
+    int ret = ::android::gralloc4::decodeBufferDescriptorInfo(encodedDescriptor, &mapperV4Descriptor);
+    if (ret) {
+        ALOGE("Failed to allocate. Failed to decode buffer descriptor: %d.\n", ret);
+        return ToBinderStatus(AllocationError::BAD_DESCRIPTOR);
+    }
+
+    struct cros_gralloc_buffer_descriptor crosDescriptor = {};
+    if (convertToCrosDescriptor(mapperV4Descriptor, &crosDescriptor)) {
+        return ToBinderStatus(AllocationError::UNSUPPORTED);
+    }
+
+    return allocate(crosDescriptor, count, outResult);
 }
 
 ndk::ScopedAStatus Allocator::allocate2(const BufferDescriptorInfo& descriptor, int32_t count,
@@ -176,23 +96,28 @@
         return ToBinderStatus(AllocationError::NO_RESOURCES);
     }
 
-    Dataspace initialDataspace = Dataspace::UNKNOWN;
+    struct cros_gralloc_buffer_descriptor crosDescriptor = {};
 
-    for (const auto& option : descriptor.additionalOptions) {
-        if (option.name != STANDARD_METADATA_DATASPACE) {
-            return ToBinderStatus(AllocationError::UNSUPPORTED);
-        }
-        initialDataspace = static_cast<Dataspace>(option.value);
+    ndk::ScopedAStatus status = convertToCrosDescriptor(descriptor, crosDescriptor);
+    if (!status.isOk()) {
+        return status;
     }
 
-    BufferDescriptorInfoV4 descriptionV4 = convertAidlToIMapperV4Descriptor(descriptor);
+    return allocate(crosDescriptor, count, outResult);
+}
+
+ndk::ScopedAStatus Allocator::allocate(const struct cros_gralloc_buffer_descriptor& descriptor, int32_t count,
+                                       allocator::AllocationResult* outResult) {
+    if (!mDriver) {
+        ALOGE("Failed to allocate. Driver is uninitialized.\n");
+        return ToBinderStatus(AllocationError::NO_RESOURCES);
+    }
 
     std::vector<native_handle_t*> handles;
     handles.resize(count, nullptr);
 
     for (int32_t i = 0; i < count; i++) {
-        ndk::ScopedAStatus status = allocate(descriptionV4, &outResult->stride, &handles[i],
-                                             initialDataspace);
+        ndk::ScopedAStatus status = allocateBuffer(descriptor, &outResult->stride, &handles[i]);
         if (!status.isOk()) {
             for (int32_t j = 0; j < i; j++) {
                 releaseBufferAndHandle(handles[j]);
@@ -211,6 +136,40 @@
     return ndk::ScopedAStatus::ok();
 }
 
+ndk::ScopedAStatus Allocator::allocateBuffer(const struct cros_gralloc_buffer_descriptor& descriptor, int32_t* outStride,
+                                             native_handle_t** outHandle) {
+    if (!mDriver) {
+        ALOGE("Failed to allocate. Driver is uninitialized.\n");
+        return ToBinderStatus(AllocationError::NO_RESOURCES);
+    }
+
+    if (!mDriver->is_supported(&descriptor)) {
+        const std::string drmFormatString =
+            get_drm_format_string(descriptor.drm_format);
+        const std::string pixelFormatString = ::android::hardware::graphics::common::V1_2::toString(
+            static_cast<::android::hardware::graphics::common::V1_2::PixelFormat>(
+                descriptor.droid_format));
+        const std::string usageString = ::android::hardware::graphics::common::V1_2::toString<::android::hardware::graphics::common::V1_2::BufferUsage>(
+            static_cast<uint64_t>(descriptor.droid_usage));
+        ALOGE("Failed to allocate. Unsupported combination: pixel format:%s, drm format:%s, "
+              "usage:%s\n",
+              pixelFormatString.c_str(), drmFormatString.c_str(), usageString.c_str());
+        return ToBinderStatus(AllocationError::UNSUPPORTED);
+    }
+
+    native_handle_t* handle;
+    int ret = mDriver->allocate(&descriptor, &handle);
+    if (ret) {
+        return ToBinderStatus(AllocationError::NO_RESOURCES);
+    }
+
+    cros_gralloc_handle_t crosHandle = cros_gralloc_convert_handle(handle);
+    *outStride = static_cast<int32_t>(crosHandle->pixel_stride);
+    *outHandle = handle;
+
+    return ndk::ScopedAStatus::ok();
+}
+
 ndk::ScopedAStatus Allocator::isSupported(const BufferDescriptorInfo& descriptor,
                             bool* outResult) {
     if (!mDriver) {
@@ -225,16 +184,15 @@
         }
     }
 
-    struct cros_gralloc_buffer_descriptor crosDescriptor;
-    if (convertToCrosDescriptor(convertAidlToIMapperV4Descriptor(descriptor), &crosDescriptor)) {
+    struct cros_gralloc_buffer_descriptor crosDescriptor = {};
+    ndk::ScopedAStatus status = convertToCrosDescriptor(descriptor, crosDescriptor);
+    if (!status.isOk()) {
         // Failing to convert the descriptor means the layer count, pixel format, or usage is
         // unsupported, thus isSupported() = false
         *outResult = false;
         return ndk::ScopedAStatus::ok();
     }
 
-    crosDescriptor.reserved_region_size += sizeof(CrosGralloc4Metadata);
-
     *outResult = mDriver->is_supported(&crosDescriptor);
     return ndk::ScopedAStatus::ok();
 }
diff --git a/cros_gralloc/aidl/Allocator.h b/cros_gralloc/aidl/Allocator.h
index be06dbb..3454aab 100644
--- a/cros_gralloc/aidl/Allocator.h
+++ b/cros_gralloc/aidl/Allocator.h
@@ -13,7 +13,6 @@
 
 #include "cros_gralloc/cros_gralloc_driver.h"
 #include "cros_gralloc/cros_gralloc_helpers.h"
-#include "cros_gralloc/gralloc4/CrosGralloc4Metadata.h"
 
 namespace aidl::android::hardware::graphics::allocator::impl {
 
@@ -39,16 +38,12 @@
 
   private:
     using Dataspace = aidl::android::hardware::graphics::common::Dataspace;
-    ndk::ScopedAStatus allocate(
-            const ::android::hardware::graphics::mapper::V4_0::IMapper::BufferDescriptorInfo&
-                    descriptor,
-            int32_t* outStride, native_handle_t** outHandle,
-            Dataspace initialDataspace = Dataspace::UNKNOWN);
 
-    ndk::ScopedAStatus initializeMetadata(
-            cros_gralloc_handle_t crosHandle,
-            const struct cros_gralloc_buffer_descriptor& crosDescriptor,
-            Dataspace initialDataspace);
+    ndk::ScopedAStatus allocate(const struct cros_gralloc_buffer_descriptor& descriptor,
+                                int32_t count, allocator::AllocationResult* outResult);
+
+    ndk::ScopedAStatus allocateBuffer(const struct cros_gralloc_buffer_descriptor& descriptor,
+                                      int32_t* outStride, native_handle_t** outHandle);
 
     void releaseBufferAndHandle(native_handle_t* handle);
 
diff --git a/cros_gralloc/aidl/Android.bp b/cros_gralloc/aidl/Android.bp
new file mode 100644
index 0000000..b52f806
--- /dev/null
+++ b/cros_gralloc/aidl/Android.bp
@@ -0,0 +1,63 @@
+//
+// Copyright (C) 2022 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "external_minigbm_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    //   SPDX-license-identifier-BSD
+    default_applicable_licenses: ["external_minigbm_license"],
+}
+
+cc_binary {
+    name: "android.hardware.graphics.allocator-service.minigbm",
+    defaults: ["minigbm_cros_gralloc_defaults"],
+    relative_install_path: "hw",
+    init_rc: ["allocator.rc"],
+    vintf_fragments: ["allocator.xml"],
+    vendor: true,
+    shared_libs: [
+        "android.hardware.graphics.allocator-V2-ndk",
+        "android.hardware.graphics.mapper@4.0",
+        "libbase",
+        "libbinder_ndk",
+        "libgralloctypes",
+        "libhidlbase",
+        "liblog",
+        "libminigbm_gralloc",
+        "libminigbm_gralloc4_utils",
+    ],
+    static_libs: [
+        "libaidlcommonsupport",
+    ],
+    srcs: [
+        "Allocator.cpp",
+        "Main.cpp",
+    ],
+}
+
+filegroup {
+    name: "allocator.minigbm.rc",
+    srcs: ["allocator.rc"]
+}
+
+prebuilt_etc {
+    name: "allocator.minigbm.xml",
+    src: "allocator.xml",
+    sub_dir: "vintf",
+    installable: false,
+}
diff --git a/cros_gralloc/cros_gralloc_buffer.cc b/cros_gralloc/cros_gralloc_buffer.cc
index dba8061..b2c4dc8 100644
--- a/cros_gralloc/cros_gralloc_buffer.cc
+++ b/cros_gralloc/cros_gralloc_buffer.cc
@@ -11,6 +11,13 @@
 
 #include <cutils/native_handle.h>
 
+#include "cros_gralloc_buffer_metadata.h"
+
+using aidl::android::hardware::graphics::common::BlendMode;
+using aidl::android::hardware::graphics::common::Cta861_3;
+using aidl::android::hardware::graphics::common::Dataspace;
+using aidl::android::hardware::graphics::common::Smpte2086;
+
 /*static*/
 std::unique_ptr<cros_gralloc_buffer>
 cros_gralloc_buffer::create(struct bo *acquire_bo,
@@ -35,6 +42,31 @@
 	return buffer;
 }
 
+int32_t
+cros_gralloc_buffer::initialize_metadata(const struct cros_gralloc_buffer_descriptor *descriptor)
+{
+	struct cros_gralloc_buffer_metadata *metadata;
+
+	int ret = get_metadata(&metadata);
+	if (ret) {
+		ALOGE("Failed to initialize metadata: failed to get metadata region.");
+		return ret;
+	}
+
+	if (metadata == nullptr) {
+		ALOGE("Failed to initialize metadata: invalid metadata address.");
+		return -1;
+	}
+
+	new (metadata) cros_gralloc_buffer_metadata();
+
+	snprintf(metadata->name, CROS_GRALLOC_BUFFER_METADATA_MAX_NAME_SIZE, "%s",
+		 descriptor->name.c_str());
+	metadata->dataspace = descriptor->dataspace;
+	metadata->blend_mode = descriptor->blend;
+	return 0;
+}
+
 cros_gralloc_buffer::cros_gralloc_buffer(struct bo *acquire_bo,
 					 struct cros_gralloc_handle *acquire_handle)
     : bo_(acquire_bo), hnd_(acquire_handle)
@@ -120,6 +152,132 @@
 	return hnd_->usage;
 }
 
+int32_t cros_gralloc_buffer::get_name(std::optional<std::string> *name) const
+{
+	const struct cros_gralloc_buffer_metadata *metadata;
+
+	int ret = get_metadata(&metadata);
+	if (ret) {
+		ALOGE("Failed to get_name: failed to get metadata.");
+		return ret;
+	}
+
+	*name = metadata->name;
+	return 0;
+}
+
+int32_t cros_gralloc_buffer::get_blend_mode(std::optional<BlendMode> *blend_mode) const
+{
+	const struct cros_gralloc_buffer_metadata *metadata;
+
+	int ret = get_metadata(&metadata);
+	if (ret) {
+		ALOGE("Failed to get_blend_mode: failed to get metadata.");
+		return ret;
+	}
+
+	*blend_mode = metadata->blend_mode;
+	return 0;
+}
+
+int32_t cros_gralloc_buffer::set_blend_mode(BlendMode blend_mode)
+{
+	struct cros_gralloc_buffer_metadata *metadata;
+
+	int ret = get_metadata(&metadata);
+	if (ret) {
+		ALOGE("Failed to set_blend_mode: failed to get metadata.");
+		return ret;
+	}
+
+	metadata->blend_mode = blend_mode;
+	return 0;
+}
+
+int32_t cros_gralloc_buffer::get_dataspace(std::optional<Dataspace> *dataspace) const
+{
+	const struct cros_gralloc_buffer_metadata *metadata;
+
+	int ret = get_metadata(&metadata);
+	if (ret) {
+		ALOGE("Failed to get_dataspace: failed to get metadata.");
+		return ret;
+	}
+
+	*dataspace = metadata->dataspace;
+	return 0;
+}
+
+int32_t cros_gralloc_buffer::set_dataspace(Dataspace dataspace)
+{
+	struct cros_gralloc_buffer_metadata *metadata;
+
+	int ret = get_metadata(&metadata);
+	if (ret) {
+		ALOGE("Failed to set_dataspace: failed to get metadata.");
+		return ret;
+	}
+
+	metadata->dataspace = dataspace;
+	return 0;
+}
+
+int32_t cros_gralloc_buffer::get_cta861_3(std::optional<Cta861_3> *cta) const
+{
+	const struct cros_gralloc_buffer_metadata *metadata;
+
+	int ret = get_metadata(&metadata);
+	if (ret) {
+		ALOGE("Failed to get_cta861_3: failed to get metadata.");
+		return ret;
+	}
+
+	*cta = metadata->cta861_3.to_std_optional();
+	return 0;
+}
+
+int32_t cros_gralloc_buffer::set_cta861_3(std::optional<Cta861_3> cta)
+{
+	struct cros_gralloc_buffer_metadata *metadata;
+
+	int ret = get_metadata(&metadata);
+	if (ret) {
+		ALOGE("Failed to set_cta861_3: failed to get metadata.");
+		return ret;
+	}
+
+	metadata->cta861_3 = cta;
+	return 0;
+}
+
+int32_t cros_gralloc_buffer::get_smpte2086(std::optional<Smpte2086> *smpte) const
+{
+	const struct cros_gralloc_buffer_metadata *metadata;
+
+	int ret = get_metadata(&metadata);
+	if (ret) {
+		ALOGE("Failed to get_smpte2086: failed to get metadata.");
+		return ret;
+	}
+
+	*smpte = metadata->smpte2086.to_std_optional();
+	return 0;
+}
+
+int32_t cros_gralloc_buffer::set_smpte2086(std::optional<Smpte2086> smpte)
+{
+	struct cros_gralloc_buffer_metadata *metadata;
+
+	int ret = get_metadata(&metadata);
+	if (ret) {
+		ALOGE("Failed to set_cta861_3: failed to get metadata.");
+		return ret;
+	}
+
+	metadata->smpte2086 = smpte;
+	return 0;
+}
+
 int32_t cros_gralloc_buffer::increase_refcount()
 {
 	return ++refcount_;
@@ -242,3 +400,54 @@
 	*size = hnd_->reserved_region_size;
 	return 0;
 }
+
+int32_t cros_gralloc_buffer::get_client_reserved_region(void **client_reserved_region_addr,
+							uint64_t *client_reserved_region_size) const
+{
+	int32_t ret = get_reserved_region(client_reserved_region_addr, client_reserved_region_size);
+	if (ret) {
+		return ret;
+	}
+
+	*client_reserved_region_addr =
+	    reinterpret_cast<void *>(reinterpret_cast<char *>(*client_reserved_region_addr) +
+				     sizeof(struct cros_gralloc_buffer_metadata));
+	*client_reserved_region_size =
+	    *client_reserved_region_size - sizeof(struct cros_gralloc_buffer_metadata);
+	return 0;
+}
+
+int32_t cros_gralloc_buffer::get_metadata(struct cros_gralloc_buffer_metadata **metadata)
+{
+	void *metadata_addr;
+	uint64_t metadata_region_size;
+	int32_t ret = get_reserved_region(&metadata_addr, &metadata_region_size);
+	if (ret) {
+		return ret;
+	}
+
+	if (metadata_addr == nullptr) {
+		return -1;
+	}
+
+	*metadata = reinterpret_cast<struct cros_gralloc_buffer_metadata *>(metadata_addr);
+	return 0;
+}
+
+int32_t
+cros_gralloc_buffer::get_metadata(const struct cros_gralloc_buffer_metadata **metadata) const
+{
+	void *metadata_addr;
+	uint64_t metadata_region_size;
+	int32_t ret = get_reserved_region(&metadata_addr, &metadata_region_size);
+	if (ret) {
+		return ret;
+	}
+
+	if (metadata_addr == nullptr) {
+		return -1;
+	}
+
+	*metadata = reinterpret_cast<const struct cros_gralloc_buffer_metadata *>(metadata_addr);
+	return 0;
+}
diff --git a/cros_gralloc/cros_gralloc_buffer.h b/cros_gralloc/cros_gralloc_buffer.h
index b477faa..e246602 100644
--- a/cros_gralloc/cros_gralloc_buffer.h
+++ b/cros_gralloc/cros_gralloc_buffer.h
@@ -8,6 +8,12 @@
 #define CROS_GRALLOC_BUFFER_H
 
 #include <memory>
+#include <optional>
+
+#include <aidl/android/hardware/graphics/common/BlendMode.h>
+#include <aidl/android/hardware/graphics/common/Cta861_3.h>
+#include <aidl/android/hardware/graphics/common/Dataspace.h>
+#include <aidl/android/hardware/graphics/common/Smpte2086.h>
 
 #include "cros_gralloc_helpers.h"
 
@@ -19,6 +25,8 @@
 
 	~cros_gralloc_buffer();
 
+	int32_t initialize_metadata(const struct cros_gralloc_buffer_descriptor *descriptor);
+
 	uint32_t get_id() const;
 	uint32_t get_width() const;
 	uint32_t get_pixel_stride() const;
@@ -33,6 +41,26 @@
 	int32_t get_android_format() const;
 	int64_t get_android_usage() const;
 
+	int32_t get_name(std::optional<std::string> *name) const;
+
+	int32_t get_blend_mode(
+	    std::optional<aidl::android::hardware::graphics::common::BlendMode> *blend_mode) const;
+	int32_t set_blend_mode(aidl::android::hardware::graphics::common::BlendMode blend_mode);
+
+	int32_t get_dataspace(
+	    std::optional<aidl::android::hardware::graphics::common::Dataspace> *dataspace) const;
+	int32_t set_dataspace(aidl::android::hardware::graphics::common::Dataspace dataspace);
+
+	int32_t
+	get_cta861_3(std::optional<aidl::android::hardware::graphics::common::Cta861_3> *cta) const;
+	int32_t
+	set_cta861_3(std::optional<aidl::android::hardware::graphics::common::Cta861_3> cta);
+
+	int32_t get_smpte2086(
+	    std::optional<aidl::android::hardware::graphics::common::Smpte2086> *smpte) const;
+	int32_t
+	set_smpte2086(std::optional<aidl::android::hardware::graphics::common::Smpte2086> smpte);
+
 	/* The new reference count is returned by both these functions. */
 	int32_t increase_refcount();
 	int32_t decrease_refcount();
@@ -46,8 +74,8 @@
 	int32_t invalidate();
 	int32_t flush();
 
-	int32_t get_reserved_region(void **reserved_region_addr,
-				    uint64_t *reserved_region_size) const;
+	int32_t get_client_reserved_region(void **client_reserved_region_addr,
+					   uint64_t *client_reserved_region_size) const;
 
       private:
 	cros_gralloc_buffer(struct bo *acquire_bo, struct cros_gralloc_handle *acquire_handle);
@@ -55,6 +83,12 @@
 	cros_gralloc_buffer(cros_gralloc_buffer const &);
 	cros_gralloc_buffer operator=(cros_gralloc_buffer const &);
 
+	int32_t get_reserved_region(void **reserved_region_addr,
+				    uint64_t *reserved_region_size) const;
+
+	int32_t get_metadata(struct cros_gralloc_buffer_metadata **metadata);
+	int32_t get_metadata(const struct cros_gralloc_buffer_metadata **metadata) const;
+
 	struct bo *bo_;
 
 	/* Note: this will be nullptr for imported/retained buffers. */
diff --git a/cros_gralloc/cros_gralloc_buffer_metadata.h b/cros_gralloc/cros_gralloc_buffer_metadata.h
new file mode 100644
index 0000000..361a472
--- /dev/null
+++ b/cros_gralloc/cros_gralloc_buffer_metadata.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2022 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef CROSGRALLOC4METADATA_H
+#define CROSGRALLOC4METADATA_H
+
+#include <optional>
+#include <type_traits>
+
+#include <aidl/android/hardware/graphics/common/BlendMode.h>
+#include <aidl/android/hardware/graphics/common/Cta861_3.h>
+#include <aidl/android/hardware/graphics/common/Dataspace.h>
+#include <aidl/android/hardware/graphics/common/Smpte2086.h>
+
+#include "cros_gralloc_helpers.h"
+
+// Simple replacement for std::optional which is not guarenteed to be memory layout
+// stable across ABIs.
+template <typename T> struct cros_buffer_optional {
+
+	enum class state : uint32_t { VACANT, OCCUPIED };
+
+	cros_buffer_optional() = default;
+
+	cros_buffer_optional(std::optional<T> v) : occupancy(v ? state::OCCUPIED : state::VACANT)
+	{
+		if (v) {
+			value = *v;
+		}
+	}
+
+	std::optional<T> to_std_optional() const
+	{
+		return occupancy == state::VACANT ? std::nullopt : std::make_optional(value);
+	}
+
+	state occupancy = state::VACANT;
+	T value;
+};
+
+/*
+ * The metadata for cros_gralloc_buffer-s that should reside in a shared memory region
+ * instead of directly in cros_gralloc_handle-s.
+ *
+ * Any metadata that is mutable must be stored in this shared memory region as
+ * cros_gralloc_handle-s can not be tracked and updated across processes.
+ */
+struct cros_gralloc_buffer_metadata {
+	/*
+	 * Name is stored in the shared memory metadata to simplify cros_gralloc_handle
+	 * creation. This allows us to keep handles small while avoiding variable sized
+	 * handles.
+	 */
+	char name[CROS_GRALLOC_BUFFER_METADATA_MAX_NAME_SIZE];
+	aidl::android::hardware::graphics::common::BlendMode blend_mode;
+	aidl::android::hardware::graphics::common::Dataspace dataspace;
+	cros_buffer_optional<aidl::android::hardware::graphics::common::Cta861_3> cta861_3;
+	cros_buffer_optional<aidl::android::hardware::graphics::common::Smpte2086> smpte2086;
+};
+
+static_assert(std::is_standard_layout_v<cros_gralloc_buffer_metadata>);
+static_assert(std::is_trivially_copyable_v<cros_gralloc_buffer_metadata>);
+
+#endif
diff --git a/cros_gralloc/cros_gralloc_driver.cc b/cros_gralloc/cros_gralloc_driver.cc
index 550f75a..cb8b94b 100644
--- a/cros_gralloc/cros_gralloc_driver.cc
+++ b/cros_gralloc/cros_gralloc_driver.cc
@@ -14,7 +14,10 @@
 #include <syscall.h>
 #include <xf86drm.h>
 
+#include "../drv_helpers.h"
+#include "../drv_priv.h"
 #include "../util.h"
+#include "cros_gralloc_buffer_metadata.h"
 
 // Constants taken from pipe_loader_drm.c in Mesa
 
@@ -155,7 +158,15 @@
 	close(fd);
 }
 
-cros_gralloc_driver::cros_gralloc_driver() : drv_(init_try_nodes(), drv_destroy_and_close)
+static bool is_running_with_software_rendering()
+{
+	const char *vulkan_driver = drv_get_os_option("ro.hardware.vulkan");
+	return (vulkan_driver != nullptr && strstr(vulkan_driver, "pastel") != nullptr);
+}
+
+cros_gralloc_driver::cros_gralloc_driver()
+    : drv_(init_try_nodes(), drv_destroy_and_close),
+      is_running_with_software_rendering_(is_running_with_software_rendering())
 {
 }
 
@@ -178,6 +189,11 @@
 	uint64_t resolved_use_flags;
 	struct combination *combo;
 
+	uint64_t use_flags = descriptor->use_flags;
+	if (is_running_with_software_rendering_ && (use_flags & BO_USE_GPU_HW) != 0) {
+		use_flags |= (BO_USE_SW_READ_OFTEN | BO_USE_SW_WRITE_OFTEN);
+	}
+
 	drv_resolve_format_and_use_flags(drv_.get(), descriptor->drm_format, descriptor->use_flags,
 					 &resolved_format, &resolved_use_flags);
 
@@ -267,7 +283,7 @@
 	num_planes = drv_bo_get_num_planes(bo);
 	num_fds = num_planes;
 
-	if (descriptor->reserved_region_size > 0)
+	if (descriptor->enable_metadata_fd)
 		num_fds += 1;
 
 	num_ints = ((sizeof(struct cros_gralloc_handle) - sizeof(native_handle_t)) / sizeof(int)) -
@@ -291,7 +307,11 @@
 		hnd->sizes[plane] = drv_bo_get_plane_size(bo, plane);
 	}
 
-	hnd->reserved_region_size = descriptor->reserved_region_size;
+	hnd->reserved_region_size = 0;
+	if (descriptor->enable_metadata_fd)
+		hnd->reserved_region_size =
+		    sizeof(struct cros_gralloc_buffer_metadata) + descriptor->client_metadata_size;
+
 	if (hnd->reserved_region_size > 0) {
 		ret = create_reserved_region(descriptor->name, hnd->reserved_region_size);
 		if (ret < 0)
@@ -313,7 +333,7 @@
 	hnd->magic = cros_gralloc_magic;
 	hnd->droid_format = descriptor->droid_format;
 	hnd->usage = descriptor->droid_usage;
-	hnd->total_size = descriptor->reserved_region_size + drv_bo_get_total_size(bo);
+	hnd->total_size = hnd->reserved_region_size + drv_bo_get_total_size(bo);
 
 	buffer = cros_gralloc_buffer::create(bo, hnd);
 	if (!buffer) {
@@ -322,6 +342,12 @@
 		goto destroy_hnd;
 	}
 
+	ret = buffer->initialize_metadata(descriptor);
+	if (ret) {
+		ALOGE("Failed to allocate: failed to initialize cros_gralloc_buffer metadata.");
+		goto destroy_hnd;
+	}
+
 	{
 		std::lock_guard<std::mutex> lock(mutex_);
 
@@ -458,6 +484,15 @@
 		return -EINVAL;
 	}
 
+	if (!is_running_with_software_rendering_) {
+		if ((hnd->usage & (GRALLOC_USAGE_SW_READ_MASK | GRALLOC_USAGE_SW_WRITE_MASK)) ==
+		    0) {
+			ALOGE("Attempted to lock() a buffer that was not allocated with a "
+			      "BufferUsage::CPU_* usage.");
+			return -EINVAL;
+		}
+	}
+
 	auto buffer = get_buffer(hnd);
 	if (!buffer) {
 		ALOGE("Invalid reference (lock() called on unregistered handle).");
@@ -572,27 +607,6 @@
 	return buffer->resource_info(strides, offsets, format_modifier);
 }
 
-int32_t cros_gralloc_driver::get_reserved_region(buffer_handle_t handle,
-						 void **reserved_region_addr,
-						 uint64_t *reserved_region_size)
-{
-	std::lock_guard<std::mutex> lock(mutex_);
-
-	auto hnd = cros_gralloc_convert_handle(handle);
-	if (!hnd) {
-		ALOGE("Invalid handle.");
-		return -EINVAL;
-	}
-
-	auto buffer = get_buffer(hnd);
-	if (!buffer) {
-		ALOGE("Invalid reference (get_reserved_region() called on unregistered handle).");
-		return -EINVAL;
-	}
-
-	return buffer->get_reserved_region(reserved_region_addr, reserved_region_size);
-}
-
 uint32_t cros_gralloc_driver::get_resolved_drm_format(uint32_t drm_format, uint64_t use_flags)
 {
 	uint32_t resolved_format;
diff --git a/cros_gralloc/cros_gralloc_driver.h b/cros_gralloc/cros_gralloc_driver.h
index 1f96178..4e1fdf2 100644
--- a/cros_gralloc/cros_gralloc_driver.h
+++ b/cros_gralloc/cros_gralloc_driver.h
@@ -44,9 +44,6 @@
 	int32_t resource_info(buffer_handle_t handle, uint32_t strides[DRV_MAX_PLANES],
 			      uint32_t offsets[DRV_MAX_PLANES], uint64_t *format_modifier);
 
-	int32_t get_reserved_region(buffer_handle_t handle, void **reserved_region_addr,
-				    uint64_t *reserved_region_size);
-
 	uint32_t get_resolved_drm_format(uint32_t drm_format, uint64_t use_flags);
 
 	void with_buffer(cros_gralloc_handle_t hnd,
@@ -84,6 +81,9 @@
 	std::mutex mutex_;
 	std::unordered_map<uint32_t, std::unique_ptr<cros_gralloc_buffer>> buffers_;
 	std::unordered_map<cros_gralloc_handle_t, cros_gralloc_imported_handle_info> handles_;
+
+	/* TODO(b/242184599): remove after SwiftShader is moved to the host. */
+	const bool is_running_with_software_rendering_ = false;
 };
 
 #endif
diff --git a/cros_gralloc/cros_gralloc_helpers.h b/cros_gralloc/cros_gralloc_helpers.h
index 6b1febb..1987eab 100644
--- a/cros_gralloc/cros_gralloc_helpers.h
+++ b/cros_gralloc/cros_gralloc_helpers.h
@@ -10,6 +10,8 @@
 #include "../drv.h"
 #include "cros_gralloc_handle.h"
 
+#include <aidl/android/hardware/graphics/common/BlendMode.h>
+#include <aidl/android/hardware/graphics/common/Dataspace.h>
 #include <log/log.h>
 #include <system/graphics.h>
 #include <system/window.h>
@@ -27,6 +29,8 @@
 #define BUFFER_USAGE_FRONT_RENDERING_MASK                                                          \
 	(BUFFER_USAGE_FRONT_RENDERING | BUFFER_USAGE_FRONT_RENDERING_PRIVATE)
 
+#define CROS_GRALLOC_BUFFER_METADATA_MAX_NAME_SIZE 1024
+
 struct cros_gralloc_buffer_descriptor {
 	uint32_t width;
 	uint32_t height;
@@ -34,8 +38,16 @@
 	int64_t droid_usage;
 	uint32_t drm_format;
 	uint64_t use_flags;
-	uint64_t reserved_region_size;
+	// If true, allocate an additional shared memory region for buffer metadata.
+	bool enable_metadata_fd = false;
+	// If the additional shared memory region for buffer metadata is present, the
+	// additional amount of space reserved for client use.
+	uint64_t client_metadata_size = 0;
 	std::string name;
+	aidl::android::hardware::graphics::common::Dataspace dataspace =
+	    aidl::android::hardware::graphics::common::Dataspace::UNKNOWN;
+	aidl::android::hardware::graphics::common::BlendMode blend =
+	    aidl::android::hardware::graphics::common::BlendMode::INVALID;
 };
 
 constexpr uint32_t cros_gralloc_magic = 0xABCDDCBA;
diff --git a/cros_gralloc/gralloc0/gralloc0.cc b/cros_gralloc/gralloc0/gralloc0.cc
index 173cbcf..b6f493d 100644
--- a/cros_gralloc/gralloc0/gralloc0.cc
+++ b/cros_gralloc/gralloc0/gralloc0.cc
@@ -81,7 +81,7 @@
 	descriptor.droid_usage = usage;
 	descriptor.drm_format = cros_gralloc_convert_format(format);
 	descriptor.use_flags = cros_gralloc_convert_usage(usage);
-	descriptor.reserved_region_size = 0;
+	descriptor.enable_metadata_fd = false;
 
 	if (!mod->driver->is_supported(&descriptor)) {
 		ALOGE("Unsupported combination -- HAL format: %u, HAL usage: %u, "
@@ -531,6 +531,8 @@
 		.lockAsync = gralloc0_lock_async,
 		.unlockAsync = gralloc0_unlock_async,
 		.lockAsync_ycbcr = gralloc0_lock_async_ycbcr,
+                .validateBufferSize = NULL,
+                .getTransportSize = NULL,
 	    },
 
 	.alloc = nullptr,
diff --git a/cros_gralloc/gralloc4/Android.bp b/cros_gralloc/gralloc4/Android.bp
new file mode 100644
index 0000000..73588f7
--- /dev/null
+++ b/cros_gralloc/gralloc4/Android.bp
@@ -0,0 +1,174 @@
+//
+// Copyright (C) 2020 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "external_minigbm_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    //   SPDX-license-identifier-BSD
+    default_applicable_licenses: ["external_minigbm_license"],
+}
+
+filegroup {
+    name: "minigbm_gralloc4_allocator_files",
+    srcs: [
+        "CrosGralloc4Allocator.cc",
+        "CrosGralloc4AllocatorService.cc",
+        "CrosGralloc4Utils.cc",
+    ],
+}
+
+filegroup {
+    name: "minigbm_gralloc4_mapper_files",
+    srcs: [
+        "CrosGralloc4Mapper.cc",
+        "CrosGralloc4Utils.cc",
+    ],
+}
+
+cc_library {
+    name: "libminigbm_gralloc4_utils",
+    defaults: ["minigbm_cros_gralloc_defaults"],
+    vendor: true,
+    srcs: [
+        "CrosGralloc4Utils.cc",
+    ],
+    shared_libs: [
+        "android.hardware.graphics.mapper@4.0",
+        "libgralloctypes",
+        "libhidlbase",
+        "libminigbm_gralloc",
+    ],
+}
+
+cc_defaults {
+    name: "minigbm_gralloc4_common_defaults",
+    defaults: ["minigbm_cros_gralloc_defaults"],
+
+    shared_libs: [
+        "android.hardware.graphics.mapper@4.0",
+        "libgralloctypes",
+        "libhidlbase",
+        "libbase",
+        "libutils",
+    ],
+
+    cflags: ["-Wno-sign-compare"],
+    relative_install_path: "hw",
+}
+
+cc_defaults {
+    name: "minigbm_gralloc4_allocator_defaults",
+    defaults: ["minigbm_gralloc4_common_defaults"],
+
+    shared_libs: ["android.hardware.graphics.allocator@4.0"],
+    srcs: [":minigbm_gralloc4_allocator_files"],
+}
+
+vintf_fragment {
+    name: "android.hardware.graphics.allocator@4.0.xml",
+    src: "android.hardware.graphics.allocator@4.0.xml",
+    vendor: true,
+}
+
+cc_binary {
+    name: "android.hardware.graphics.allocator@4.0-service.minigbm",
+    defaults: ["minigbm_gralloc4_allocator_defaults"],
+    shared_libs: ["libminigbm_gralloc"],
+    vintf_fragment_modules: ["android.hardware.graphics.allocator@4.0.xml"],
+    init_rc: ["android.hardware.graphics.allocator@4.0-service.minigbm.rc"],
+}
+
+cc_binary {
+    name: "android.hardware.graphics.allocator@4.0-service.minigbm_msm",
+    defaults: ["minigbm_gralloc4_allocator_defaults"],
+    shared_libs: ["libminigbm_gralloc_msm"],
+    vintf_fragment_modules: ["android.hardware.graphics.allocator@4.0.xml"],
+    init_rc: ["android.hardware.graphics.allocator@4.0-service.minigbm_msm.rc"],
+}
+
+cc_binary {
+    name: "android.hardware.graphics.allocator@4.0-service.minigbm_arcvm",
+    defaults: ["minigbm_gralloc4_allocator_defaults"],
+    shared_libs: ["libminigbm_gralloc_arcvm"],
+    vintf_fragment_modules: ["android.hardware.graphics.allocator@4.0.xml"],
+    init_rc: ["android.hardware.graphics.allocator@4.0-service.minigbm_arcvm.rc"],
+}
+
+cc_binary {
+    name: "android.hardware.graphics.allocator@4.0-service.minigbm_intel",
+    defaults: ["minigbm_gralloc4_allocator_defaults"],
+    shared_libs: ["libminigbm_gralloc_intel"],
+    vintf_fragment_modules: ["android.hardware.graphics.allocator@4.0.xml"],
+    init_rc: ["android.hardware.graphics.allocator@4.0-service.minigbm_intel.rc"],
+    enabled: false,
+    arch: {
+        x86: {
+            enabled: true,
+        },
+        x86_64: {
+            enabled: true,
+        },
+    },
+}
+
+vintf_fragment {
+    name: "android.hardware.graphics.mapper@4.0.xml",
+    src: "android.hardware.graphics.mapper@4.0.xml",
+    vendor: true,
+}
+
+cc_library_shared {
+    name: "android.hardware.graphics.mapper@4.0-impl.minigbm",
+    defaults: ["minigbm_gralloc4_common_defaults"],
+    shared_libs: ["libminigbm_gralloc"],
+    vintf_fragment_modules: ["android.hardware.graphics.mapper@4.0.xml"],
+    srcs: [":minigbm_gralloc4_mapper_files"],
+}
+
+cc_library_shared {
+    name: "android.hardware.graphics.mapper@4.0-impl.minigbm_msm",
+    defaults: ["minigbm_gralloc4_common_defaults"],
+    shared_libs: ["libminigbm_gralloc_msm"],
+    vintf_fragment_modules: ["android.hardware.graphics.mapper@4.0.xml"],
+    srcs: [":minigbm_gralloc4_mapper_files"],
+}
+
+cc_library_shared {
+    name: "android.hardware.graphics.mapper@4.0-impl.minigbm_arcvm",
+    defaults: ["minigbm_gralloc4_common_defaults"],
+    shared_libs: ["libminigbm_gralloc_arcvm"],
+    vintf_fragment_modules: ["android.hardware.graphics.mapper@4.0.xml"],
+    srcs: [":minigbm_gralloc4_mapper_files"],
+}
+
+cc_library_shared {
+    name: "android.hardware.graphics.mapper@4.0-impl.minigbm_intel",
+    defaults: ["minigbm_gralloc4_common_defaults"],
+    shared_libs: ["libminigbm_gralloc_intel"],
+    vintf_fragment_modules: ["android.hardware.graphics.mapper@4.0.xml"],
+    srcs: [":minigbm_gralloc4_mapper_files"],
+    enabled: false,
+    arch: {
+        x86: {
+            enabled: true,
+        },
+        x86_64: {
+            enabled: true,
+        },
+    },
+}
diff --git a/cros_gralloc/gralloc4/CrosGralloc4Allocator.cc b/cros_gralloc/gralloc4/CrosGralloc4Allocator.cc
index 3166793..852df88 100644
--- a/cros_gralloc/gralloc4/CrosGralloc4Allocator.cc
+++ b/cros_gralloc/gralloc4/CrosGralloc4Allocator.cc
@@ -10,7 +10,6 @@
 #include <gralloctypes/Gralloc4.h>
 
 #include "cros_gralloc/cros_gralloc_helpers.h"
-#include "cros_gralloc/gralloc4/CrosGralloc4Metadata.h"
 #include "cros_gralloc/gralloc4/CrosGralloc4Utils.h"
 
 using aidl::android::hardware::graphics::common::BlendMode;
@@ -31,37 +30,6 @@
     return mDriver ? Error::NONE : Error::NO_RESOURCES;
 }
 
-Error CrosGralloc4Allocator::initializeMetadata(
-        cros_gralloc_handle_t crosHandle,
-        const struct cros_gralloc_buffer_descriptor& crosDescriptor) {
-    if (!mDriver) {
-        ALOGE("Failed to initializeMetadata. Driver is uninitialized.");
-        return Error::NO_RESOURCES;
-    }
-
-    if (!crosHandle) {
-        ALOGE("Failed to initializeMetadata. Invalid handle.");
-        return Error::BAD_BUFFER;
-    }
-
-    void* addr;
-    uint64_t size;
-    int ret = mDriver->get_reserved_region(crosHandle, &addr, &size);
-    if (ret) {
-        ALOGE("Failed to getReservedRegion.");
-        return Error::NO_RESOURCES;
-    }
-
-    CrosGralloc4Metadata* crosMetadata = reinterpret_cast<CrosGralloc4Metadata*>(addr);
-
-    snprintf(crosMetadata->name, CROS_GRALLOC4_METADATA_MAX_NAME_SIZE, "%s",
-             crosDescriptor.name.c_str());
-    crosMetadata->dataspace = Dataspace::UNKNOWN;
-    crosMetadata->blendMode = BlendMode::INVALID;
-
-    return Error::NONE;
-}
-
 Error CrosGralloc4Allocator::allocate(const BufferDescriptorInfo& descriptor, uint32_t* outStride,
                                       hidl_handle* outHandle) {
     if (!mDriver) {
@@ -78,8 +46,6 @@
         return Error::UNSUPPORTED;
     }
 
-    crosDescriptor.reserved_region_size += sizeof(CrosGralloc4Metadata);
-
     if (!mDriver->is_supported(&crosDescriptor)) {
         std::string drmFormatString = get_drm_format_string(crosDescriptor.drm_format);
         std::string pixelFormatString = getPixelFormatString(descriptor.format);
@@ -97,14 +63,6 @@
 
     cros_gralloc_handle_t crosHandle = cros_gralloc_convert_handle(handle);
 
-    Error error = initializeMetadata(crosHandle, crosDescriptor);
-    if (error != Error::NONE) {
-        mDriver->release(handle);
-        native_handle_close(handle);
-        native_handle_delete(handle);
-        return error;
-    }
-
     outHandle->setTo(handle, /*shouldOwn=*/true);
     *outStride = crosHandle->pixel_stride;
 
diff --git a/cros_gralloc/gralloc4/CrosGralloc4Allocator.h b/cros_gralloc/gralloc4/CrosGralloc4Allocator.h
index db7294f..f2febba 100644
--- a/cros_gralloc/gralloc4/CrosGralloc4Allocator.h
+++ b/cros_gralloc/gralloc4/CrosGralloc4Allocator.h
@@ -11,7 +11,6 @@
 
 #include "cros_gralloc/cros_gralloc_driver.h"
 #include "cros_gralloc/cros_gralloc_helpers.h"
-#include "cros_gralloc/gralloc4/CrosGralloc4Metadata.h"
 
 class CrosGralloc4Allocator : public android::hardware::graphics::allocator::V4_0::IAllocator {
   public:
@@ -23,10 +22,6 @@
     android::hardware::graphics::mapper::V4_0::Error init();
 
   private:
-    android::hardware::graphics::mapper::V4_0::Error initializeMetadata(
-            cros_gralloc_handle_t crosHandle,
-            const struct cros_gralloc_buffer_descriptor& crosDescriptor);
-
     android::hardware::graphics::mapper::V4_0::Error allocate(
             const android::hardware::graphics::mapper::V4_0::IMapper::BufferDescriptorInfo&
                     description,
diff --git a/cros_gralloc/gralloc4/CrosGralloc4Mapper.cc b/cros_gralloc/gralloc4/CrosGralloc4Mapper.cc
index 23d6231..f9f75b6 100644
--- a/cros_gralloc/gralloc4/CrosGralloc4Mapper.cc
+++ b/cros_gralloc/gralloc4/CrosGralloc4Mapper.cc
@@ -7,9 +7,12 @@
 #include "cros_gralloc/gralloc4/CrosGralloc4Mapper.h"
 
 #include <aidl/android/hardware/graphics/common/BlendMode.h>
+#include <aidl/android/hardware/graphics/common/Cta861_3.h>
 #include <aidl/android/hardware/graphics/common/Dataspace.h>
 #include <aidl/android/hardware/graphics/common/PlaneLayout.h>
 #include <aidl/android/hardware/graphics/common/Rect.h>
+#include <aidl/android/hardware/graphics/common/Smpte2086.h>
+
 #include <cutils/native_handle.h>
 #include <gralloctypes/Gralloc4.h>
 
@@ -17,9 +20,11 @@
 #include "cros_gralloc/gralloc4/CrosGralloc4Utils.h"
 
 using aidl::android::hardware::graphics::common::BlendMode;
+using aidl::android::hardware::graphics::common::Cta861_3;
 using aidl::android::hardware::graphics::common::Dataspace;
 using aidl::android::hardware::graphics::common::PlaneLayout;
 using aidl::android::hardware::graphics::common::Rect;
+using aidl::android::hardware::graphics::common::Smpte2086;
 using android::hardware::hidl_handle;
 using android::hardware::hidl_vec;
 using android::hardware::Return;
@@ -438,25 +443,18 @@
         return Void();
     }
 
-    const CrosGralloc4Metadata* crosMetadata = nullptr;
-    if (metadataType == android::gralloc4::MetadataType_BlendMode ||
-        metadataType == android::gralloc4::MetadataType_Cta861_3 ||
-        metadataType == android::gralloc4::MetadataType_Dataspace ||
-        metadataType == android::gralloc4::MetadataType_Name ||
-        metadataType == android::gralloc4::MetadataType_Smpte2086) {
-        Error error = getMetadata(crosBuffer, &crosMetadata);
-        if (error != Error::NONE) {
-            ALOGE("Failed to get. Failed to get buffer metadata.");
-            hidlCb(Error::NO_RESOURCES, encodedMetadata);
-            return Void();
-        }
-    }
-
     android::status_t status = android::NO_ERROR;
     if (metadataType == android::gralloc4::MetadataType_BufferId) {
         status = android::gralloc4::encodeBufferId(crosBuffer->get_id(), &encodedMetadata);
     } else if (metadataType == android::gralloc4::MetadataType_Name) {
-        status = android::gralloc4::encodeName(crosMetadata->name, &encodedMetadata);
+        std::optional<std::string> name;
+        int ret = crosBuffer->get_name(&name);
+        if (ret) {
+            ALOGE("Failed to get. Failed to get name internal.");
+            status = android::UNKNOWN_ERROR;
+        } else {
+            status = android::gralloc4::encodeName(*name, &encodedMetadata);
+        }
     } else if (metadataType == android::gralloc4::MetadataType_Width) {
         status = android::gralloc4::encodeWidth(crosBuffer->get_width(), &encodedMetadata);
     } else if (metadataType == android::gralloc4::MetadataType_Height) {
@@ -522,13 +520,41 @@
 
         status = android::gralloc4::encodeCrop(crops, &encodedMetadata);
     } else if (metadataType == android::gralloc4::MetadataType_Dataspace) {
-        status = android::gralloc4::encodeDataspace(crosMetadata->dataspace, &encodedMetadata);
+        std::optional<Dataspace> dataspace;
+        int ret = crosBuffer->get_dataspace(&dataspace);
+        if (ret) {
+            ALOGE("Failed to get. Failed to get dataspace internal.");
+            status = android::UNKNOWN_ERROR;
+        } else {
+            status = android::gralloc4::encodeDataspace(*dataspace, &encodedMetadata);
+        }
     } else if (metadataType == android::gralloc4::MetadataType_BlendMode) {
-        status = android::gralloc4::encodeBlendMode(crosMetadata->blendMode, &encodedMetadata);
+        std::optional<BlendMode> blend;
+        int ret = crosBuffer->get_blend_mode(&blend);
+        if (ret) {
+            ALOGE("Failed to get. Failed to get blend mode internal.");
+            status = android::UNKNOWN_ERROR;
+        } else {
+            status = android::gralloc4::encodeBlendMode(*blend, &encodedMetadata);
+        }
     } else if (metadataType == android::gralloc4::MetadataType_Smpte2086) {
-        status = android::gralloc4::encodeSmpte2086(crosMetadata->smpte2086, &encodedMetadata);
+        std::optional<Smpte2086> smpte;
+        int ret = crosBuffer->get_smpte2086(&smpte);
+        if (ret) {
+            ALOGE("Failed to get. Failed to get smpte2086 internal.");
+            status = android::UNKNOWN_ERROR;
+        } else {
+            status = android::gralloc4::encodeSmpte2086(smpte, &encodedMetadata);
+        }
     } else if (metadataType == android::gralloc4::MetadataType_Cta861_3) {
-        status = android::gralloc4::encodeCta861_3(crosMetadata->cta861_3, &encodedMetadata);
+        std::optional<Cta861_3> cta;
+        int ret = crosBuffer->get_cta861_3(&cta);
+        if (ret) {
+            ALOGE("Failed to get. Failed to get cta861_3 internal.");
+            status = android::UNKNOWN_ERROR;
+        } else {
+            status = android::gralloc4::encodeCta861_3(cta, &encodedMetadata);
+        }
     } else if (metadataType == android::gralloc4::MetadataType_Smpte2094_40) {
         status = android::gralloc4::encodeSmpte2094_40(std::nullopt, &encodedMetadata);
     } else {
@@ -608,38 +634,54 @@
         return Error::BAD_BUFFER;
     }
 
-    CrosGralloc4Metadata* crosMetadata = nullptr;
-
-    Error error = getMutableMetadata(crosBuffer, &crosMetadata);
-    if (error != Error::NONE) {
-        ALOGE("Failed to set. Failed to get buffer metadata.");
-        return Error::UNSUPPORTED;
-    }
-
     if (metadataType == android::gralloc4::MetadataType_BlendMode) {
-        auto status = android::gralloc4::decodeBlendMode(encodedMetadata, &crosMetadata->blendMode);
+        BlendMode blend;
+        auto status = android::gralloc4::decodeBlendMode(encodedMetadata, &blend);
         if (status != android::NO_ERROR) {
             ALOGE("Failed to set. Failed to decode blend mode.");
             return Error::UNSUPPORTED;
         }
+        int ret = crosBuffer->set_blend_mode(blend);
+        if (ret) {
+            ALOGE("Failed to set. Failed to set blend mode internal.");
+            return Error::NO_RESOURCES;
+        }
     } else if (metadataType == android::gralloc4::MetadataType_Cta861_3) {
-        auto status = android::gralloc4::decodeCta861_3(encodedMetadata, &crosMetadata->cta861_3);
+        std::optional<Cta861_3> cta;
+        auto status = android::gralloc4::decodeCta861_3(encodedMetadata, &cta);
         if (status != android::NO_ERROR) {
             ALOGE("Failed to set. Failed to decode cta861_3.");
             return Error::UNSUPPORTED;
         }
+        int ret = crosBuffer->set_cta861_3(cta);
+        if (ret) {
+            ALOGE("Failed to set. Failed to set cta861_3 internal.");
+            return Error::NO_RESOURCES;
+        }
     } else if (metadataType == android::gralloc4::MetadataType_Dataspace) {
-        auto status = android::gralloc4::decodeDataspace(encodedMetadata, &crosMetadata->dataspace);
+        Dataspace dataspace;
+        auto status = android::gralloc4::decodeDataspace(encodedMetadata, &dataspace);
         if (status != android::NO_ERROR) {
             ALOGE("Failed to set. Failed to decode dataspace.");
             return Error::UNSUPPORTED;
         }
+        int ret = crosBuffer->set_dataspace(dataspace);
+        if (ret) {
+            ALOGE("Failed to set. Failed to set dataspace internal.");
+            return Error::NO_RESOURCES;
+        }
     } else if (metadataType == android::gralloc4::MetadataType_Smpte2086) {
-        auto status = android::gralloc4::decodeSmpte2086(encodedMetadata, &crosMetadata->smpte2086);
+        std::optional<Smpte2086> smpte;
+        auto status = android::gralloc4::decodeSmpte2086(encodedMetadata, &smpte);
         if (status != android::NO_ERROR) {
             ALOGE("Failed to set. Failed to decode smpte2086.");
             return Error::UNSUPPORTED;
         }
+        int ret = crosBuffer->set_smpte2086(smpte);
+        if (ret) {
+            ALOGE("Failed to set. Failed to set dataspace internal.");
+            return Error::NO_RESOURCES;
+        }
     }
 
     return Error::NONE;
@@ -1034,75 +1076,6 @@
     return Void();
 }
 
-Error CrosGralloc4Mapper::getReservedRegionArea(const cros_gralloc_buffer* crosBuffer,
-                                                ReservedRegionArea area, void** outAddr,
-                                                uint64_t* outSize) {
-    if (!mDriver) {
-        ALOGE("Failed to getReservedRegionArea. Driver is uninitialized.");
-        return Error::NO_RESOURCES;
-    }
-
-    if (!crosBuffer) {
-        ALOGE("Failed to getReservedRegionArea. Invalid buffer.");
-        return Error::BAD_BUFFER;
-    }
-
-    int ret = crosBuffer->get_reserved_region(outAddr, outSize);
-    if (ret) {
-        ALOGE("Failed to getReservedRegionArea.");
-        *outAddr = nullptr;
-        *outSize = 0;
-        return Error::NO_RESOURCES;
-    }
-
-    switch (area) {
-        case ReservedRegionArea::MAPPER4_METADATA: {
-            // CrosGralloc4Metadata resides at the beginning reserved region.
-            *outSize = sizeof(CrosGralloc4Metadata);
-            break;
-        }
-        case ReservedRegionArea::USER_METADATA: {
-            // User metadata resides after the CrosGralloc4Metadata.
-            *outAddr = reinterpret_cast<void*>(reinterpret_cast<char*>(*outAddr) +
-                                               sizeof(CrosGralloc4Metadata));
-            *outSize = *outSize - sizeof(CrosGralloc4Metadata);
-            break;
-        }
-    }
-
-    return Error::NONE;
-}
-
-Error CrosGralloc4Mapper::getMetadata(const cros_gralloc_buffer* crosBuffer,
-                                      const CrosGralloc4Metadata** outMetadata) {
-    void* addr = nullptr;
-    uint64_t size;
-
-    Error error =
-            getReservedRegionArea(crosBuffer, ReservedRegionArea::MAPPER4_METADATA, &addr, &size);
-    if (error != Error::NONE) {
-        return error;
-    }
-
-    *outMetadata = reinterpret_cast<const CrosGralloc4Metadata*>(addr);
-    return Error::NONE;
-}
-
-Error CrosGralloc4Mapper::getMutableMetadata(cros_gralloc_buffer* crosBuffer,
-                                             CrosGralloc4Metadata** outMetadata) {
-    void* addr = nullptr;
-    uint64_t size;
-
-    Error error =
-            getReservedRegionArea(crosBuffer, ReservedRegionArea::MAPPER4_METADATA, &addr, &size);
-    if (error != Error::NONE) {
-        return error;
-    }
-
-    *outMetadata = reinterpret_cast<CrosGralloc4Metadata*>(addr);
-    return Error::NONE;
-}
-
 Return<void> CrosGralloc4Mapper::getReservedRegion(void* rawHandle, getReservedRegion_cb hidlCb) {
     if (!mDriver) {
         ALOGE("Failed to getReservedRegion. Driver is uninitialized.");
@@ -1128,13 +1101,17 @@
     uint64_t reservedRegionSize = 0;
 
     Error error = Error::NONE;
-    mDriver->with_buffer(crosHandle, [&, this](cros_gralloc_buffer* crosBuffer) {
-        error = getReservedRegionArea(crosBuffer, ReservedRegionArea::USER_METADATA,
-                                      &reservedRegionAddr, &reservedRegionSize);
+    mDriver->with_buffer(crosHandle, [&](cros_gralloc_buffer* crosBuffer) {
+        int ret = crosBuffer->get_client_reserved_region(&reservedRegionAddr, &reservedRegionSize);
+        if (ret) {
+            reservedRegionAddr = nullptr;
+            reservedRegionSize = 0;
+            error = Error::NO_RESOURCES;
+        }
     });
 
     if (error != Error::NONE) {
-        ALOGE("Failed to getReservedRegion. Failed to getReservedRegionArea.");
+        ALOGE("Failed to getReservedRegion.");
         hidlCb(Error::BAD_BUFFER, nullptr, 0);
         return Void();
     }
diff --git a/cros_gralloc/gralloc4/CrosGralloc4Mapper.h b/cros_gralloc/gralloc4/CrosGralloc4Mapper.h
index e4422e2..c8f4afe 100644
--- a/cros_gralloc/gralloc4/CrosGralloc4Mapper.h
+++ b/cros_gralloc/gralloc4/CrosGralloc4Mapper.h
@@ -10,7 +10,6 @@
 
 #include "cros_gralloc/cros_gralloc_driver.h"
 #include "cros_gralloc/cros_gralloc_handle.h"
-#include "cros_gralloc/gralloc4/CrosGralloc4Metadata.h"
 
 class CrosGralloc4Mapper : public android::hardware::graphics::mapper::V4_0::IMapper {
   public:
@@ -68,24 +67,6 @@
                                                       getReservedRegion_cb hidlCb) override;
 
   private:
-    enum class ReservedRegionArea {
-        /* CrosGralloc4Metadata */
-        MAPPER4_METADATA,
-
-        /* External user metadata */
-        USER_METADATA,
-    };
-
-    android::hardware::graphics::mapper::V4_0::Error getReservedRegionArea(
-            const cros_gralloc_buffer* crosBuffer, ReservedRegionArea area, void** outAddr,
-            uint64_t* outSize);
-
-    android::hardware::graphics::mapper::V4_0::Error getMetadata(
-            const cros_gralloc_buffer* crosBuffer, const CrosGralloc4Metadata** outMetadata);
-
-    android::hardware::graphics::mapper::V4_0::Error getMutableMetadata(
-            cros_gralloc_buffer* crosBuffer, CrosGralloc4Metadata** outMetadata);
-
     android::hardware::Return<void> get(const cros_gralloc_buffer* crosBuffer,
                                         const MetadataType& metadataType, get_cb hidlCb);
 
diff --git a/cros_gralloc/gralloc4/CrosGralloc4Metadata.h b/cros_gralloc/gralloc4/CrosGralloc4Metadata.h
deleted file mode 100644
index c908e35..0000000
--- a/cros_gralloc/gralloc4/CrosGralloc4Metadata.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright 2022 The Chromium OS Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef CROSGRALLOC4METADATA_H
-#define CROSGRALLOC4METADATA_H
-
-#include <aidl/android/hardware/graphics/common/BlendMode.h>
-#include <aidl/android/hardware/graphics/common/Cta861_3.h>
-#include <aidl/android/hardware/graphics/common/Dataspace.h>
-#include <aidl/android/hardware/graphics/common/Smpte2086.h>
-
-#define CROS_GRALLOC4_METADATA_MAX_NAME_SIZE 1024
-
-/*
- * The metadata for cros_gralloc_buffer-s that should reside in a shared memory region
- * instead of directly in cros_gralloc_handle-s.
- *
- * Any metadata that is mutable must be stored in this shared memory region as
- * cros_gralloc_handle-s can not be tracked and updated across processes.
- */
-struct CrosGralloc4Metadata {
-    /*
-     * Name is stored in the shared memory metadata to simplify cros_gralloc_handle
-     * creation. This allows us to keep handles small while avoiding variable sized
-     * handles.
-     */
-    char name[CROS_GRALLOC4_METADATA_MAX_NAME_SIZE];
-    aidl::android::hardware::graphics::common::BlendMode blendMode;
-    aidl::android::hardware::graphics::common::Dataspace dataspace;
-    std::optional<aidl::android::hardware::graphics::common::Cta861_3> cta861_3;
-    std::optional<aidl::android::hardware::graphics::common::Smpte2086> smpte2086;
-};
-
-#endif
diff --git a/cros_gralloc/gralloc4/CrosGralloc4Utils.cc b/cros_gralloc/gralloc4/CrosGralloc4Utils.cc
index 25b42b5..703e50f 100644
--- a/cros_gralloc/gralloc4/CrosGralloc4Utils.cc
+++ b/cros_gralloc/gralloc4/CrosGralloc4Utils.cc
@@ -62,7 +62,8 @@
     outCrosDescriptor->height = descriptor.height;
     outCrosDescriptor->droid_format = static_cast<int32_t>(descriptor.format);
     outCrosDescriptor->droid_usage = descriptor.usage;
-    outCrosDescriptor->reserved_region_size = descriptor.reservedSize;
+    outCrosDescriptor->enable_metadata_fd = true;
+    outCrosDescriptor->client_metadata_size = descriptor.reservedSize;
     if (descriptor.layerCount > 1) {
         ALOGE("Failed to convert descriptor. Unsupported layerCount: %d", descriptor.layerCount);
         return -EINVAL;
diff --git a/cros_gralloc/mapper_stablec/Android.bp b/cros_gralloc/mapper_stablec/Android.bp
new file mode 100644
index 0000000..401c177
--- /dev/null
+++ b/cros_gralloc/mapper_stablec/Android.bp
@@ -0,0 +1,51 @@
+//
+// Copyright (C) 2022 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "external_minigbm_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    //   SPDX-license-identifier-BSD
+    default_applicable_licenses: ["external_minigbm_license"],
+}
+
+cc_library_shared {
+    name: "mapper.minigbm",
+    defaults: ["minigbm_gralloc4_common_defaults"],
+    vintf_fragments: ["mapper.minigbm.xml"],
+    shared_libs: [
+        "android.hardware.graphics.allocator-V2-ndk",
+        "libminigbm_gralloc",
+    ],
+    header_libs: [
+        "libbase_headers",
+        "libimapper_stablec",
+        "libimapper_providerutils",
+    ],
+    srcs: [
+        ":minigbm_gralloc4_mapper_files",
+        "Mapper.cpp",
+    ],
+    cpp_std: "c++20",
+}
+
+prebuilt_etc {
+    name: "mapper.minigbm.xml",
+    src: "mapper.minigbm.xml",
+    sub_dir: "vintf",
+    installable: false,
+}
diff --git a/cros_gralloc/mapper_stablec/Mapper.cpp b/cros_gralloc/mapper_stablec/Mapper.cpp
index c28d7f9..866f0dd 100644
--- a/cros_gralloc/mapper_stablec/Mapper.cpp
+++ b/cros_gralloc/mapper_stablec/Mapper.cpp
@@ -19,7 +19,6 @@
 
 #include "cros_gralloc/cros_gralloc_driver.h"
 #include "cros_gralloc/cros_gralloc_handle.h"
-#include "cros_gralloc/gralloc4/CrosGralloc4Metadata.h"
 #include "cros_gralloc/gralloc4/CrosGralloc4Utils.h"
 
 using namespace ::aidl::android::hardware::graphics::common;
@@ -43,7 +42,7 @@
     REQUIRE_DRIVER()                                    \
     VALIDATE_BUFFER_HANDLE(bufferHandle)
 
-static_assert(CROS_GRALLOC4_METADATA_MAX_NAME_SIZE >=
+static_assert(CROS_GRALLOC_BUFFER_METADATA_MAX_NAME_SIZE >=
                       decltype(std::declval<BufferDescriptorInfo>().name){}.size(),
               "Metadata name storage too small to fit a BufferDescriptorInfo::name");
 
@@ -109,30 +108,12 @@
                                      uint64_t* _Nonnull outReservedSize) override;
 
   private:
-    enum class ReservedRegionArea {
-        /* CrosGralloc4Metadata */
-        MAPPER4_METADATA,
-
-        /* External user metadata */
-        USER_METADATA,
-    };
-
-    AIMapper_Error getReservedRegionArea(const cros_gralloc_buffer* crosBuffer,
-                                         ReservedRegionArea area, void** outAddr,
-                                         uint64_t* outSize);
-
-    AIMapper_Error getCrosMetadata(const cros_gralloc_buffer* crosBuffer,
-                                   const CrosGralloc4Metadata** outMetadata);
-
-    AIMapper_Error getMutableCrosMetadata(cros_gralloc_buffer* crosBuffer,
-                                          CrosGralloc4Metadata** outMetadata);
-
     template <typename F, StandardMetadataType TYPE>
     int32_t getStandardMetadata(const cros_gralloc_buffer* crosBuffer, F&& provide,
                                 StandardMetadata<TYPE>);
 
     template <StandardMetadataType TYPE>
-    AIMapper_Error setStandardMetadata(CrosGralloc4Metadata* crosMetadata,
+    AIMapper_Error setStandardMetadata(cros_gralloc_buffer* crosBuffer,
                                        typename StandardMetadata<TYPE>::value_type&& value);
 
     void dumpBuffer(
@@ -329,23 +310,16 @@
 template <typename F, StandardMetadataType metadataType>
 int32_t CrosGrallocMapperV5::getStandardMetadata(const cros_gralloc_buffer* crosBuffer, F&& provide,
                                                  StandardMetadata<metadataType>) {
-    const CrosGralloc4Metadata* crosMetadata = nullptr;
-    if constexpr (metadataType == StandardMetadataType::BLEND_MODE ||
-                  metadataType == StandardMetadataType::CTA861_3 ||
-                  metadataType == StandardMetadataType::DATASPACE ||
-                  metadataType == StandardMetadataType::NAME ||
-                  metadataType == StandardMetadataType::SMPTE2086) {
-        AIMapper_Error error = getCrosMetadata(crosBuffer, &crosMetadata);
-        if (error != AIMAPPER_ERROR_NONE) {
-            ALOGE("Failed to get. Failed to get buffer metadata.");
-            return -AIMAPPER_ERROR_NO_RESOURCES;
-        }
-    }
     if constexpr (metadataType == StandardMetadataType::BUFFER_ID) {
         return provide(crosBuffer->get_id());
     }
     if constexpr (metadataType == StandardMetadataType::NAME) {
-        return provide(crosMetadata->name);
+        std::optional<std::string> name;
+        if (crosBuffer->get_name(&name)) {
+            return -AIMAPPER_ERROR_NO_RESOURCES;
+        } else {
+            return provide(*name);
+        }
     }
     if constexpr (metadataType == StandardMetadataType::WIDTH) {
         return provide(crosBuffer->get_width());
@@ -423,16 +397,36 @@
         return provide(crops);
     }
     if constexpr (metadataType == StandardMetadataType::DATASPACE) {
-        return provide(crosMetadata->dataspace);
+        std::optional<Dataspace> dataspace;
+        if (crosBuffer->get_dataspace(&dataspace)) {
+            return -AIMAPPER_ERROR_NO_RESOURCES;
+        } else {
+            return provide(*dataspace);
+        }
     }
     if constexpr (metadataType == StandardMetadataType::BLEND_MODE) {
-        return provide(crosMetadata->blendMode);
+        std::optional<BlendMode> blend;
+        if (crosBuffer->get_blend_mode(&blend)) {
+            return -AIMAPPER_ERROR_NO_RESOURCES;
+        } else {
+            return provide(*blend);
+        }
     }
     if constexpr (metadataType == StandardMetadataType::SMPTE2086) {
-        return crosMetadata->smpte2086 ? provide(*crosMetadata->smpte2086) : 0;
+        std::optional<Smpte2086> smpte;
+        if (crosBuffer->get_smpte2086(&smpte)) {
+            return -AIMAPPER_ERROR_NO_RESOURCES;
+        } else {
+            return smpte ? provide(*smpte) : 0;
+        }
     }
     if constexpr (metadataType == StandardMetadataType::CTA861_3) {
-        return crosMetadata->cta861_3 ? provide(*crosMetadata->cta861_3) : 0;
+        std::optional<Cta861_3> cta;
+        if (crosBuffer->get_cta861_3(&cta)) {
+            return -AIMAPPER_ERROR_NO_RESOURCES;
+        } else {
+            return cta ? provide(*cta) : 0;
+        }
     }
     return -AIMAPPER_ERROR_UNSUPPORTED;
 }
@@ -488,14 +482,8 @@
 
     AIMapper_Error status = AIMAPPER_ERROR_UNSUPPORTED;
     mDriver->with_buffer(crosHandle, [&](cros_gralloc_buffer* crosBuffer) {
-        CrosGralloc4Metadata* crosMetadata = nullptr;
-        status = getMutableCrosMetadata(crosBuffer, &crosMetadata);
-        if (status != AIMAPPER_ERROR_NONE) {
-            return;
-        }
-
         auto applier = [&]<StandardMetadataType T>(auto&& value) -> AIMapper_Error {
-            return setStandardMetadata<T>(crosMetadata, std::forward<decltype(value)>(value));
+            return setStandardMetadata<T>(crosBuffer, std::forward<decltype(value)>(value));
         };
 
         status = applyStandardMetadata(standardType, metadata, metadataSize, applier);
@@ -505,19 +493,25 @@
 
 template <StandardMetadataType TYPE>
 AIMapper_Error CrosGrallocMapperV5::setStandardMetadata(
-        CrosGralloc4Metadata* crosMetadata, typename StandardMetadata<TYPE>::value_type&& value) {
+        cros_gralloc_buffer* crosBuffer, typename StandardMetadata<TYPE>::value_type&& value) {
+    int ret = 0;
     if constexpr (TYPE == StandardMetadataType::BLEND_MODE) {
-        crosMetadata->blendMode = value;
+        ret = crosBuffer->set_blend_mode(value);
     }
     if constexpr (TYPE == StandardMetadataType::CTA861_3) {
-        crosMetadata->cta861_3 = value;
+        ret = crosBuffer->set_cta861_3(value);
     }
     if constexpr (TYPE == StandardMetadataType::DATASPACE) {
-        crosMetadata->dataspace = value;
+        ret = crosBuffer->set_dataspace(value);
     }
     if constexpr (TYPE == StandardMetadataType::SMPTE2086) {
-        crosMetadata->smpte2086 = value;
+        ret = crosBuffer->set_smpte2086(value);
     }
+
+    if (ret) {
+        return AIMAPPER_ERROR_NO_RESOURCES;
+    }
+
     // Unsupported metadatas were already filtered before we reached this point
     return AIMAPPER_ERROR_NONE;
 }
@@ -667,78 +661,23 @@
     uint64_t reservedRegionSize = 0;
 
     AIMapper_Error error = AIMAPPER_ERROR_NONE;
-    mDriver->with_buffer(crosHandle, [&, this](cros_gralloc_buffer* crosBuffer) {
-        error = getReservedRegionArea(crosBuffer, ReservedRegionArea::USER_METADATA,
-                                      &reservedRegionAddr, &reservedRegionSize);
+    mDriver->with_buffer(crosHandle, [&](cros_gralloc_buffer* crosBuffer) {
+        int ret = crosBuffer->get_client_reserved_region(&reservedRegionAddr, &reservedRegionSize);
+        if (ret) {
+            reservedRegionAddr = nullptr;
+            reservedRegionSize = 0;
+            error = AIMAPPER_ERROR_NO_RESOURCES;
+        }
     });
 
     if (error != AIMAPPER_ERROR_NONE) {
-        ALOGE("Failed to getReservedRegion. Failed to getReservedRegionArea.");
+        ALOGE("Failed to getReservedRegion. Failed to getReservedRegion.");
         return AIMAPPER_ERROR_BAD_BUFFER;
     }
 
     return AIMAPPER_ERROR_NONE;
 }
 
-AIMapper_Error CrosGrallocMapperV5::getReservedRegionArea(const cros_gralloc_buffer* crosBuffer,
-                                                          ReservedRegionArea area, void** outAddr,
-                                                          uint64_t* outSize) {
-    int ret = crosBuffer->get_reserved_region(outAddr, outSize);
-    if (ret) {
-        ALOGE("Failed to getReservedRegionArea.");
-        *outAddr = nullptr;
-        *outSize = 0;
-        return AIMAPPER_ERROR_NO_RESOURCES;
-    }
-
-    switch (area) {
-        case ReservedRegionArea::MAPPER4_METADATA: {
-            // CrosGralloc4Metadata resides at the beginning reserved region.
-            *outSize = sizeof(CrosGralloc4Metadata);
-            break;
-        }
-        case ReservedRegionArea::USER_METADATA: {
-            // User metadata resides after the CrosGralloc4Metadata.
-            *outAddr = reinterpret_cast<void*>(reinterpret_cast<char*>(*outAddr) +
-                                               sizeof(CrosGralloc4Metadata));
-            *outSize = *outSize - sizeof(CrosGralloc4Metadata);
-            break;
-        }
-    }
-
-    return AIMAPPER_ERROR_NONE;
-}
-
-AIMapper_Error CrosGrallocMapperV5::getCrosMetadata(const cros_gralloc_buffer* crosBuffer,
-                                                    const CrosGralloc4Metadata** outMetadata) {
-    void* addr = nullptr;
-    uint64_t size;
-
-    auto error =
-            getReservedRegionArea(crosBuffer, ReservedRegionArea::MAPPER4_METADATA, &addr, &size);
-    if (error != AIMAPPER_ERROR_NONE) {
-        return error;
-    }
-
-    *outMetadata = reinterpret_cast<const CrosGralloc4Metadata*>(addr);
-    return AIMAPPER_ERROR_NONE;
-}
-
-AIMapper_Error CrosGrallocMapperV5::getMutableCrosMetadata(cros_gralloc_buffer* crosBuffer,
-                                                           CrosGralloc4Metadata** outMetadata) {
-    void* addr = nullptr;
-    uint64_t size;
-
-    auto error =
-            getReservedRegionArea(crosBuffer, ReservedRegionArea::MAPPER4_METADATA, &addr, &size);
-    if (error != AIMAPPER_ERROR_NONE) {
-        return error;
-    }
-
-    *outMetadata = reinterpret_cast<CrosGralloc4Metadata*>(addr);
-    return AIMAPPER_ERROR_NONE;
-}
-
 extern "C" uint32_t ANDROID_HAL_MAPPER_VERSION = AIMAPPER_VERSION_5;
 
 extern "C" AIMapper_Error AIMapper_loadIMapper(AIMapper* _Nullable* _Nonnull outImplementation) {
diff --git a/drv_helpers.h b/drv_helpers.h
index 873bd08..1c347f8 100644
--- a/drv_helpers.h
+++ b/drv_helpers.h
@@ -7,6 +7,10 @@
 #ifndef DRV_HELPERS_H
 #define DRV_HELPERS_H
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 #include <stdbool.h>
 
 #include "drv.h"
@@ -72,4 +76,8 @@
 void lru_insert(struct lru *lru, struct lru_entry *entry);
 void lru_init(struct lru *lru, int max);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif
diff --git a/rust/gbm_wrapper.h b/rust/gbm_wrapper.h
new file mode 100644
index 0000000..abcf3af
--- /dev/null
+++ b/rust/gbm_wrapper.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2024 Google LLC
+ */
+
+#include <gbm.h>
+
+// bindgen doesn't create constants for macros that expand to other macros
+// https://github.com/Smithay/gbm.rs/blob/606c4260e0147256fb5c2901bbe837c0dc7d9f2d/gbm-sys/build.rs#L16
+
+const unsigned int __BINDGEN_TMP_GBM_BO_IMPORT_WL_BUFFER = GBM_BO_IMPORT_WL_BUFFER;
+#undef GBM_BO_IMPORT_WL_BUFFER
+const unsigned int GBM_BO_IMPORT_WL_BUFFER = __BINDGEN_TMP_GBM_BO_IMPORT_WL_BUFFER;
+#define GBM_BO_IMPORT_WL_BUFFER GBM_BO_IMPORT_WL_BUFFER
+
+const unsigned int __BINDGEN_TMP_GBM_BO_IMPORT_EGL_IMAGE = GBM_BO_IMPORT_EGL_IMAGE;
+#undef GBM_BO_IMPORT_EGL_IMAGE
+const unsigned int GBM_BO_IMPORT_EGL_IMAGE = __BINDGEN_TMP_GBM_BO_IMPORT_EGL_IMAGE;
+#define GBM_BO_IMPORT_EGL_IMAGE GBM_BO_IMPORT_EGL_IMAGE
+
+const unsigned int __BINDGEN_TMP_GBM_BO_IMPORT_FD = GBM_BO_IMPORT_FD;
+#undef GBM_BO_IMPORT_FD
+const unsigned int GBM_BO_IMPORT_FD = __BINDGEN_TMP_GBM_BO_IMPORT_FD;
+#define GBM_BO_IMPORT_FD GBM_BO_IMPORT_FD
+
+const unsigned int __BINDGEN_TMP_GBM_BO_IMPORT_FD_MODIFIER = GBM_BO_IMPORT_FD_MODIFIER;
+#undef GBM_BO_IMPORT_FD_MODIFIER
+const unsigned int GBM_BO_IMPORT_FD_MODIFIER = __BINDGEN_TMP_GBM_BO_IMPORT_FD_MODIFIER;
+#define GBM_BO_IMPORT_FD_MODIFIER GBM_BO_IMPORT_FD_MODIFIER
diff --git a/virtgpu_virgl.c b/virtgpu_virgl.c
index 20f2f32..763bdbc 100644
--- a/virtgpu_virgl.c
+++ b/virtgpu_virgl.c
@@ -48,8 +48,9 @@
 };
 
 static const uint32_t texture_source_formats[] = {
-	DRM_FORMAT_NV21,	   DRM_FORMAT_R8,	   DRM_FORMAT_R16,	    DRM_FORMAT_RG88,
-	DRM_FORMAT_YVU420_ANDROID, DRM_FORMAT_ABGR2101010, DRM_FORMAT_ABGR16161616F
+	DRM_FORMAT_NV12,	DRM_FORMAT_NV21,	 DRM_FORMAT_R8,
+	DRM_FORMAT_R16,	        DRM_FORMAT_RG88,	 DRM_FORMAT_YVU420_ANDROID,
+	DRM_FORMAT_ABGR2101010, DRM_FORMAT_ABGR16161616F
 };
 
 static const uint32_t depth_stencil_formats[] = {