Snap for 8253222 from ee8cf75deb53583e269f1a9b4588793708a9c15d to sdk-release

Change-Id: I2e585a2ade9d17e40c8d3d0c18e4497c3b94eed7
diff --git a/Android.bp b/Android.bp
index 9eb75e5..3038f22 100644
--- a/Android.bp
+++ b/Android.bp
@@ -113,6 +113,7 @@
 
     shared_libs: [
         "libcutils",
+        "libdmabufheap",
         "libdrm",
         "libnativewindow",
         "libsync",
diff --git a/cros_gralloc/cros_gralloc_buffer.cc b/cros_gralloc/cros_gralloc_buffer.cc
index 2f4ceb0..e1af7a4 100644
--- a/cros_gralloc/cros_gralloc_buffer.cc
+++ b/cros_gralloc/cros_gralloc_buffer.cc
@@ -9,34 +9,110 @@
 #include <assert.h>
 #include <sys/mman.h>
 
-cros_gralloc_buffer::cros_gralloc_buffer(uint32_t id, struct bo *acquire_bo,
-					 struct cros_gralloc_handle *acquire_handle,
-					 int32_t reserved_region_fd, uint64_t reserved_region_size)
-    : id_(id), bo_(acquire_bo), hnd_(acquire_handle), refcount_(1), lockcount_(0),
-      reserved_region_fd_(reserved_region_fd), reserved_region_size_(reserved_region_size),
-      reserved_region_addr_(nullptr)
+#include <cutils/native_handle.h>
+
+/*static*/
+std::unique_ptr<cros_gralloc_buffer>
+cros_gralloc_buffer::create(struct bo *acquire_bo,
+			    const struct cros_gralloc_handle *borrowed_handle)
+{
+	auto acquire_hnd =
+	    reinterpret_cast<struct cros_gralloc_handle *>(native_handle_clone(borrowed_handle));
+	if (!acquire_hnd) {
+		drv_log("Failed to create cros_gralloc_buffer: failed to clone handle.\n");
+		return {};
+	}
+
+	std::unique_ptr<cros_gralloc_buffer> buffer(
+	    new cros_gralloc_buffer(acquire_bo, acquire_hnd));
+	if (!buffer) {
+		drv_log("Failed to create cros_gralloc_buffer: failed to allocate.\n");
+		native_handle_close(acquire_hnd);
+		native_handle_delete(acquire_hnd);
+		return {};
+	}
+
+	return buffer;
+}
+
+cros_gralloc_buffer::cros_gralloc_buffer(struct bo *acquire_bo,
+					 struct cros_gralloc_handle *acquire_handle)
+    : bo_(acquire_bo), hnd_(acquire_handle)
 {
 	assert(bo_);
-	num_planes_ = drv_bo_get_num_planes(bo_);
-	for (uint32_t plane = 0; plane < num_planes_; plane++)
+	assert(hnd_);
+	for (uint32_t plane = 0; plane < DRV_MAX_PLANES; plane++)
 		lock_data_[plane] = nullptr;
 }
 
 cros_gralloc_buffer::~cros_gralloc_buffer()
 {
 	drv_bo_destroy(bo_);
-	if (hnd_) {
-		native_handle_close(hnd_);
-		native_handle_delete(hnd_);
-	}
 	if (reserved_region_addr_) {
-		munmap(reserved_region_addr_, reserved_region_size_);
+		munmap(reserved_region_addr_, hnd_->reserved_region_size);
 	}
+	native_handle_close(hnd_);
+	native_handle_delete(hnd_);
 }
 
 uint32_t cros_gralloc_buffer::get_id() const
 {
-	return id_;
+	return hnd_->id;
+}
+
+uint32_t cros_gralloc_buffer::get_width() const
+{
+	return hnd_->width;
+}
+
+uint32_t cros_gralloc_buffer::get_height() const
+{
+	return hnd_->height;
+}
+
+uint32_t cros_gralloc_buffer::get_format() const
+{
+	return hnd_->format;
+}
+
+uint64_t cros_gralloc_buffer::get_format_modifier() const
+{
+	return hnd_->format_modifier;
+}
+
+uint64_t cros_gralloc_buffer::get_total_size() const
+{
+	return hnd_->total_size;
+}
+
+uint32_t cros_gralloc_buffer::get_num_planes() const
+{
+	return hnd_->num_planes;
+}
+
+uint32_t cros_gralloc_buffer::get_plane_offset(uint32_t plane) const
+{
+	return hnd_->offsets[plane];
+}
+
+uint32_t cros_gralloc_buffer::get_plane_stride(uint32_t plane) const
+{
+	return hnd_->strides[plane];
+}
+
+uint32_t cros_gralloc_buffer::get_plane_size(uint32_t plane) const
+{
+	return hnd_->sizes[plane];
+}
+
+int32_t cros_gralloc_buffer::get_android_format() const
+{
+	return hnd_->droid_format;
+}
+
+uint64_t cros_gralloc_buffer::get_android_usage() const
+{
+	return static_cast<uint64_t>(hnd_->usage);
 }
 
 int32_t cros_gralloc_buffer::increase_refcount()
@@ -91,7 +167,7 @@
 		}
 	}
 
-	for (uint32_t plane = 0; plane < num_planes_; plane++)
+	for (uint32_t plane = 0; plane < hnd_->num_planes; plane++)
 		addr[plane] = static_cast<uint8_t *>(vaddr) + drv_bo_get_plane_offset(bo_, plane);
 
 	lockcount_++;
@@ -148,16 +224,18 @@
 	return 0;
 }
 
-int32_t cros_gralloc_buffer::get_reserved_region(void **addr, uint64_t *size)
+int32_t cros_gralloc_buffer::get_reserved_region(void **addr, uint64_t *size) const
 {
-	if (reserved_region_fd_ <= 0) {
+	int32_t reserved_region_fd = hnd_->fds[hnd_->num_planes];
+	if (reserved_region_fd < 0) {
 		drv_log("Buffer does not have reserved region.\n");
 		return -EINVAL;
 	}
 
 	if (!reserved_region_addr_) {
-		reserved_region_addr_ = mmap(nullptr, reserved_region_size_, PROT_WRITE | PROT_READ,
-					     MAP_SHARED, reserved_region_fd_, 0);
+		reserved_region_addr_ =
+		    mmap(nullptr, hnd_->reserved_region_size, PROT_WRITE | PROT_READ, MAP_SHARED,
+			 reserved_region_fd, 0);
 		if (reserved_region_addr_ == MAP_FAILED) {
 			drv_log("Failed to mmap reserved region: %s.\n", strerror(errno));
 			return -errno;
@@ -165,6 +243,6 @@
 	}
 
 	*addr = reserved_region_addr_;
-	*size = reserved_region_size_;
+	*size = hnd_->reserved_region_size;
 	return 0;
 }
diff --git a/cros_gralloc/cros_gralloc_buffer.h b/cros_gralloc/cros_gralloc_buffer.h
index 3158454..21f8306 100644
--- a/cros_gralloc/cros_gralloc_buffer.h
+++ b/cros_gralloc/cros_gralloc_buffer.h
@@ -7,17 +7,30 @@
 #ifndef CROS_GRALLOC_BUFFER_H
 #define CROS_GRALLOC_BUFFER_H
 
+#include <memory>
+
 #include "cros_gralloc_helpers.h"
 
 class cros_gralloc_buffer
 {
       public:
-	cros_gralloc_buffer(uint32_t id, struct bo *acquire_bo,
-			    struct cros_gralloc_handle *acquire_handle, int32_t reserved_region_fd,
-			    uint64_t reserved_region_size);
+	static std::unique_ptr<cros_gralloc_buffer>
+	create(struct bo *acquire_bo, const struct cros_gralloc_handle *borrowed_handle);
+
 	~cros_gralloc_buffer();
 
 	uint32_t get_id() const;
+	uint32_t get_width() const;
+	uint32_t get_height() const;
+	uint32_t get_format() const;
+	uint64_t get_format_modifier() const;
+	uint64_t get_total_size() const;
+	uint32_t get_num_planes() const;
+	uint32_t get_plane_offset(uint32_t plane) const;
+	uint32_t get_plane_stride(uint32_t plane) const;
+	uint32_t get_plane_size(uint32_t plane) const;
+	int32_t get_android_format() const;
+	uint64_t get_android_usage() const;
 
 	/* The new reference count is returned by both these functions. */
 	int32_t increase_refcount();
@@ -32,28 +45,27 @@
 	int32_t invalidate();
 	int32_t flush();
 
-	int32_t get_reserved_region(void **reserved_region_addr, uint64_t *reserved_region_size);
+	int32_t get_reserved_region(void **reserved_region_addr,
+				    uint64_t *reserved_region_size) const;
 
       private:
+	cros_gralloc_buffer(struct bo *acquire_bo, struct cros_gralloc_handle *acquire_handle);
+
 	cros_gralloc_buffer(cros_gralloc_buffer const &);
 	cros_gralloc_buffer operator=(cros_gralloc_buffer const &);
 
-	uint32_t id_;
 	struct bo *bo_;
 
 	/* Note: this will be nullptr for imported/retained buffers. */
 	struct cros_gralloc_handle *hnd_;
 
-	int32_t refcount_;
-	int32_t lockcount_;
-	uint32_t num_planes_;
+	int32_t refcount_ = 1;
+	int32_t lockcount_ = 0;
 
 	struct mapping *lock_data_[DRV_MAX_PLANES];
 
 	/* Optional additional shared memory region attached to some gralloc buffers. */
-	int32_t reserved_region_fd_;
-	uint64_t reserved_region_size_;
-	void *reserved_region_addr_;
+	mutable void *reserved_region_addr_ = nullptr;
 };
 
 #endif
diff --git a/cros_gralloc/cros_gralloc_driver.cc b/cros_gralloc/cros_gralloc_driver.cc
index 1381ff5..6ac094d 100644
--- a/cros_gralloc/cros_gralloc_driver.cc
+++ b/cros_gralloc/cros_gralloc_driver.cc
@@ -44,6 +44,22 @@
 	return fd;
 }
 
+int memfd_create_reserved_region(const std::string &buffer_name, uint64_t reserved_region_size)
+{
+	const std::string reserved_region_name = buffer_name + " reserved region";
+
+	int reserved_region_fd = memfd_create_wrapper(reserved_region_name.c_str(), FD_CLOEXEC);
+	if (reserved_region_fd == -1)
+		return -errno;
+
+	if (ftruncate(reserved_region_fd, reserved_region_size)) {
+		drv_log("Failed to set reserved region size: %s.\n", strerror(errno));
+		return -errno;
+	}
+
+	return reserved_region_fd;
+}
+
 cros_gralloc_driver *cros_gralloc_driver::get_instance()
 {
 	static cros_gralloc_driver s_instance;
@@ -78,7 +94,7 @@
 	return drv;
 }
 
-cros_gralloc_driver::cros_gralloc_driver()
+static struct driver *init_try_nodes()
 {
 	/*
 	 * Create a driver from render nodes first, then try card
@@ -87,6 +103,7 @@
 	 * TODO(gsingh): Enable render nodes on udl/evdi.
 	 */
 
+	struct driver *drv;
 	char const *render_nodes_fmt = "%s/renderD%d";
 	char const *card_nodes_fmt = "%s/card%d";
 	uint32_t num_nodes = DRM_NUM_NODES;
@@ -97,30 +114,36 @@
 
 	// Try render nodes...
 	for (uint32_t i = min_render_node; i < max_render_node; i++) {
-		drv_ = init_try_node(i, render_nodes_fmt);
-		if (drv_)
-			return;
+		drv = init_try_node(i, render_nodes_fmt);
+		if (drv)
+			return drv;
 	}
 
 	// Try card nodes... for vkms mostly.
 	for (uint32_t i = min_card_node; i < max_card_node; i++) {
-		drv_ = init_try_node(i, card_nodes_fmt);
-		if (drv_)
-			return;
+		drv = init_try_node(i, card_nodes_fmt);
+		if (drv)
+			return drv;
 	}
+
+	return nullptr;
+}
+
+static void drv_destroy_and_close(struct driver *drv)
+{
+	int fd = drv_get_fd(drv);
+	drv_destroy(drv);
+	close(fd);
+}
+
+cros_gralloc_driver::cros_gralloc_driver() : drv_(init_try_nodes(), drv_destroy_and_close)
+{
 }
 
 cros_gralloc_driver::~cros_gralloc_driver()
 {
 	buffers_.clear();
 	handles_.clear();
-
-	if (drv_) {
-		int fd = drv_get_fd(drv_);
-		drv_destroy(drv_);
-		drv_ = nullptr;
-		close(fd);
-	}
 }
 
 bool cros_gralloc_driver::is_initialized()
@@ -136,10 +159,10 @@
 	uint64_t resolved_use_flags;
 	struct combination *combo;
 
-	drv_resolve_format_and_use_flags(drv_, descriptor->drm_format, descriptor->use_flags,
+	drv_resolve_format_and_use_flags(drv_.get(), descriptor->drm_format, descriptor->use_flags,
 					 &resolved_format, &resolved_use_flags);
 
-	combo = drv_get_combination(drv_, resolved_format, resolved_use_flags);
+	combo = drv_get_combination(drv_.get(), resolved_format, resolved_use_flags);
 	if (!combo && (descriptor->droid_usage & GRALLOC_USAGE_HW_VIDEO_ENCODER) &&
 	    descriptor->droid_format != HAL_PIXEL_FORMAT_YCbCr_420_888) {
 		// Unmask BO_USE_HW_VIDEO_ENCODER for other formats. They are mostly
@@ -147,12 +170,12 @@
 		// camera). YV12 is passed to the encoder component, but it is converted
 		// to YCbCr_420_888 before being passed to the hw encoder.
 		resolved_use_flags &= ~BO_USE_HW_VIDEO_ENCODER;
-		combo = drv_get_combination(drv_, resolved_format, resolved_use_flags);
+		combo = drv_get_combination(drv_.get(), resolved_format, resolved_use_flags);
 	}
 	if (!combo && (descriptor->droid_usage & BUFFER_USAGE_FRONT_RENDERING)) {
 		resolved_use_flags &= ~BO_USE_FRONT_RENDERING;
 		resolved_use_flags |= BO_USE_LINEAR;
-		combo = drv_get_combination(drv_, resolved_format, resolved_use_flags);
+		combo = drv_get_combination(drv_.get(), resolved_format, resolved_use_flags);
 	}
 	if (!combo)
 		return false;
@@ -166,7 +189,7 @@
 {
 	uint32_t resolved_format;
 	uint64_t resolved_use_flags;
-	uint32_t max_texture_size = drv_get_max_texture_2d_size(drv_);
+	uint32_t max_texture_size = drv_get_max_texture_2d_size(drv_.get());
 	if (!get_resolved_format_and_use_flags(descriptor, &resolved_format, &resolved_use_flags))
 		return false;
 
@@ -177,53 +200,45 @@
 	return descriptor->width <= max_texture_size && descriptor->height <= max_texture_size;
 }
 
-int32_t create_reserved_region(const std::string &buffer_name, uint64_t reserved_region_size)
+int cros_gralloc_driver::create_reserved_region(const std::string &buffer_name,
+						uint64_t reserved_region_size)
 {
-	std::string reserved_region_name = buffer_name + " reserved region";
+	int ret;
 
-	int32_t reserved_region_fd = memfd_create_wrapper(reserved_region_name.c_str(), FD_CLOEXEC);
-	if (reserved_region_fd == -1)
-		return -errno;
+#if ANDROID_API_LEVEL >= 31
+	ret = allocator_.Alloc(kDmabufSystemHeapName, reserved_region_size);
+	if (ret >= 0)
+		return ret;
+#endif
 
-	if (ftruncate(reserved_region_fd, reserved_region_size)) {
-		drv_log("Failed to set reserved region size: %s.\n", strerror(errno));
-		return -errno;
-	}
+	ret = memfd_create_reserved_region(buffer_name, reserved_region_size);
+	if (ret >= 0)
+		return ret;
 
-	return reserved_region_fd;
-}
-
-void cros_gralloc_driver::emplace_buffer(struct bo *bo, struct cros_gralloc_handle *hnd)
-{
-	auto buffer = new cros_gralloc_buffer(hnd->id, bo, hnd, hnd->fds[hnd->num_planes],
-					      hnd->reserved_region_size);
-
-	std::lock_guard<std::mutex> lock(mutex_);
-	buffers_.emplace(hnd->id, buffer);
-	handles_.emplace(hnd, std::make_pair(buffer, 1));
+	drv_log("Failed to create_reserved_region.\n");
+	return -1;
 }
 
 int32_t cros_gralloc_driver::allocate(const struct cros_gralloc_buffer_descriptor *descriptor,
-				      buffer_handle_t *out_handle)
+				      native_handle_t **out_handle)
 {
 	int ret = 0;
 	size_t num_planes;
 	size_t num_fds;
 	size_t num_ints;
-	size_t num_bytes;
 	uint32_t resolved_format;
 	uint32_t bytes_per_pixel;
 	uint64_t resolved_use_flags;
-	char *name;
 	struct bo *bo;
 	struct cros_gralloc_handle *hnd;
+	std::unique_ptr<cros_gralloc_buffer> buffer;
 
 	if (!get_resolved_format_and_use_flags(descriptor, &resolved_format, &resolved_use_flags)) {
 		drv_log("Failed to resolve format and use_flags.\n");
 		return -EINVAL;
 	}
 
-	bo = drv_bo_create(drv_, descriptor->width, descriptor->height, resolved_format,
+	bo = drv_bo_create(drv_.get(), descriptor->width, descriptor->height, resolved_format,
 			   resolved_use_flags);
 	if (!bo) {
 		drv_log("Failed to create bo.\n");
@@ -246,14 +261,8 @@
 	if (descriptor->reserved_region_size > 0)
 		num_fds += 1;
 
-	num_bytes = sizeof(struct cros_gralloc_handle);
-	num_bytes += (descriptor->name.size() + 1);
-	/*
-	 * Ensure that the total number of bytes is a multiple of sizeof(int) as
-	 * native_handle_clone() copies data based on hnd->base.numInts.
-	 */
-	num_bytes = ALIGN(num_bytes, sizeof(int));
-	num_ints = ((num_bytes - sizeof(native_handle_t)) / sizeof(int)) - num_fds;
+	num_ints = ((sizeof(struct cros_gralloc_handle) - sizeof(native_handle_t)) / sizeof(int)) -
+		   num_fds;
 
 	hnd =
 	    reinterpret_cast<struct cros_gralloc_handle *>(native_handle_create(num_fds, num_ints));
@@ -296,14 +305,26 @@
 	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->name_offset = handle_data_size;
 
-	name = (char *)(&hnd->data[hnd->name_offset]);
-	snprintf(name, descriptor->name.size() + 1, "%s", descriptor->name.c_str());
+	buffer = cros_gralloc_buffer::create(bo, hnd);
+	if (!buffer) {
+		drv_log("Failed to allocate: failed to create cros_gralloc_buffer.\n");
+		ret = -1;
+		goto destroy_hnd;
+	}
 
-	emplace_buffer(bo, hnd);
+	{
+		std::lock_guard<std::mutex> lock(mutex_);
 
-	*out_handle = reinterpret_cast<buffer_handle_t>(hnd);
+		struct cros_gralloc_imported_handle_info hnd_info = {
+			.buffer = buffer.get(),
+			.refcount = 1,
+		};
+		handles_.emplace(hnd, hnd_info);
+		buffers_.emplace(hnd->id, std::move(buffer));
+	}
+
+	*out_handle = hnd;
 	return 0;
 
 destroy_hnd:
@@ -317,7 +338,6 @@
 
 int32_t cros_gralloc_driver::retain(buffer_handle_t handle)
 {
-	uint32_t id;
 	std::lock_guard<std::mutex> lock(mutex_);
 
 	auto hnd = cros_gralloc_convert_handle(handle);
@@ -326,43 +346,65 @@
 		return -EINVAL;
 	}
 
-	auto buffer = get_buffer(hnd);
-	if (buffer) {
-		handles_[hnd].second++;
-		buffer->increase_refcount();
+	auto hnd_it = handles_.find(hnd);
+	if (hnd_it != handles_.end()) {
+		// The underlying buffer (as multiple handles can refer to the same buffer)
+		// has already been imported into this process and the given handle has
+		// already been registered in this process. Increase both the buffer and
+		// handle reference count.
+		auto &hnd_info = hnd_it->second;
+
+		hnd_info.buffer->increase_refcount();
+		hnd_info.refcount++;
+
 		return 0;
 	}
 
-	id = hnd->id;
+	uint32_t id = hnd->id;
 
-	if (buffers_.count(id)) {
-		buffer = buffers_[id];
+	cros_gralloc_buffer *buffer = nullptr;
+
+	auto buffer_it = buffers_.find(id);
+	if (buffer_it != buffers_.end()) {
+		// The underlying buffer (as multiple handles can refer to the same buffer)
+		// has already been imported into this process but the given handle has not
+		// yet been registered. Increase the buffer reference count (here) and start
+		// to track the handle (below).
+		buffer = buffer_it->second.get();
 		buffer->increase_refcount();
 	} else {
-		struct bo *bo;
-		struct drv_import_fd_data data;
-		data.format = hnd->format;
-		data.tiling = hnd->tiling;
-
-		data.width = hnd->width;
-		data.height = hnd->height;
-		data.use_flags = hnd->use_flags;
-
+		// The underlying buffer has not yet been imported into this process. Import
+		// and start to track the buffer (here) and start to track the handle (below).
+		struct drv_import_fd_data data = {
+			.format_modifier = hnd->format_modifier,
+			.width = hnd->width,
+			.height = hnd->height,
+			.format = hnd->format,
+			.tiling = hnd->tiling,
+			.use_flags = hnd->use_flags,
+		};
 		memcpy(data.fds, hnd->fds, sizeof(data.fds));
 		memcpy(data.strides, hnd->strides, sizeof(data.strides));
 		memcpy(data.offsets, hnd->offsets, sizeof(data.offsets));
-		data.format_modifier = hnd->format_modifier;
 
-		bo = drv_bo_import(drv_, &data);
+		struct bo *bo = drv_bo_import(drv_.get(), &data);
 		if (!bo)
 			return -EFAULT;
 
-		buffer = new cros_gralloc_buffer(id, bo, nullptr, hnd->fds[hnd->num_planes],
-						 hnd->reserved_region_size);
-		buffers_.emplace(id, buffer);
+		auto scoped_buffer = cros_gralloc_buffer::create(bo, hnd);
+		if (!scoped_buffer) {
+			drv_log("Failed to import: failed to create cros_gralloc_buffer.\n");
+			return -1;
+		}
+		buffer = scoped_buffer.get();
+		buffers_.emplace(id, std::move(scoped_buffer));
 	}
 
-	handles_.emplace(hnd, std::make_pair(buffer, 1));
+	struct cros_gralloc_imported_handle_info hnd_info = {
+		.buffer = buffer,
+		.refcount = 1,
+	};
+	handles_.emplace(hnd, hnd_info);
 	return 0;
 }
 
@@ -378,16 +420,15 @@
 
 	auto buffer = get_buffer(hnd);
 	if (!buffer) {
-		drv_log("Invalid Reference.\n");
+		drv_log("Invalid reference (release() called on unregistered handle).\n");
 		return -EINVAL;
 	}
 
-	if (!--handles_[hnd].second)
+	if (!--handles_[hnd].refcount)
 		handles_.erase(hnd);
 
 	if (buffer->decrease_refcount() == 0) {
 		buffers_.erase(buffer->get_id());
-		delete buffer;
 	}
 
 	return 0;
@@ -402,6 +443,7 @@
 		return ret;
 
 	std::lock_guard<std::mutex> lock(mutex_);
+
 	auto hnd = cros_gralloc_convert_handle(handle);
 	if (!hnd) {
 		drv_log("Invalid handle.\n");
@@ -410,7 +452,7 @@
 
 	auto buffer = get_buffer(hnd);
 	if (!buffer) {
-		drv_log("Invalid Reference.\n");
+		drv_log("Invalid reference (lock() called on unregistered handle).\n");
 		return -EINVAL;
 	}
 
@@ -429,7 +471,7 @@
 
 	auto buffer = get_buffer(hnd);
 	if (!buffer) {
-		drv_log("Invalid Reference.\n");
+		drv_log("Invalid reference (unlock() called on unregistered handle).\n");
 		return -EINVAL;
 	}
 
@@ -455,7 +497,7 @@
 
 	auto buffer = get_buffer(hnd);
 	if (!buffer) {
-		drv_log("Invalid Reference.\n");
+		drv_log("Invalid reference (invalidate() called on unregistered handle).\n");
 		return -EINVAL;
 	}
 
@@ -474,7 +516,7 @@
 
 	auto buffer = get_buffer(hnd);
 	if (!buffer) {
-		drv_log("Invalid Reference.\n");
+		drv_log("Invalid reference (flush() called on unregistered handle).\n");
 		return -EINVAL;
 	}
 
@@ -500,7 +542,7 @@
 
 	auto buffer = get_buffer(hnd);
 	if (!buffer) {
-		drv_log("Invalid Reference.\n");
+		drv_log("Invalid reference (get_backing_store() called on unregistered handle).\n");
 		return -EINVAL;
 	}
 
@@ -522,7 +564,7 @@
 
 	auto buffer = get_buffer(hnd);
 	if (!buffer) {
-		drv_log("Invalid Reference.\n");
+		drv_log("Invalid reference (resource_info() called on unregistered handle).\n");
 		return -EINVAL;
 	}
 
@@ -543,7 +585,8 @@
 
 	auto buffer = get_buffer(hnd);
 	if (!buffer) {
-		drv_log("Invalid Reference.\n");
+		drv_log(
+		    "Invalid reference (get_reserved_region() called on unregistered handle).\n");
 		return -EINVAL;
 	}
 
@@ -555,7 +598,7 @@
 	uint32_t resolved_format;
 	uint64_t resolved_use_flags;
 
-	drv_resolve_format_and_use_flags(drv_, drm_format, use_flags, &resolved_format,
+	drv_resolve_format_and_use_flags(drv_.get(), drm_format, use_flags, &resolved_format,
 					 &resolved_use_flags);
 
 	return resolved_format;
@@ -565,16 +608,30 @@
 {
 	/* Assumes driver mutex is held. */
 	if (handles_.count(hnd))
-		return handles_[hnd].first;
+		return handles_[hnd].buffer;
 
 	return nullptr;
 }
 
-void cros_gralloc_driver::for_each_handle(
-    const std::function<void(cros_gralloc_handle_t)> &function)
+void cros_gralloc_driver::with_buffer(cros_gralloc_handle_t hnd,
+				      const std::function<void(cros_gralloc_buffer *)> &function)
 {
 	std::lock_guard<std::mutex> lock(mutex_);
 
-	for (const auto &pair : handles_)
-		function(pair.first);
+	auto buffer = get_buffer(hnd);
+	if (!buffer) {
+		drv_log("Invalid reference (with_buffer() called on unregistered handle).\n");
+		return;
+	}
+
+	function(buffer);
+}
+
+void cros_gralloc_driver::with_each_buffer(
+    const std::function<void(cros_gralloc_buffer *)> &function)
+{
+	std::lock_guard<std::mutex> lock(mutex_);
+
+	for (const auto &pair : buffers_)
+		function(pair.second.get());
 }
diff --git a/cros_gralloc/cros_gralloc_driver.h b/cros_gralloc/cros_gralloc_driver.h
index d1456a8..d9528d7 100644
--- a/cros_gralloc/cros_gralloc_driver.h
+++ b/cros_gralloc/cros_gralloc_driver.h
@@ -10,16 +10,22 @@
 #include "cros_gralloc_buffer.h"
 
 #include <functional>
+#include <memory>
 #include <mutex>
+#include <string>
 #include <unordered_map>
 
+#if ANDROID_API_LEVEL >= 31
+#include <BufferAllocator/BufferAllocator.h>
+#endif
+
 class cros_gralloc_driver
 {
       public:
 	static cros_gralloc_driver *get_instance();
 	bool is_supported(const struct cros_gralloc_buffer_descriptor *descriptor);
 	int32_t allocate(const struct cros_gralloc_buffer_descriptor *descriptor,
-			 buffer_handle_t *out_handle);
+			 native_handle_t **out_handle);
 
 	int32_t retain(buffer_handle_t handle);
 	int32_t release(buffer_handle_t handle);
@@ -41,23 +47,42 @@
 
 	uint32_t get_resolved_drm_format(uint32_t drm_format, uint64_t use_flags);
 
-	void for_each_handle(const std::function<void(cros_gralloc_handle_t)> &function);
+	void with_buffer(cros_gralloc_handle_t hnd,
+			 const std::function<void(cros_gralloc_buffer *)> &function);
+	void with_each_buffer(const std::function<void(cros_gralloc_buffer *)> &function);
 
       private:
 	cros_gralloc_driver();
 	~cros_gralloc_driver();
 	bool is_initialized();
 	cros_gralloc_buffer *get_buffer(cros_gralloc_handle_t hnd);
-	void emplace_buffer(struct bo *bo, struct cros_gralloc_handle *hnd);
 	bool
 	get_resolved_format_and_use_flags(const struct cros_gralloc_buffer_descriptor *descriptor,
 					  uint32_t *out_format, uint64_t *out_use_flags);
 
-	struct driver *drv_ = nullptr;
+	int create_reserved_region(const std::string &buffer_name, uint64_t reserved_region_size);
+
+#if ANDROID_API_LEVEL >= 31
+	/* For allocating cros_gralloc_buffer reserved regions for metadata. */
+	BufferAllocator allocator_;
+#endif
+
+	std::unique_ptr<struct driver, void (*)(struct driver *)> drv_;
+
+	struct cros_gralloc_imported_handle_info {
+		/*
+		 * The underlying buffer for referred to by this handle (as multiple handles can
+		 * refer to the same buffer).
+		 */
+		cros_gralloc_buffer *buffer = nullptr;
+
+		/* The handle's refcount as a handle can be imported multiple times.*/
+		int32_t refcount = 1;
+	};
+
 	std::mutex mutex_;
-	std::unordered_map<uint32_t, cros_gralloc_buffer *> buffers_;
-	std::unordered_map<cros_gralloc_handle_t, std::pair<cros_gralloc_buffer *, int32_t>>
-	    handles_;
+	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_;
 };
 
 #endif
diff --git a/cros_gralloc/cros_gralloc_handle.h b/cros_gralloc/cros_gralloc_handle.h
index 2b70d4b..2d0e1ac 100644
--- a/cros_gralloc/cros_gralloc_handle.h
+++ b/cros_gralloc/cros_gralloc_handle.h
@@ -40,10 +40,6 @@
 	uint32_t num_planes;
 	uint64_t reserved_region_size;
 	uint64_t total_size; /* Total allocation size */
-	/*
-	 * Name is a null terminated char array located at handle->base.data[handle->name_offset].
-	 */
-	uint32_t name_offset;
 } __attribute__((packed));
 
 typedef const struct cros_gralloc_handle *cros_gralloc_handle_t;
diff --git a/cros_gralloc/gralloc0/gralloc0.cc b/cros_gralloc/gralloc0/gralloc0.cc
index 53c89fd..ce62521 100644
--- a/cros_gralloc/gralloc0/gralloc0.cc
+++ b/cros_gralloc/gralloc0/gralloc0.cc
@@ -8,6 +8,7 @@
 #include "../cros_gralloc_driver.h"
 
 #include <cassert>
+#include <cutils/native_handle.h>
 #include <hardware/gralloc.h>
 #include <memory.h>
 
@@ -67,9 +68,10 @@
 }
 
 static int gralloc0_alloc(alloc_device_t *dev, int w, int h, int format, int usage,
-			  buffer_handle_t *handle, int *stride)
+			  buffer_handle_t *out_handle, int *out_stride)
 {
 	int32_t ret;
+	native_handle_t *handle;
 	struct cros_gralloc_buffer_descriptor descriptor;
 	auto mod = (struct gralloc0_module const *)dev->common.module;
 
@@ -89,20 +91,31 @@
 		return -EINVAL;
 	}
 
-	ret = mod->driver->allocate(&descriptor, handle);
+	ret = mod->driver->allocate(&descriptor, &handle);
 	if (ret)
 		return ret;
 
-	auto hnd = cros_gralloc_convert_handle(*handle);
-	*stride = hnd->pixel_stride;
+	auto hnd = cros_gralloc_convert_handle(handle);
+	*out_handle = handle;
+	*out_stride = hnd->pixel_stride;
 
 	return 0;
 }
 
 static int gralloc0_free(alloc_device_t *dev, buffer_handle_t handle)
 {
+	int32_t ret;
 	auto mod = (struct gralloc0_module const *)dev->common.module;
-	return mod->driver->release(handle);
+
+	ret = mod->driver->release(handle);
+	if (ret)
+		return ret;
+
+	auto hnd = const_cast<native_handle_t *>(handle);
+	native_handle_close(hnd);
+	native_handle_delete(hnd);
+
+	return 0;
 }
 
 static int gralloc0_close(struct hw_device_t *dev)
diff --git a/cros_gralloc/gralloc4/CrosGralloc4Allocator.cc b/cros_gralloc/gralloc4/CrosGralloc4Allocator.cc
index 0368e1a..6610c5e 100644
--- a/cros_gralloc/gralloc4/CrosGralloc4Allocator.cc
+++ b/cros_gralloc/gralloc4/CrosGralloc4Allocator.cc
@@ -10,8 +10,11 @@
 #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;
+using aidl::android::hardware::graphics::common::Dataspace;
 using android::hardware::hidl_handle;
 using android::hardware::hidl_vec;
 using android::hardware::Return;
@@ -28,6 +31,37 @@
     return mDriver ? Error::NONE : Error::NO_RESOURCES;
 }
 
+Error CrosGralloc4Allocator::initializeMetadata(
+        cros_gralloc_handle_t crosHandle,
+        const struct cros_gralloc_buffer_descriptor& crosDescriptor) {
+    if (!mDriver) {
+        drv_log("Failed to initializeMetadata. Driver is uninitialized.\n");
+        return Error::NO_RESOURCES;
+    }
+
+    if (!crosHandle) {
+        drv_log("Failed to initializeMetadata. Invalid handle.\n");
+        return Error::BAD_BUFFER;
+    }
+
+    void* addr;
+    uint64_t size;
+    int ret = mDriver->get_reserved_region(crosHandle, &addr, &size);
+    if (ret) {
+        drv_log("Failed to getReservedRegion.\n");
+        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) {
@@ -44,6 +78,8 @@
         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);
@@ -53,18 +89,24 @@
         return Error::UNSUPPORTED;
     }
 
-    buffer_handle_t handle;
+    native_handle_t* handle;
     int ret = mDriver->allocate(&crosDescriptor, &handle);
     if (ret) {
         return Error::NO_RESOURCES;
     }
 
+    outHandle->setTo(handle, /*shouldOwn=*/true);
+
     cros_gralloc_handle_t crosHandle = cros_gralloc_convert_handle(handle);
     if (!crosHandle) {
         return Error::NO_RESOURCES;
     }
 
-    *outHandle = handle;
+    Error error = initializeMetadata(crosHandle, crosDescriptor);
+    if (error != Error::NONE) {
+        return error;
+    }
+
     *outStride = crosHandle->pixel_stride;
 
     return Error::NONE;
diff --git a/cros_gralloc/gralloc4/CrosGralloc4Allocator.h b/cros_gralloc/gralloc4/CrosGralloc4Allocator.h
index 1555a61..9c1c783 100644
--- a/cros_gralloc/gralloc4/CrosGralloc4Allocator.h
+++ b/cros_gralloc/gralloc4/CrosGralloc4Allocator.h
@@ -8,6 +8,8 @@
 #include <android/hardware/graphics/mapper/4.0/IMapper.h>
 
 #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:
@@ -19,6 +21,10 @@
     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 8f952e1..cc2c4d5 100644
--- a/cros_gralloc/gralloc4/CrosGralloc4Mapper.cc
+++ b/cros_gralloc/gralloc4/CrosGralloc4Mapper.cc
@@ -418,11 +418,13 @@
         return Void();
     }
 
-    get(crosHandle, metadataType, hidlCb);
+    mDriver->with_buffer(crosHandle, [&, this](cros_gralloc_buffer* crosBuffer) {
+        get(crosBuffer, metadataType, hidlCb);
+    });
     return Void();
 }
 
-Return<void> CrosGralloc4Mapper::get(cros_gralloc_handle_t crosHandle,
+Return<void> CrosGralloc4Mapper::get(const cros_gralloc_buffer* crosBuffer,
                                      const MetadataType& metadataType, get_cb hidlCb) {
     hidl_vec<uint8_t> encodedMetadata;
 
@@ -432,40 +434,54 @@
         return Void();
     }
 
-    if (!crosHandle) {
-        drv_log("Failed to get. Invalid handle.\n");
+    if (!crosBuffer) {
+        drv_log("Failed to get. Invalid buffer.\n");
         hidlCb(Error::BAD_BUFFER, encodedMetadata);
         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) {
+            drv_log("Failed to get. Failed to get buffer metadata.\n");
+            hidlCb(Error::NO_RESOURCES, encodedMetadata);
+            return Void();
+        }
+    }
+
     android::status_t status = android::NO_ERROR;
     if (metadataType == android::gralloc4::MetadataType_BufferId) {
-        status = android::gralloc4::encodeBufferId(crosHandle->id, &encodedMetadata);
+        status = android::gralloc4::encodeBufferId(crosBuffer->get_id(), &encodedMetadata);
     } else if (metadataType == android::gralloc4::MetadataType_Name) {
-        const char* name = (const char*)(&crosHandle->data[crosHandle->name_offset]);
-        status = android::gralloc4::encodeName(name, &encodedMetadata);
+        status = android::gralloc4::encodeName(crosMetadata->name, &encodedMetadata);
     } else if (metadataType == android::gralloc4::MetadataType_Width) {
-        status = android::gralloc4::encodeWidth(crosHandle->width, &encodedMetadata);
+        status = android::gralloc4::encodeWidth(crosBuffer->get_width(), &encodedMetadata);
     } else if (metadataType == android::gralloc4::MetadataType_Height) {
-        status = android::gralloc4::encodeHeight(crosHandle->height, &encodedMetadata);
+        status = android::gralloc4::encodeHeight(crosBuffer->get_height(), &encodedMetadata);
     } else if (metadataType == android::gralloc4::MetadataType_LayerCount) {
         status = android::gralloc4::encodeLayerCount(1, &encodedMetadata);
     } else if (metadataType == android::gralloc4::MetadataType_PixelFormatRequested) {
-        PixelFormat pixelFormat = static_cast<PixelFormat>(crosHandle->droid_format);
+        PixelFormat pixelFormat = static_cast<PixelFormat>(crosBuffer->get_android_format());
         status = android::gralloc4::encodePixelFormatRequested(pixelFormat, &encodedMetadata);
     } else if (metadataType == android::gralloc4::MetadataType_PixelFormatFourCC) {
         status = android::gralloc4::encodePixelFormatFourCC(
-                drv_get_standard_fourcc(crosHandle->format), &encodedMetadata);
+                drv_get_standard_fourcc(crosBuffer->get_format()), &encodedMetadata);
     } else if (metadataType == android::gralloc4::MetadataType_PixelFormatModifier) {
-        status = android::gralloc4::encodePixelFormatModifier(crosHandle->format_modifier,
+        status = android::gralloc4::encodePixelFormatModifier(crosBuffer->get_format_modifier(),
                                                               &encodedMetadata);
     } else if (metadataType == android::gralloc4::MetadataType_Usage) {
-        uint64_t usage = static_cast<uint64_t>(crosHandle->usage);
-        status = android::gralloc4::encodeUsage(usage, &encodedMetadata);
+        status = android::gralloc4::encodeUsage(crosBuffer->get_android_usage(), &encodedMetadata);
     } else if (metadataType == android::gralloc4::MetadataType_AllocationSize) {
-        status = android::gralloc4::encodeAllocationSize(crosHandle->total_size, &encodedMetadata);
+        status = android::gralloc4::encodeAllocationSize(crosBuffer->get_total_size(),
+                                                         &encodedMetadata);
     } else if (metadataType == android::gralloc4::MetadataType_ProtectedContent) {
-        uint64_t hasProtectedContent = crosHandle->usage & BufferUsage::PROTECTED ? 1 : 0;
+        uint64_t hasProtectedContent =
+                crosBuffer->get_android_usage() & BufferUsage::PROTECTED ? 1 : 0;
         status = android::gralloc4::encodeProtectedContent(hasProtectedContent, &encodedMetadata);
     } else if (metadataType == android::gralloc4::MetadataType_Compression) {
         status = android::gralloc4::encodeCompression(android::gralloc4::Compression_None,
@@ -478,38 +494,43 @@
                                                        &encodedMetadata);
     } else if (metadataType == android::gralloc4::MetadataType_PlaneLayouts) {
         std::vector<PlaneLayout> planeLayouts;
-        getPlaneLayouts(crosHandle->format, &planeLayouts);
+        getPlaneLayouts(crosBuffer->get_format(), &planeLayouts);
 
         for (size_t plane = 0; plane < planeLayouts.size(); plane++) {
             PlaneLayout& planeLayout = planeLayouts[plane];
-            planeLayout.offsetInBytes = crosHandle->offsets[plane];
-            planeLayout.strideInBytes = crosHandle->strides[plane];
-            planeLayout.totalSizeInBytes = crosHandle->sizes[plane];
-            planeLayout.widthInSamples = crosHandle->width / planeLayout.horizontalSubsampling;
-            planeLayout.heightInSamples = crosHandle->height / planeLayout.verticalSubsampling;
+            planeLayout.offsetInBytes = crosBuffer->get_plane_offset(plane);
+            planeLayout.strideInBytes = crosBuffer->get_plane_stride(plane);
+            planeLayout.totalSizeInBytes = crosBuffer->get_plane_size(plane);
+            planeLayout.widthInSamples =
+                    crosBuffer->get_width() / planeLayout.horizontalSubsampling;
+            planeLayout.heightInSamples =
+                    crosBuffer->get_height() / planeLayout.verticalSubsampling;
         }
 
         status = android::gralloc4::encodePlaneLayouts(planeLayouts, &encodedMetadata);
     } else if (metadataType == android::gralloc4::MetadataType_Crop) {
+        const uint32_t numPlanes = crosBuffer->get_num_planes();
+        const uint32_t w = crosBuffer->get_width();
+        const uint32_t h = crosBuffer->get_height();
         std::vector<aidl::android::hardware::graphics::common::Rect> crops;
-        for (size_t plane = 0; plane < crosHandle->num_planes; plane++) {
+        for (uint32_t plane = 0; plane < numPlanes; plane++) {
             aidl::android::hardware::graphics::common::Rect crop;
             crop.left = 0;
             crop.top = 0;
-            crop.right = crosHandle->width;
-            crop.bottom = crosHandle->height;
+            crop.right = w;
+            crop.bottom = h;
             crops.push_back(crop);
         }
 
         status = android::gralloc4::encodeCrop(crops, &encodedMetadata);
     } else if (metadataType == android::gralloc4::MetadataType_Dataspace) {
-        status = android::gralloc4::encodeDataspace(Dataspace::UNKNOWN, &encodedMetadata);
+        status = android::gralloc4::encodeDataspace(crosMetadata->dataspace, &encodedMetadata);
     } else if (metadataType == android::gralloc4::MetadataType_BlendMode) {
-        status = android::gralloc4::encodeBlendMode(BlendMode::INVALID, &encodedMetadata);
+        status = android::gralloc4::encodeBlendMode(crosMetadata->blendMode, &encodedMetadata);
     } else if (metadataType == android::gralloc4::MetadataType_Smpte2086) {
-        status = android::gralloc4::encodeSmpte2086(std::nullopt, &encodedMetadata);
+        status = android::gralloc4::encodeSmpte2086(crosMetadata->smpte2086, &encodedMetadata);
     } else if (metadataType == android::gralloc4::MetadataType_Cta861_3) {
-        status = android::gralloc4::encodeCta861_3(std::nullopt, &encodedMetadata);
+        status = android::gralloc4::encodeCta861_3(crosMetadata->cta861_3, &encodedMetadata);
     } else if (metadataType == android::gralloc4::MetadataType_Smpte2094_40) {
         status = android::gralloc4::encodeSmpte2094_40(std::nullopt, &encodedMetadata);
     } else {
@@ -528,7 +549,7 @@
 }
 
 Return<Error> CrosGralloc4Mapper::set(void* rawHandle, const MetadataType& metadataType,
-                                      const hidl_vec<uint8_t>& /*metadata*/) {
+                                      const hidl_vec<uint8_t>& encodedMetadata) {
     if (!mDriver) {
         drv_log("Failed to set. Driver is uninitialized.\n");
         return Error::NO_RESOURCES;
@@ -562,7 +583,68 @@
         return Error::BAD_VALUE;
     }
 
-    return Error::UNSUPPORTED;
+    if (metadataType != android::gralloc4::MetadataType_BlendMode &&
+        metadataType != android::gralloc4::MetadataType_Cta861_3 &&
+        metadataType != android::gralloc4::MetadataType_Dataspace &&
+        metadataType != android::gralloc4::MetadataType_Smpte2086) {
+        return Error::UNSUPPORTED;
+    }
+
+    Error error = Error::NONE;
+    mDriver->with_buffer(crosHandle, [&, this](cros_gralloc_buffer* crosBuffer) {
+        error = set(crosBuffer, metadataType, encodedMetadata);
+    });
+
+    return error;
+}
+
+Error CrosGralloc4Mapper::set(cros_gralloc_buffer* crosBuffer, const MetadataType& metadataType,
+                              const android::hardware::hidl_vec<uint8_t>& encodedMetadata) {
+    if (!mDriver) {
+        drv_log("Failed to set. Driver is uninitialized.\n");
+        return Error::NO_RESOURCES;
+    }
+
+    if (!crosBuffer) {
+        drv_log("Failed to set. Invalid buffer.\n");
+        return Error::BAD_BUFFER;
+    }
+
+    CrosGralloc4Metadata* crosMetadata = nullptr;
+
+    Error error = getMutableMetadata(crosBuffer, &crosMetadata);
+    if (error != Error::NONE) {
+        drv_log("Failed to set. Failed to get buffer metadata.\n");
+        return Error::UNSUPPORTED;
+    }
+
+    if (metadataType == android::gralloc4::MetadataType_BlendMode) {
+        auto status = android::gralloc4::decodeBlendMode(encodedMetadata, &crosMetadata->blendMode);
+        if (status != android::NO_ERROR) {
+            drv_log("Failed to set. Failed to decode blend mode.\n");
+            return Error::UNSUPPORTED;
+        }
+    } else if (metadataType == android::gralloc4::MetadataType_Cta861_3) {
+        auto status = android::gralloc4::decodeCta861_3(encodedMetadata, &crosMetadata->cta861_3);
+        if (status != android::NO_ERROR) {
+            drv_log("Failed to set. Failed to decode cta861_3.\n");
+            return Error::UNSUPPORTED;
+        }
+    } else if (metadataType == android::gralloc4::MetadataType_Dataspace) {
+        auto status = android::gralloc4::decodeDataspace(encodedMetadata, &crosMetadata->dataspace);
+        if (status != android::NO_ERROR) {
+            drv_log("Failed to set. Failed to decode dataspace.\n");
+            return Error::UNSUPPORTED;
+        }
+    } else if (metadataType == android::gralloc4::MetadataType_Smpte2086) {
+        auto status = android::gralloc4::decodeSmpte2086(encodedMetadata, &crosMetadata->smpte2086);
+        if (status != android::NO_ERROR) {
+            drv_log("Failed to set. Failed to decode smpte2086.\n");
+            return Error::UNSUPPORTED;
+        }
+    }
+
+    return Error::NONE;
 }
 
 int CrosGralloc4Mapper::getResolvedDrmFormat(PixelFormat pixelFormat, uint64_t bufferUsage,
@@ -787,25 +869,25 @@
                     android::gralloc4::MetadataType_Dataspace,
                     "",
                     /*isGettable=*/true,
-                    /*isSettable=*/false,
+                    /*isSettable=*/true,
             },
             {
                     android::gralloc4::MetadataType_BlendMode,
                     "",
                     /*isGettable=*/true,
-                    /*isSettable=*/false,
+                    /*isSettable=*/true,
             },
             {
                     android::gralloc4::MetadataType_Smpte2086,
                     "",
                     /*isGettable=*/true,
-                    /*isSettable=*/false,
+                    /*isSettable=*/true,
             },
             {
                     android::gralloc4::MetadataType_Cta861_3,
                     "",
                     /*isGettable=*/true,
-                    /*isSettable=*/false,
+                    /*isSettable=*/true,
             },
             {
                     android::gralloc4::MetadataType_Smpte2094_40,
@@ -842,10 +924,13 @@
         return Void();
     }
 
-    return dumpBuffer(crosHandle, hidlCb);
+    mDriver->with_buffer(crosHandle, [&, this](cros_gralloc_buffer* crosBuffer) {
+        dumpBuffer(crosBuffer, hidlCb);
+    });
+    return Void();
 }
 
-Return<void> CrosGralloc4Mapper::dumpBuffer(cros_gralloc_handle_t crosHandle,
+Return<void> CrosGralloc4Mapper::dumpBuffer(const cros_gralloc_buffer* crosBuffer,
                                             dumpBuffer_cb hidlCb) {
     BufferDump bufferDump;
 
@@ -855,12 +940,6 @@
         return Void();
     }
 
-    if (!crosHandle) {
-        drv_log("Failed to dumpBuffer. Invalid handle.\n");
-        hidlCb(Error::BAD_BUFFER, bufferDump);
-        return Void();
-    }
-
     std::vector<MetadataDump> metadataDumps;
 
     MetadataType metadataType = android::gralloc4::MetadataType_BufferId;
@@ -872,55 +951,55 @@
     };
 
     metadataType = android::gralloc4::MetadataType_BufferId;
-    get(crosHandle, metadataType, metadata_get_callback);
+    get(crosBuffer, metadataType, metadata_get_callback);
 
     metadataType = android::gralloc4::MetadataType_Name;
-    get(crosHandle, metadataType, metadata_get_callback);
+    get(crosBuffer, metadataType, metadata_get_callback);
 
     metadataType = android::gralloc4::MetadataType_Width;
-    get(crosHandle, metadataType, metadata_get_callback);
+    get(crosBuffer, metadataType, metadata_get_callback);
 
     metadataType = android::gralloc4::MetadataType_Height;
-    get(crosHandle, metadataType, metadata_get_callback);
+    get(crosBuffer, metadataType, metadata_get_callback);
 
     metadataType = android::gralloc4::MetadataType_LayerCount;
-    get(crosHandle, metadataType, metadata_get_callback);
+    get(crosBuffer, metadataType, metadata_get_callback);
 
     metadataType = android::gralloc4::MetadataType_PixelFormatRequested;
-    get(crosHandle, metadataType, metadata_get_callback);
+    get(crosBuffer, metadataType, metadata_get_callback);
 
     metadataType = android::gralloc4::MetadataType_PixelFormatFourCC;
-    get(crosHandle, metadataType, metadata_get_callback);
+    get(crosBuffer, metadataType, metadata_get_callback);
 
     metadataType = android::gralloc4::MetadataType_PixelFormatModifier;
-    get(crosHandle, metadataType, metadata_get_callback);
+    get(crosBuffer, metadataType, metadata_get_callback);
 
     metadataType = android::gralloc4::MetadataType_Usage;
-    get(crosHandle, metadataType, metadata_get_callback);
+    get(crosBuffer, metadataType, metadata_get_callback);
 
     metadataType = android::gralloc4::MetadataType_AllocationSize;
-    get(crosHandle, metadataType, metadata_get_callback);
+    get(crosBuffer, metadataType, metadata_get_callback);
 
     metadataType = android::gralloc4::MetadataType_ProtectedContent;
-    get(crosHandle, metadataType, metadata_get_callback);
+    get(crosBuffer, metadataType, metadata_get_callback);
 
     metadataType = android::gralloc4::MetadataType_Compression;
-    get(crosHandle, metadataType, metadata_get_callback);
+    get(crosBuffer, metadataType, metadata_get_callback);
 
     metadataType = android::gralloc4::MetadataType_Interlaced;
-    get(crosHandle, metadataType, metadata_get_callback);
+    get(crosBuffer, metadataType, metadata_get_callback);
 
     metadataType = android::gralloc4::MetadataType_ChromaSiting;
-    get(crosHandle, metadataType, metadata_get_callback);
+    get(crosBuffer, metadataType, metadata_get_callback);
 
     metadataType = android::gralloc4::MetadataType_PlaneLayouts;
-    get(crosHandle, metadataType, metadata_get_callback);
+    get(crosBuffer, metadataType, metadata_get_callback);
 
     metadataType = android::gralloc4::MetadataType_Dataspace;
-    get(crosHandle, metadataType, metadata_get_callback);
+    get(crosBuffer, metadataType, metadata_get_callback);
 
     metadataType = android::gralloc4::MetadataType_BlendMode;
-    get(crosHandle, metadataType, metadata_get_callback);
+    get(crosBuffer, metadataType, metadata_get_callback);
 
     bufferDump.metadataDump = metadataDumps;
     hidlCb(Error::NONE, bufferDump);
@@ -938,22 +1017,89 @@
 
     Error error = Error::NONE;
 
-    auto handleCallback = [&](cros_gralloc_handle_t crosHandle) {
-        auto dumpBufferCallback = [&](Error err, BufferDump bufferDump) {
-            error = err;
-            if (error == Error::NONE) {
-                bufferDumps.push_back(bufferDump);
-            }
-        };
-
-        dumpBuffer(crosHandle, dumpBufferCallback);
+    const auto dumpBufferCallback = [&](Error err, BufferDump bufferDump) {
+        error = err;
+        if (error == Error::NONE) {
+            bufferDumps.push_back(bufferDump);
+        }
     };
-    mDriver->for_each_handle(handleCallback);
+
+    mDriver->with_each_buffer(
+            [&](cros_gralloc_buffer* crosBuffer) { dumpBuffer(crosBuffer, dumpBufferCallback); });
 
     hidlCb(error, bufferDumps);
     return Void();
 }
 
+Error CrosGralloc4Mapper::getReservedRegionArea(const cros_gralloc_buffer* crosBuffer,
+                                                ReservedRegionArea area, void** outAddr,
+                                                uint64_t* outSize) {
+    if (!mDriver) {
+        drv_log("Failed to getReservedRegionArea. Driver is uninitialized.\n");
+        return Error::NO_RESOURCES;
+    }
+
+    if (!crosBuffer) {
+        drv_log("Failed to getReservedRegionArea. Invalid buffer.\n");
+        return Error::BAD_BUFFER;
+    }
+
+    int ret = crosBuffer->get_reserved_region(outAddr, outSize);
+    if (ret) {
+        drv_log("Failed to getReservedRegionArea.\n");
+        *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) {
         drv_log("Failed to getReservedRegion. Driver is uninitialized.\n");
@@ -977,9 +1123,15 @@
 
     void* reservedRegionAddr = nullptr;
     uint64_t reservedRegionSize = 0;
-    int ret = mDriver->get_reserved_region(bufferHandle, &reservedRegionAddr, &reservedRegionSize);
-    if (ret) {
-        drv_log("Failed to getReservedRegion.\n");
+
+    Error error = Error::NONE;
+    mDriver->with_buffer(crosHandle, [&, this](cros_gralloc_buffer* crosBuffer) {
+        error = getReservedRegionArea(crosBuffer, ReservedRegionArea::USER_METADATA,
+                                      &reservedRegionAddr, &reservedRegionSize);
+    });
+
+    if (error != Error::NONE) {
+        drv_log("Failed to getReservedRegion. Failed to getReservedRegionArea.\n");
         hidlCb(Error::BAD_BUFFER, nullptr, 0);
         return Void();
     }
diff --git a/cros_gralloc/gralloc4/CrosGralloc4Mapper.h b/cros_gralloc/gralloc4/CrosGralloc4Mapper.h
index 0641b29..1734feb 100644
--- a/cros_gralloc/gralloc4/CrosGralloc4Mapper.h
+++ b/cros_gralloc/gralloc4/CrosGralloc4Mapper.h
@@ -8,6 +8,7 @@
 
 #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:
@@ -65,10 +66,32 @@
                                                       getReservedRegion_cb hidlCb) override;
 
   private:
-    android::hardware::Return<void> get(cros_gralloc_handle_t crosHandle,
+    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);
 
-    android::hardware::Return<void> dumpBuffer(cros_gralloc_handle_t crosHandle,
+    android::hardware::graphics::mapper::V4_0::Error set(
+            cros_gralloc_buffer* crosBuffer, const MetadataType& metadataType,
+            const android::hardware::hidl_vec<uint8_t>& metadata);
+
+    android::hardware::Return<void> dumpBuffer(const cros_gralloc_buffer* crosBuffer,
                                                dumpBuffer_cb hidlCb);
 
     int getResolvedDrmFormat(android::hardware::graphics::common::V1_2::PixelFormat pixelFormat,
diff --git a/cros_gralloc/gralloc4/CrosGralloc4Metadata.h b/cros_gralloc/gralloc4/CrosGralloc4Metadata.h
new file mode 100644
index 0000000..c908e35
--- /dev/null
+++ b/cros_gralloc/gralloc4/CrosGralloc4Metadata.h
@@ -0,0 +1,37 @@
+/*
+ * 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/dri.c b/dri.c
index 4ee133d..ea8c757 100644
--- a/dri.c
+++ b/dri.c
@@ -459,7 +459,7 @@
 	}
 
 	uint64_t planes;
-	GLboolean ret = dri->image_extension->queryDmaBufFormatModifierAttribs(
+	unsigned char ret = dri->image_extension->queryDmaBufFormatModifierAttribs(
 	    dri->device, format, modifier, __DRI_IMAGE_FORMAT_MODIFIER_ATTRIB_PLANE_COUNT, &planes);
 	if (!ret)
 		return 0;
diff --git a/i915.c b/i915.c
index 055c582..6a44448 100644
--- a/i915.c
+++ b/i915.c
@@ -41,6 +41,9 @@
 						 I915_FORMAT_MOD_Y_TILED, I915_FORMAT_MOD_X_TILED,
 						 DRM_FORMAT_MOD_LINEAR };
 
+static const uint64_t gen11_modifier_order[] = { I915_FORMAT_MOD_Y_TILED, I915_FORMAT_MOD_X_TILED,
+						 DRM_FORMAT_MOD_LINEAR };
+
 struct modifier_support_t {
 	const uint64_t *order;
 	uint32_t count;
@@ -163,6 +166,10 @@
 	if (i915->gen == 12) {
 		i915->modifier.order = gen12_modifier_order;
 		i915->modifier.count = ARRAY_SIZE(gen12_modifier_order);
+	}
+	else if (i915->gen == 11) {
+		i915->modifier.order = gen11_modifier_order;
+		i915->modifier.count = ARRAY_SIZE(gen11_modifier_order);
 	} else {
 		i915->modifier.order = gen_modifier_order;
 		i915->modifier.count = ARRAY_SIZE(gen_modifier_order);
diff --git a/mediatek.c b/mediatek.c
index 8456edd..cd3e641 100644
--- a/mediatek.c
+++ b/mediatek.c
@@ -32,6 +32,8 @@
 // All platforms except MT8173 should USE_NV12_FOR_HW_VIDEO_DECODING.
 #if defined(MTK_MT8183) || defined(MTK_MT8186) || defined(MTK_MT8192) || defined(MTK_MT8195)
 #define USE_NV12_FOR_HW_VIDEO_DECODING
+#else
+#define DONT_USE_64_ALIGNMENT_FOR_VIDEO_BUFFERS
 #endif
 
 struct mediatek_private_map_data {
@@ -56,8 +58,27 @@
 	DRM_FORMAT_YVU420,
 	DRM_FORMAT_YVU420_ANDROID
 };
+
+#ifdef DONT_USE_64_ALIGNMENT_FOR_VIDEO_BUFFERS
+static const uint32_t video_yuv_formats[] = {
+	DRM_FORMAT_NV21,
+	DRM_FORMAT_NV12,
+	DRM_FORMAT_YVU420,
+	DRM_FORMAT_YVU420_ANDROID
+};
 // clang-format on
 
+static bool is_video_yuv_format(uint32_t format)
+{
+	size_t i;
+	for (i = 0; i < ARRAY_SIZE(video_yuv_formats); ++i) {
+		if (format == video_yuv_formats[i])
+			return true;
+	}
+	return false;
+}
+#endif
+
 static int mediatek_init(struct driver *drv)
 {
 	struct format_metadata metadata;
@@ -130,10 +151,17 @@
 
 	/*
 	 * Since the ARM L1 cache line size is 64 bytes, align to that as a
-	 * performance optimization.
+	 * performance optimization, except for video buffers on certain platforms,
+	 * these should only be accessed from the GPU and VCODEC subsystems (maybe
+	 * also MDP), so it's better to align to macroblocks.
 	 */
 	stride = drv_stride_from_format(format, width, 0);
+#ifdef DONT_USE_64_ALIGNMENT_FOR_VIDEO_BUFFERS
+	const uint32_t alignment = is_video_yuv_format(format) ? 16 : 64;
+	stride = ALIGN(stride, alignment);
+#else
 	stride = ALIGN(stride, 64);
+#endif
 
 	if (bo->meta.use_flags & BO_USE_HW_VIDEO_ENCODER) {
 		uint32_t aligned_height = ALIGN(height, 32);
diff --git a/msm.c b/msm.c
index 255e723..14ecf2b 100644
--- a/msm.c
+++ b/msm.c
@@ -207,22 +207,6 @@
 		drv_log("WARNING: waffle detected, disabling UBWC\n");
 		return true;
 	}
-
-	/* The video_decode_accelerator_tests needs to read back the frames
-	 * to verify they are correct.  The frame verification relies on
-	 * computing the MD5 of the video frame.  UBWC results in a different
-	 * MD5.  This turns off UBWC for gtest until a proper frame
-	 * comparison can be made
-	 * Rely on the same mechanism that waffle is using, but this time check
-	 * for a dynamic library function that is present in chrome, but missing
-	 * in gtest.  Cups is not loaded for video tests.
-	 *
-	 * See b/171260705
-	 */
-	if (!dlsym(RTLD_DEFAULT, "cupsFilePrintf")) {
-		drv_log("WARNING: gtest detected, disabling UBWC\n");
-		return true;
-	}
 #endif
 	return false;
 }
diff --git a/virtgpu_virgl.c b/virtgpu_virgl.c
index c159c21..cbfae66 100644
--- a/virtgpu_virgl.c
+++ b/virtgpu_virgl.c
@@ -633,7 +633,7 @@
 	/* Android CTS tests require this. */
 	virgl_add_combination(drv, DRM_FORMAT_RGB888, &LINEAR_METADATA, BO_USE_SW_MASK);
 	virgl_add_combination(drv, DRM_FORMAT_BGR888, &LINEAR_METADATA, BO_USE_SW_MASK);
-	virgl_add_combination(drv, DRM_FORMAT_P010, &LINEAR_METADATA,
+	virgl_add_combination(drv, DRM_FORMAT_P010, &LINEAR_METADATA, BO_USE_TEXTURE |
 			      BO_USE_SW_MASK | BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE);
 	drv_modify_combination(drv, DRM_FORMAT_R8, &LINEAR_METADATA,
 			       BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE | BO_USE_HW_VIDEO_DECODER |