Snap for 10103804 from 9df12251ffa5aab3bf744c16004a0faffd796d41 to mainline-tzdata5-release

Change-Id: Ib15130ccbc346952109e2916eee7138fc3301edc
diff --git a/gralloc4/service/aidl/service.cpp b/gralloc4/service/aidl/service.cpp
index b6ccd44..515a31d 100644
--- a/gralloc4/service/aidl/service.cpp
+++ b/gralloc4/service/aidl/service.cpp
@@ -19,7 +19,7 @@
     AIBinder_setMinSchedulerPolicy(binder.get(), SCHED_NORMAL, -20);
 
     const auto instance = std::string() + GrallocAllocator::descriptor + "/default";
-    auto status = AServiceManager_addServiceWithFlag(binder.get(), instance.c_str(),
+    auto status = AServiceManager_addServiceWithFlags(binder.get(), instance.c_str(),
                                         AServiceManager_AddServiceFlag::ADD_SERVICE_ALLOW_ISOLATED);
     if (status != STATUS_OK) {
         ALOGE("Failed to start AIDL gralloc allocator service");
diff --git a/gralloc4/src/4.x/Android.bp b/gralloc4/src/4.x/Android.bp
index 88c7a01..16eec6a 100644
--- a/gralloc4/src/4.x/Android.bp
+++ b/gralloc4/src/4.x/Android.bp
@@ -50,7 +50,6 @@
 		"liblog",
 		"libcutils",
 		"libdmabufheap",
-		"libion_google",
 		"libsync",
 		"libutils",
 		"libnativewindow",
diff --git a/gralloc4/src/4.x/GrallocMapper.cpp b/gralloc4/src/4.x/GrallocMapper.cpp
index e0ac1de..c0b5f5f 100644
--- a/gralloc4/src/4.x/GrallocMapper.cpp
+++ b/gralloc4/src/4.x/GrallocMapper.cpp
@@ -35,14 +35,9 @@
 using android::hardware::Void;
 
 
-GrallocMapper::GrallocMapper()
-{
-}
+GrallocMapper::GrallocMapper() {}
 
-GrallocMapper::~GrallocMapper()
-{
-	mali_gralloc_ion_close();
-}
+GrallocMapper::~GrallocMapper() {}
 
 Return<void> GrallocMapper::createDescriptor(const BufferDescriptorInfo &descriptorInfo, createDescriptor_cb hidl_cb)
 {
diff --git a/gralloc4/src/Android.bp b/gralloc4/src/Android.bp
index 3511d12..a813fc8 100644
--- a/gralloc4/src/Android.bp
+++ b/gralloc4/src/Android.bp
@@ -68,7 +68,6 @@
 		"libhidlbase",
 		"libhidltransport",
 		"libnativewindow",
-		"libion_google",
 		"android.hardware.graphics.common@1.2",
 		"android.hardware.graphics.common-V4-ndk",
 		"android.hardware.graphics.mapper@4.0",
diff --git a/gralloc4/src/aidl/GrallocAllocator.cpp b/gralloc4/src/aidl/GrallocAllocator.cpp
index d7addc5..6945505 100644
--- a/gralloc4/src/aidl/GrallocAllocator.cpp
+++ b/gralloc4/src/aidl/GrallocAllocator.cpp
@@ -24,9 +24,7 @@
 
 GrallocAllocator::GrallocAllocator() {}
 
-GrallocAllocator::~GrallocAllocator() {
-    mali_gralloc_ion_close();
-}
+GrallocAllocator::~GrallocAllocator() {}
 
 ndk::ScopedAStatus GrallocAllocator::allocate(const std::vector<uint8_t>& descriptor, int32_t count,
                                               AidlAllocator::AllocationResult* result) {
diff --git a/gralloc4/src/allocator/Android.bp b/gralloc4/src/allocator/Android.bp
index 7a3cb31..fe42411 100644
--- a/gralloc4/src/allocator/Android.bp
+++ b/gralloc4/src/allocator/Android.bp
@@ -86,7 +86,6 @@
 		"liblog",
 		"libcutils",
 		"libdmabufheap",
-		"libion_google",
 		"libsync",
 		"libutils",
 		"libnativewindow",
diff --git a/gralloc4/src/allocator/mali_gralloc_ion.cpp b/gralloc4/src/allocator/mali_gralloc_ion.cpp
index bfd92d7..8bfc6d8 100644
--- a/gralloc4/src/allocator/mali_gralloc_ion.cpp
+++ b/gralloc4/src/allocator/mali_gralloc_ion.cpp
@@ -29,7 +29,6 @@
 #include <cutils/atomic.h>
 #include <utils/Trace.h>
 
-
 #include <linux/dma-buf.h>
 #include <vector>
 #include <sys/ioctl.h>
@@ -37,9 +36,6 @@
 #include <hardware/hardware.h>
 #include <hardware/gralloc1.h>
 
-#include <hardware/exynos/ion.h>
-#include <hardware/exynos/dmabuf_container.h>
-
 #include <BufferAllocator/BufferAllocator.h>
 #include "mali_gralloc_buffer.h"
 #include "gralloc_helper.h"
@@ -54,17 +50,6 @@
 #include <array>
 #include <string>
 
-#define INIT_ZERO(obj) (memset(&(obj), 0, sizeof((obj))))
-
-#define HEAP_MASK_FROM_ID(id) (1 << id)
-#define HEAP_MASK_FROM_TYPE(type) (1 << type)
-
-#if defined(ION_HEAP_SECURE_MASK)
-#if (HEAP_MASK_FROM_TYPE(ION_HEAP_TYPE_SECURE) != ION_HEAP_SECURE_MASK)
-#error "ION_HEAP_TYPE_SECURE value is not compatible with ION_HEAP_SECURE_MASK"
-#endif
-#endif
-
 static const char kDmabufSensorDirectHeapName[] = "sensor_direct_heap";
 static const char kDmabufFaceauthTpuHeapName[] = "faceauth_tpu-secure";
 static const char kDmabufFaceauthImgHeapName[] = "faimg-secure";
@@ -73,298 +58,144 @@
 static const char kDmabufFaceauthModelHeapName[] = "famodel-secure";
 static const char kDmabufVframeSecureHeapName[] = "vframe-secure";
 static const char kDmabufVstreamSecureHeapName[] = "vstream-secure";
+static const char kDmabufVscalerSecureHeapName[] = "vscaler-secure";
+static const char kDmabufFramebufferSecureHeapName[] = "framebuffer-secure";
 
-struct ion_device
-{
-	int client()
-	{
-		return ion_client;
-	}
-
-	static void close()
-	{
-		ion_device &dev = get_inst();
-		if (dev.ion_client >= 0)
-		{
-			exynos_ion_close(dev.ion_client);
-			dev.ion_client = -1;
-		}
-
-		dev.buffer_allocator.reset();
-	}
-
-	static ion_device *get()
-	{
-		ion_device &dev = get_inst();
-		if (!dev.buffer_allocator)
-		{
-			dev.buffer_allocator = std::make_unique<BufferAllocator>();
-			if (!dev.buffer_allocator)
-				ALOGE("Unable to create BufferAllocator object");
-		}
-
-		if (dev.ion_client < 0)
-		{
-			if (dev.open_and_query_ion() != 0)
-			{
-				close();
-			}
-		}
-
-		if (dev.ion_client < 0)
-		{
-			return nullptr;
-		}
-		return &dev;
-	}
-
-	/*
-	 *  Identifies a heap and retrieves file descriptor from ION for allocation
-	 *
-	 * @param usage     [in]    Producer and consumer combined usage.
-	 * @param size      [in]    Requested buffer size (in bytes).
-	 * @param heap_type [in]    Requested heap type.
-	 * @param flags     [in]    ION allocation attributes defined by ION_FLAG_*.
-	 * @param min_pgsz  [out]   Minimum page size (in bytes).
-	 * @buffer_name     [in]    Optional name specifying what the buffer is for.
-	 *
-	 * @return File handle which can be used for allocation, on success
-	 *         -1, otherwise.
-	 */
-	int alloc_from_ion_heap(uint64_t usage, size_t size, unsigned int flags, int *min_pgsz,
-				const std::string& buffer_name = std::string());
-
-	/*
-	 *  Signals the start or end of a region where the CPU is accessing a
-	 *  buffer, allowing appropriate cache synchronization.
-	 *
-	 * @param fd        [in]    fd for the buffer
-	 * @param read      [in]    True if the CPU is reading from the buffer
-	 * @param write     [in]    True if the CPU is writing to the buffer
-	 * @param start     [in]    True if the CPU has not yet performed the
-	 *                          operations; false if the operations are
-	 *                          completed.
-	 *
-	 * @return 0 on success; an error code otherwise.
-	 */
-	int sync(int fd, bool read, bool write, bool start);
-
-private:
-	int ion_client;
-	std::unique_ptr<BufferAllocator> buffer_allocator;
-
-	ion_device()
-	    : ion_client(-1)
-	{
-	}
-
-	static ion_device& get_inst()
-	{
-		static ion_device dev;
-		return dev;
-	}
-
-	/*
-	 * Opens the ION module. Queries heap information and stores it for later use
-	 *
-	 * @return              0 in case of success
-	 *                      -1 for all error cases
-	 */
-	int open_and_query_ion();
-
-	/*
-	 *  Allocates in the DMA-BUF heap with name @heap_name. If allocation fails from
-	 *  the DMA-BUF heap or if it does not exist, falls back to an ION heap of the
-	 *  same name.
-	 *
-	 * @param heap_name [in]    DMA-BUF heap name for allocation
-	 * @param size      [in]    Requested buffer size (in bytes).
-	 * @param flags     [in]    ION allocation attributes defined by ION_FLAG_* to
-	 *                          be used for ION allocations. Will not be used with
-	 *                          DMA-BUF heaps since the framework does not support
-	 *                          allocation flags.
-	 * @buffer_name     [in]    Name specifying what the buffer is for.
-	 *
-	 * @return fd of the allocated buffer on success, -1 otherwise;
-	 */
-
-	int alloc_from_dmabuf_heap(const std::string& heap_name, size_t size, unsigned int flags,
-				   const std::string& buffer_name);
-};
-
-static void set_ion_flags(uint64_t usage, unsigned int *ion_flags)
-{
-	if (ion_flags == nullptr)
-		return;
-
-	if ((usage & GRALLOC_USAGE_SW_READ_MASK) == GRALLOC_USAGE_SW_READ_OFTEN)
-	{
-		*ion_flags |= ION_FLAG_CACHED;
-	}
-
-	// DRM or Secure Camera
-	if (usage & (GRALLOC_USAGE_PROTECTED))
-	{
-		*ion_flags |= ION_FLAG_PROTECTED;
-	}
-
-	/* TODO: used for exynos3830. Add this as an option to Android.bp */
-#if defined(GRALLOC_SCALER_WFD) && GRALLOC_SCALER_WFD == 1
-	if (usage & GRALLOC_USAGE_PRIVATE_NONSECURE && usage & GRALLOC_USAGE_HW_COMPOSER)
-	{
-		*ion_flags |= ION_FLAG_PROTECTED;
-	}
-#endif
-	/* Sensor direct channels require uncached allocations. */
-	if (usage & GRALLOC_USAGE_SENSOR_DIRECT_DATA)
-	{
-		*ion_flags &= ~ION_FLAG_CACHED;
-	}
+BufferAllocator& get_allocator() {
+		static BufferAllocator allocator;
+		return allocator;
 }
 
-static unsigned int select_faceauth_heap_mask(uint64_t usage)
+std::string find_first_available_heap(const std::initializer_list<std::string>&& options) {
+	static auto available_heaps = BufferAllocator::GetDmabufHeapList();
+
+	for (const auto& heap: options)
+		if (available_heaps.find(heap) != available_heaps.end())
+			return heap;
+
+	return "";
+}
+
+std::string select_dmabuf_heap(uint64_t usage)
 {
 	struct HeapSpecifier
 	{
-		uint64_t      usage_bits; // exact match required
-		unsigned int  mask;
+		uint64_t      usage_bits;
+		std::string   name;
 	};
 
-	static constexpr std::array<HeapSpecifier, 5> faceauth_heaps =
+	static const std::array<HeapSpecifier, 6> exact_usage_heaps =
 	{{
+		// Faceauth heaps
 		{ // isp_image_heap
 			GRALLOC_USAGE_PROTECTED | GRALLOC_USAGE_HW_CAMERA_WRITE | GS101_GRALLOC_USAGE_TPU_INPUT,
-			EXYNOS_ION_HEAP_FA_IMG_MASK
+			kDmabufFaceauthImgHeapName
 		},
 		{ // isp_internal_heap
 			GRALLOC_USAGE_PROTECTED | GRALLOC_USAGE_HW_CAMERA_WRITE | GRALLOC_USAGE_HW_CAMERA_READ,
-			EXYNOS_ION_HEAP_FA_RAWIMG_MASK
+			kDmabufFaceauthRawImgHeapName
 		},
 		{ // isp_preview_heap
 			GRALLOC_USAGE_PROTECTED | GRALLOC_USAGE_HW_CAMERA_WRITE | GRALLOC_USAGE_HW_COMPOSER |
             GRALLOC_USAGE_HW_TEXTURE,
-			EXYNOS_ION_HEAP_FA_PREV_MASK
+			kDmabufFaceauthPrevHeapName
 		},
 		{ // ml_model_heap
 			GRALLOC_USAGE_PROTECTED | GS101_GRALLOC_USAGE_TPU_INPUT,
-			EXYNOS_ION_HEAP_FA_MODEL_MASK
+			kDmabufFaceauthModelHeapName
 		},
 		{ // tpu_heap
 			GRALLOC_USAGE_PROTECTED | GS101_GRALLOC_USAGE_TPU_OUTPUT | GS101_GRALLOC_USAGE_TPU_INPUT,
-			EXYNOS_ION_HEAP_FA_TPU_MASK
+			kDmabufFaceauthTpuHeapName
+		},
+
+		{
+			GRALLOC_USAGE_PROTECTED | GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_HW_RENDER |
+			GRALLOC_USAGE_HW_COMPOSER | GRALLOC_USAGE_HW_FB,
+			find_first_available_heap({kDmabufFramebufferSecureHeapName, kDmabufVframeSecureHeapName})
+		},
+	}};
+
+	static const std::array<HeapSpecifier, 6> inexact_usage_heaps =
+	{{
+		// If GPU, use vframe-secure
+		{
+			GRALLOC_USAGE_PROTECTED | GRALLOC_USAGE_HW_TEXTURE,
+			kDmabufVframeSecureHeapName
+		},
+		{
+			GRALLOC_USAGE_PROTECTED | GRALLOC_USAGE_HW_RENDER,
+			kDmabufVframeSecureHeapName
+		},
+
+		// If HWC but not GPU
+		{
+			GRALLOC_USAGE_PROTECTED | GRALLOC_USAGE_HW_COMPOSER,
+			kDmabufVscalerSecureHeapName
+		},
+
+		// Catchall for protected
+		{
+			GRALLOC_USAGE_PROTECTED,
+			kDmabufVframeSecureHeapName
+		},
+
+		// Sensor heap
+		{
+			GRALLOC_USAGE_SENSOR_DIRECT_DATA,
+			kDmabufSensorDirectHeapName
+		},
+
+		// Catchall to system
+		{
+			0,
+			kDmabufSystemUncachedHeapName
 		}
 	}};
 
-	for (const HeapSpecifier &heap : faceauth_heaps)
+	for (const HeapSpecifier &heap : exact_usage_heaps)
 	{
 		if (usage == heap.usage_bits)
 		{
-			ALOGV("Using FaceAuth heap mask 0x%x for usage 0x%" PRIx64 "\n",
-			      heap.mask, usage);
-			return heap.mask;
+			return heap.name;
 		}
 	}
 
-	return 0;
+	for (const HeapSpecifier &heap : inexact_usage_heaps)
+	{
+		if ((usage & heap.usage_bits) == heap.usage_bits)
+		{
+			if (heap.name == kDmabufSystemUncachedHeapName &&
+			    ((usage & GRALLOC_USAGE_SW_READ_MASK) == GRALLOC_USAGE_SW_READ_OFTEN))
+				return kDmabufSystemHeapName;
+
+			return heap.name;
+		}
+	}
+
+	return "";
 }
 
-static unsigned int select_heap_mask(uint64_t usage)
+int alloc_from_dmabuf_heap(uint64_t usage, size_t size, const std::string& buffer_name = "")
 {
-	if (unsigned int faceauth_heap_mask = select_faceauth_heap_mask(usage);
-	    faceauth_heap_mask != 0)
-	{
-		return faceauth_heap_mask;
+	ATRACE_CALL();
+	if (size == 0) { return -1; }
+
+	auto heap_name = select_dmabuf_heap(usage);
+	if (heap_name.empty()) {
+			MALI_GRALLOC_LOGW("No heap found for usage: %s (0x%" PRIx64 ")", describe_usage(usage).c_str(), usage);
+			return -EINVAL;
 	}
 
-	unsigned int heap_mask;
-
-	if (usage & GRALLOC_USAGE_PROTECTED)
-	{
-		if (usage & GRALLOC_USAGE_PRIVATE_NONSECURE)
-		{
-			heap_mask = EXYNOS_ION_HEAP_SYSTEM_MASK;
-		}
-		else if ((usage & GRALLOC_USAGE_HW_COMPOSER) &&
-			!(usage & GRALLOC_USAGE_HW_TEXTURE) &&
-			!(usage & GRALLOC_USAGE_HW_RENDER))
-		{
-			heap_mask = EXYNOS_ION_HEAP_VIDEO_SCALER_MASK;
-		}
-		else
-		{
-			heap_mask = EXYNOS_ION_HEAP_VIDEO_FRAME_MASK;
-		}
-	}
-	/* TODO: used for exynos3830. Add this as a an option to Android.bp */
-#if defined(GRALLOC_SCALER_WFD) && GRALLOC_SCALER_WFD == 1
-	else if (usage & GRALLOC_USAGE_PRIVATE_NONSECURE && usage & GRALLOC_USAGE_HW_COMPOSER)
-	{
-		heap_mask = EXYNOS_ION_HEAP_EXT_UI_MASK;
-	}
-#endif
-	else if (usage & GRALLOC_USAGE_SENSOR_DIRECT_DATA)
-	{
-		heap_mask = EXYNOS_ION_HEAP_SENSOR_DIRECT_MASK;
-	}
-	else
-	{
-		heap_mask = EXYNOS_ION_HEAP_SYSTEM_MASK;
-	}
-
-	return heap_mask;
-}
-
-/*
- * Selects a DMA-BUF heap name.
- *
- * @param heap_mask     [in]    heap_mask for which the equivalent DMA-BUF heap
- *                              name must be found.
- *
- * @return the name of the DMA-BUF heap equivalent to the ION heap of mask
- *         @heap_mask.
- *
- */
-static std::string select_dmabuf_heap(unsigned int heap_mask)
-{
-	switch (heap_mask) {
-		case EXYNOS_ION_HEAP_SENSOR_DIRECT_MASK:
-			return kDmabufSensorDirectHeapName;
-		case EXYNOS_ION_HEAP_FA_TPU_MASK:
-			return kDmabufFaceauthTpuHeapName;
-		case EXYNOS_ION_HEAP_FA_IMG_MASK:
-			return kDmabufFaceauthImgHeapName;
-		case EXYNOS_ION_HEAP_FA_RAWIMG_MASK:
-			return kDmabufFaceauthRawImgHeapName;
-		case EXYNOS_ION_HEAP_FA_PREV_MASK:
-			return kDmabufFaceauthPrevHeapName;
-		case EXYNOS_ION_HEAP_FA_MODEL_MASK:
-			return kDmabufFaceauthModelHeapName;
-		case EXYNOS_ION_HEAP_VIDEO_FRAME_MASK:
-			return kDmabufVframeSecureHeapName;
-		case EXYNOS_ION_HEAP_VIDEO_STREAM_MASK:
-			return kDmabufVstreamSecureHeapName;
-		default:
-			return {};
-	}
-}
-
-int ion_device::alloc_from_dmabuf_heap(const std::string& heap_name, size_t size,
-				       unsigned int flags, const std::string& buffer_name)
-{
 	ATRACE_NAME(("alloc_from_dmabuf_heap " +  heap_name).c_str());
-	if (!buffer_allocator)
-	{
-		return -1;
-	}
-
-	int shared_fd = buffer_allocator->Alloc(heap_name, size, flags);
+	int shared_fd = get_allocator().Alloc(heap_name, size, 0);
 	if (shared_fd < 0)
 	{
 		ALOGE("Allocation failed for heap %s error: %d\n", heap_name.c_str(), shared_fd);
 	}
 
 	if (!buffer_name.empty()) {
-		if (buffer_allocator->DmabufSetName(shared_fd, buffer_name)) {
+		if (get_allocator().DmabufSetName(shared_fd, buffer_name)) {
 			ALOGW("Unable to set buffer name %s: %s", buffer_name.c_str(), strerror(errno));
 		}
 	}
@@ -372,58 +203,7 @@
 	return shared_fd;
 }
 
-int ion_device::alloc_from_ion_heap(uint64_t usage, size_t size, unsigned int flags, int *min_pgsz,
-				    const std::string& buffer_name)
-{
-	ATRACE_CALL();
-	/* TODO: remove min_pgsz? I don't think this is useful on Exynos */
-	if (size == 0 || min_pgsz == NULL)
-	{
-		return -1;
-	}
-
-	unsigned int heap_mask = select_heap_mask(usage);
-
-	int shared_fd;
-	auto dmabuf_heap_name = select_dmabuf_heap(heap_mask);
-	if (!dmabuf_heap_name.empty())
-	{
-		shared_fd = alloc_from_dmabuf_heap(dmabuf_heap_name, size, flags, buffer_name);
-	}
-	else
-	{
-		if (ion_client < 0)
-		{
-			return -1;
-		}
-
-		shared_fd = exynos_ion_alloc(ion_client, size, heap_mask, flags);
-	}
-
-	*min_pgsz = SZ_4K;
-
-	return shared_fd;
-}
-
-int ion_device::open_and_query_ion()
-{
-	if (ion_client >= 0)
-	{
-		MALI_GRALLOC_LOGW("ION device already open");
-		return 0;
-	}
-
-	ion_client = exynos_ion_open();
-	if (ion_client < 0)
-	{
-		MALI_GRALLOC_LOGE("ion_open failed with %s", strerror(errno));
-		return -1;
-	}
-
-	return 0;
-}
-
-static SyncType sync_type_for_flags(const bool read, const bool write)
+SyncType sync_type_for_flags(const bool read, const bool write)
 {
 	if (read && !write)
 	{
@@ -440,24 +220,19 @@
 	}
 }
 
-int ion_device::sync(const int fd, const bool read, const bool write, const bool start)
+int sync(const int fd, const bool read, const bool write, const bool start)
 {
-	if (!buffer_allocator)
-	{
-		return -1;
-	}
-
 	if (start)
 	{
-		return buffer_allocator->CpuSyncStart(fd, sync_type_for_flags(read, write));
+		return get_allocator().CpuSyncStart(fd, sync_type_for_flags(read, write));
 	}
 	else
 	{
-		return buffer_allocator->CpuSyncEnd(fd, sync_type_for_flags(read, write));
+		return get_allocator().CpuSyncEnd(fd, sync_type_for_flags(read, write));
 	}
 }
 
-static int mali_gralloc_ion_sync(const private_handle_t * const hnd,
+int mali_gralloc_ion_sync(const private_handle_t * const hnd,
                                        const bool read,
                                        const bool write,
                                        const bool start)
@@ -467,16 +242,10 @@
 		return -EINVAL;
 	}
 
-	ion_device *dev = ion_device::get();
-	if (!dev)
-	{
-		return -1;
-	}
-
 	for (int i = 0; i < hnd->fd_count; i++)
 	{
 		const int fd = hnd->fds[i];
-		if (const int ret = dev->sync(fd, read, write, start))
+		if (const int ret = sync(fd, read, write, start))
 		{
 			return ret;
 		}
@@ -486,16 +255,6 @@
 }
 
 
-/*
- * Signal start of CPU access to the DMABUF exported from ION.
- *
- * @param hnd   [in]    Buffer handle
- * @param read  [in]    Flag indicating CPU read access to memory
- * @param write [in]    Flag indicating CPU write access to memory
- *
- * @return              0 in case of success
- *                      errno for all error cases
- */
 int mali_gralloc_ion_sync_start(const private_handle_t * const hnd,
                                 const bool read,
                                 const bool write)
@@ -504,16 +263,6 @@
 }
 
 
-/*
- * Signal end of CPU access to the DMABUF exported from ION.
- *
- * @param hnd   [in]    Buffer handle
- * @param read  [in]    Flag indicating CPU read access to memory
- * @param write [in]    Flag indicating CPU write access to memory
- *
- * @return              0 in case of success
- *                      errno for all error cases
- */
 int mali_gralloc_ion_sync_end(const private_handle_t * const hnd,
                               const bool read,
                               const bool write)
@@ -544,7 +293,7 @@
 	delete hnd;
 }
 
-static void mali_gralloc_ion_free_internal(buffer_handle_t * const pHandle,
+void mali_gralloc_ion_free_internal(buffer_handle_t * const pHandle,
                                            const uint32_t num_hnds)
 {
 	for (uint32_t i = 0; i < num_hnds; i++)
@@ -560,23 +309,14 @@
 int mali_gralloc_ion_allocate_attr(private_handle_t *hnd)
 {
 	ATRACE_CALL();
-	ion_device *dev = ion_device::get();
-	if (!dev)
-	{
-		return -1;
-	}
 
 	int idx = hnd->get_share_attr_fd_index();
-	int ion_flags = 0;
-	int min_pgsz;
 	uint64_t usage = GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN;
 
-	ion_flags = ION_FLAG_CACHED;
-
-	hnd->fds[idx] = dev->alloc_from_ion_heap(usage, hnd->attr_size, ion_flags, &min_pgsz);
+	hnd->fds[idx] = alloc_from_dmabuf_heap(usage, hnd->attr_size);
 	if (hnd->fds[idx] < 0)
 	{
-		MALI_GRALLOC_LOGE("ion_alloc failed from client ( %d )", dev->client());
+		MALI_GRALLOC_LOGE("ion_alloc failed");
 		return -1;
 	}
 
@@ -605,36 +345,24 @@
 	unsigned int priv_heap_flag = 0;
 	uint64_t usage;
 	uint32_t i;
-	unsigned int ion_flags = 0;
-	int min_pgsz = 0;
 	int fds[MAX_FDS];
 	std::fill(fds, fds + MAX_FDS, -1);
 
-	ion_device *dev = ion_device::get();
-	if (!dev)
-	{
-		return -1;
-	}
-
 	for (i = 0; i < numDescriptors; i++)
 	{
 		buffer_descriptor_t *bufDescriptor = (buffer_descriptor_t *)(descriptors[i]);
 		usage = bufDescriptor->consumer_usage | bufDescriptor->producer_usage;
 
-		ion_flags = 0;
-		set_ion_flags(usage, &ion_flags);
-
 		for (int fidx = 0; fidx < bufDescriptor->fd_count; fidx++)
 		{
 			if (ion_fd >= 0 && fidx == 0) {
 				fds[fidx] = ion_fd;
 			} else {
-				fds[fidx] = dev->alloc_from_ion_heap(usage, bufDescriptor->alloc_sizes[fidx], ion_flags,
-								     &min_pgsz, bufDescriptor->name);
+				fds[fidx] = alloc_from_dmabuf_heap(usage, bufDescriptor->alloc_sizes[fidx], bufDescriptor->name);
 			}
 			if (fds[fidx] < 0)
 			{
-				MALI_GRALLOC_LOGE("ion_alloc failed from client ( %d )", dev->client());
+				MALI_GRALLOC_LOGE("ion_alloc failed");
 
 				for (int cidx = 0; cidx < fidx; cidx++)
 				{
@@ -692,7 +420,7 @@
 
 			if (MAP_FAILED == cpu_ptr)
 			{
-				MALI_GRALLOC_LOGE("mmap failed from client ( %d ), fd ( %d )", dev->client(), hnd->fds[0]);
+				MALI_GRALLOC_LOGE("mmap failed for fd ( %d )", hnd->fds[0]);
 				mali_gralloc_ion_free_internal(pHandle, numDescriptors);
 				return -1;
 			}
@@ -721,7 +449,6 @@
 	return 0;
 }
 
-
 int mali_gralloc_ion_map(private_handle_t *hnd)
 {
 	uint64_t usage = hnd->producer_usage | hnd->consumer_usage;
@@ -760,59 +487,6 @@
 	return 0;
 }
 
-int import_exynos_ion_handles(private_handle_t *hnd)
-{
-	int retval = -1;
-
-	ion_device *dev = ion_device::get();
-
-	for (int idx = 0; idx < hnd->fd_count; idx++)
-	{
-		if (hnd->fds[idx] >= 0)
-		{
-			retval = exynos_ion_import_handle(dev->client(), hnd->fds[idx], &hnd->ion_handles[idx]);
-			if (retval)
-			{
-				MALI_GRALLOC_LOGE("error importing ion_handle. ion_client(%d), ion_handle[%d](%d) format(%s %#" PRIx64 ")",
-				     dev->client(), idx, hnd->ion_handles[idx], format_name(hnd->alloc_format), hnd->alloc_format);
-				goto error;
-			}
-		}
-	}
-
-	return retval;
-
-error:
-	for (int idx = 0; idx < hnd->fd_count; idx++)
-	{
-		if (hnd->ion_handles[idx])
-		{
-			exynos_ion_free_handle(dev->client(), hnd->ion_handles[idx]);
-		}
-	}
-
-	return retval;
-}
-
-void free_exynos_ion_handles(private_handle_t *hnd)
-{
-	ion_device *dev = ion_device::get();
-
-	for (int idx = 0; idx < hnd->fd_count; idx++)
-	{
-		if (hnd->ion_handles[idx])
-		{
-			if (hnd->ion_handles[idx] &&
-			    exynos_ion_free_handle(dev->client(), hnd->ion_handles[idx]))
-			{
-				MALI_GRALLOC_LOGE("error freeing ion_handle. ion_client(%d), ion_handle[%d](%d) format(%s %#" PRIx64 ")",
-					dev->client(), idx, hnd->ion_handles[idx], format_name(hnd->alloc_format), hnd->alloc_format);
-			}
-		}
-	}
-}
-
-
 void mali_gralloc_ion_unmap(private_handle_t *hnd)
 {
 	for (int i = 0; i < hnd->fd_count; i++)
@@ -838,9 +512,3 @@
 	hnd->cpu_read = 0;
 	hnd->cpu_write = 0;
 }
-
-void mali_gralloc_ion_close(void)
-{
-	ion_device::close();
-}
-
diff --git a/gralloc4/src/allocator/mali_gralloc_ion.h b/gralloc4/src/allocator/mali_gralloc_ion.h
index 3877c5e..5f55c2f 100644
--- a/gralloc4/src/allocator/mali_gralloc_ion.h
+++ b/gralloc4/src/allocator/mali_gralloc_ion.h
@@ -32,9 +32,6 @@
                               const bool read, const bool write);
 int mali_gralloc_ion_map(private_handle_t *hnd);
 void mali_gralloc_ion_unmap(private_handle_t *hnd);
-void mali_gralloc_ion_close(void);
 int mali_gralloc_attr_allocate(void);
-int import_exynos_ion_handles(private_handle_t *hnd);
-void free_exynos_ion_handles(private_handle_t *hnd);
 
 #endif /* MALI_GRALLOC_ION_H_ */
diff --git a/gralloc4/src/capabilities/src/gralloc_capabilities.cpp b/gralloc4/src/capabilities/src/gralloc_capabilities.cpp
index bb10941..161b5c0 100644
--- a/gralloc4/src/capabilities/src/gralloc_capabilities.cpp
+++ b/gralloc4/src/capabilities/src/gralloc_capabilities.cpp
@@ -69,8 +69,8 @@
 	dpu_runtime_caps.caps_mask |= MALI_GRALLOC_FORMAT_CAPABILITY_PIXFMT_RGBA1010102;
 #endif
 
-#if defined(MALI_GPU_SUPPORT_AFBC_BASIC) && (MALI_GPU_SUPPORT_AFBC_BASIC == 1)
 	gpu_runtime_caps.caps_mask |= MALI_GRALLOC_FORMAT_CAPABILITY_OPTIONS_PRESENT;
+#if defined(MALI_GPU_SUPPORT_AFBC_BASIC) && (MALI_GPU_SUPPORT_AFBC_BASIC == 1)
 	gpu_runtime_caps.caps_mask |= MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_BASIC;
 	gpu_runtime_caps.caps_mask |= MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_YUV_READ;
 	gpu_runtime_caps.caps_mask |= MALI_GRALLOC_FORMAT_CAPABILITY_PIXFMT_RGBA1010102;
@@ -116,16 +116,21 @@
 	vpu_runtime_caps.caps_mask |= MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_BASIC;
 	vpu_runtime_caps.caps_mask |= MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_YUV_WRITE;
 
+	/* Determine CAM IP capabilities */
+	cam_runtime_caps.caps_mask |= MALI_GRALLOC_FORMAT_CAPABILITY_OPTIONS_PRESENT;
+
 /* Build specific capability changes */
 #if defined(GRALLOC_ARM_NO_EXTERNAL_AFBC) && (GRALLOC_ARM_NO_EXTERNAL_AFBC == 1)
+	cpu_runtime_caps.caps_mask &= ~MALI_GRALLOC_FORMAT_CAPABILITY_AFBCENABLE_MASK;
 	dpu_runtime_caps.caps_mask &= ~MALI_GRALLOC_FORMAT_CAPABILITY_AFBCENABLE_MASK;
-	gpu_runtime_caps.caps_mask &= ~MALI_GRALLOC_FORMAT_CAPABILITY_AFBCENABLE_MASK;
 	vpu_runtime_caps.caps_mask &= ~MALI_GRALLOC_FORMAT_CAPABILITY_AFBCENABLE_MASK;
+	gpu_runtime_caps.caps_mask &= ~MALI_GRALLOC_FORMAT_CAPABILITY_AFBCENABLE_MASK;
 	cam_runtime_caps.caps_mask &= ~MALI_GRALLOC_FORMAT_CAPABILITY_AFBCENABLE_MASK;
+	bo_runtime_caps.caps_mask &= ~MALI_GRALLOC_FORMAT_CAPABILITY_AFBCENABLE_MASK;
+	bw_runtime_caps.caps_mask &= ~MALI_GRALLOC_FORMAT_CAPABILITY_AFBCENABLE_MASK;
+	mfc_runtime_caps.caps_mask &= ~MALI_GRALLOC_FORMAT_CAPABILITY_AFBCENABLE_MASK;
 #endif
 
-	cam_runtime_caps.caps_mask |= MALI_GRALLOC_FORMAT_CAPABILITY_OPTIONS_PRESENT;
-
 	runtime_caps_read = true;
 
 already_init:
diff --git a/gralloc4/src/core/exynos_format_allocation.h b/gralloc4/src/core/exynos_format_allocation.h
index 0abfbd0..7c07b96 100644
--- a/gralloc4/src/core/exynos_format_allocation.h
+++ b/gralloc4/src/core/exynos_format_allocation.h
@@ -16,12 +16,7 @@
 
 #pragma once
 
-#if __has_include(<linux/videodev2_exynos_media.h>)
 #include <linux/videodev2_exynos_media.h>
-#else
-#include "mfc_macros_local.h"
-#endif
-
 #include <gralloc_priv.h>
 
 #define PLANE_SIZE(w, h)      ((w) * (h))
diff --git a/gralloc4/src/core/format_info.cpp b/gralloc4/src/core/format_info.cpp
index b993f16..14a1d84 100644
--- a/gralloc4/src/core/format_info.cpp
+++ b/gralloc4/src/core/format_info.cpp
@@ -112,8 +112,8 @@
 	{ ID(HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_10B_SBWC_L80),  .npln = 2, .ncmp = { 1, 2, 0 }, .bps = 10, .bpp_afbc = { 0,  0,  0 }, .bpp = { 16, 32, 0 }, .hsub = 2, .vsub = 2, .align_w = 2,  .align_h = 2,  ALIGN_W_CPU_DEFAULT, .tile_size = 1,  .has_alpha = false, .is_rgb = false, .is_yuv = true,  .afbc = false, .linear = true,  .yuv_transform = false, .flex = true,  .planes_contiguous = false },
 
 	/* Google Formats */
-	{ ID(HAL_PIXEL_FORMAT_GOOGLE_NV12_SP),                     .npln = 2, .ncmp = { 1, 2, 0 }, .bps = 8,  .bpp_afbc = { 0,  0,  0 }, .bpp = { 8,  16, 0 }, .hsub = 2, .vsub = 2, .align_w = 64, .align_h = 8,  .align_w_cpu = 64,   .tile_size = 1,  .has_alpha = false, .is_rgb = false, .is_yuv = true,  .afbc = false, .linear = true,  .yuv_transform = false, .flex = true,  .planes_contiguous = true }, 
-	{ ID(HAL_PIXEL_FORMAT_GOOGLE_NV12_SP_10B),                 .npln = 2, .ncmp = { 1, 2, 0 }, .bps = 10, .bpp_afbc = { 0,  0,  0 }, .bpp = { 16, 32, 0 }, .hsub = 2, .vsub = 2, .align_w = 64, .align_h = 8,  .align_w_cpu = 64,   .tile_size = 1,  .has_alpha = false, .is_rgb = false, .is_yuv = true,  .afbc = false, .linear = true,  .yuv_transform = false, .flex = true,  .planes_contiguous = true }, 
+	{ ID(HAL_PIXEL_FORMAT_GOOGLE_NV12_SP),                     .npln = 2, .ncmp = { 1, 2, 0 }, .bps = 8,  .bpp_afbc = { 0,  0,  0 }, .bpp = { 8,  16, 0 }, .hsub = 2, .vsub = 2, .align_w = 64, .align_h = 16,  .align_w_cpu = 64,   .tile_size = 1,  .has_alpha = false, .is_rgb = false, .is_yuv = true,  .afbc = false, .linear = true,  .yuv_transform = false, .flex = true,  .planes_contiguous = true },
+	{ ID(HAL_PIXEL_FORMAT_GOOGLE_NV12_SP_10B),                 .npln = 2, .ncmp = { 1, 2, 0 }, .bps = 10, .bpp_afbc = { 0,  0,  0 }, .bpp = { 16, 32, 0 }, .hsub = 2, .vsub = 2, .align_w = 64, .align_h = 16,  .align_w_cpu = 64,   .tile_size = 1,  .has_alpha = false, .is_rgb = false, .is_yuv = true,  .afbc = false, .linear = true,  .yuv_transform = false, .flex = true,  .planes_contiguous = true },
 	{ ID(HAL_PIXEL_FORMAT_GOOGLE_R_8),                         .npln = 1, .ncmp = { 1, 0, 0 }, .bps = 8,  .bpp_afbc = { 8,  0,  0 }, .bpp = { 8,  0,  0 }, .hsub = 0, .vsub = 0, .align_w = 16, .align_h = 16, .align_w_cpu = 16,   .tile_size = 1,  .has_alpha = false, .is_rgb = true,  .is_yuv = false, .afbc = true,  .linear = true,  .yuv_transform = false, .flex = true,  .planes_contiguous = false },
 	{ ID(HAL_PIXEL_FORMAT_GOOGLE_RG_88),                       .npln = 1, .ncmp = { 2, 0, 0 }, .bps = 8,  .bpp_afbc = { 16, 0,  0 }, .bpp = { 16, 0,  0 }, .hsub = 0, .vsub = 0, .align_w = 16, .align_h = 16, .align_w_cpu = 16,   .tile_size = 1,  .has_alpha = false, .is_rgb = true,  .is_yuv = false, .afbc = true,  .linear = true,  .yuv_transform = false, .flex = true,  .planes_contiguous = false },
 	/* END ALIGNED SECTION */
@@ -128,7 +128,7 @@
 	/* BEGIN ALIGNED SECTION */
 	/* TODO(b/189467474) AFBC disabled on the GPU for RGB_565 due to color swap in Vulkan */
 	{ .id = MALI_GRALLOC_FORMAT_INTERNAL_RGB_565,             .cpu_rd = F_LIN,  .cpu_wr = F_LIN,  .gpu_rd = F_LIN,        .gpu_wr = F_LIN,        .dpu_rd = F_LIN|F_AFBC, .dpu_wr = F_NONE, .dpu_aeu_wr = F_AFBC, .vpu_rd = F_NONE, .vpu_wr = F_NONE, .cam_wr = F_NONE,  },
-	{ .id = MALI_GRALLOC_FORMAT_INTERNAL_RGB_888,             .cpu_rd = F_LIN,  .cpu_wr = F_LIN,  .gpu_rd = F_LIN|F_AFBC, .gpu_wr = F_LIN|F_AFBC, .dpu_rd = F_LIN|F_AFBC, .dpu_wr = F_LIN,  .dpu_aeu_wr = F_AFBC, .vpu_rd = F_NONE, .vpu_wr = F_NONE, .cam_wr = F_NONE,  },
+	{ .id = MALI_GRALLOC_FORMAT_INTERNAL_RGB_888,             .cpu_rd = F_LIN,  .cpu_wr = F_LIN,  .gpu_rd = F_LIN|F_AFBC, .gpu_wr = F_LIN|F_AFBC, .dpu_rd = F_LIN|F_AFBC, .dpu_wr = F_LIN,  .dpu_aeu_wr = F_AFBC, .vpu_rd = F_NONE, .vpu_wr = F_NONE, .cam_wr = F_LIN,   },
 	{ .id = MALI_GRALLOC_FORMAT_INTERNAL_RGBA_8888,           .cpu_rd = F_LIN,  .cpu_wr = F_LIN,  .gpu_rd = F_LIN|F_AFBC, .gpu_wr = F_LIN|F_AFBC, .dpu_rd = F_LIN|F_AFBC, .dpu_wr = F_LIN,  .dpu_aeu_wr = F_AFBC, .vpu_rd = F_LIN,  .vpu_wr = F_NONE, .cam_wr = F_LIN,   },
 	{ .id = MALI_GRALLOC_FORMAT_INTERNAL_BGRA_8888,           .cpu_rd = F_LIN,  .cpu_wr = F_LIN,  .gpu_rd = F_LIN,        .gpu_wr = F_LIN,        .dpu_rd = F_LIN,        .dpu_wr = F_LIN,  .dpu_aeu_wr = F_NONE, .vpu_rd = F_LIN,  .vpu_wr = F_NONE, .cam_wr = F_NONE,  },
 	{ .id = MALI_GRALLOC_FORMAT_INTERNAL_RGBX_8888,           .cpu_rd = F_LIN,  .cpu_wr = F_LIN,  .gpu_rd = F_LIN|F_AFBC, .gpu_wr = F_LIN|F_AFBC, .dpu_rd = F_LIN|F_AFBC, .dpu_wr = F_LIN,  .dpu_aeu_wr = F_NONE, .vpu_rd = F_NONE, .vpu_wr = F_NONE, .cam_wr = F_NONE,  },
diff --git a/gralloc4/src/core/mali_gralloc_bufferallocation.cpp b/gralloc4/src/core/mali_gralloc_bufferallocation.cpp
index f76bcf9..289db0b 100644
--- a/gralloc4/src/core/mali_gralloc_bufferallocation.cpp
+++ b/gralloc4/src/core/mali_gralloc_bufferallocation.cpp
@@ -22,6 +22,7 @@
 #include <assert.h>
 #include <atomic>
 #include <algorithm>
+#include <set>
 #include <utils/Trace.h>
 
 #include <hardware/hardware.h>
@@ -449,20 +450,14 @@
                                uint32_t stride_align,
                                uint32_t * byte_stride)
 {
-	if (plane == 0)
-	{
-		*byte_stride = GRALLOC_ALIGN(luma_stride, GRALLOC_ALIGN(stride_align, 32));
-	}
-	else
-	{
-		/*
-		 * Derive chroma stride from luma and verify it is:
-		 * 1. Aligned to "1/2*lcm(hw_align, cpu_align)"
-		 * 2. Multiple of 16px (16 bytes)
-		 */
-		*byte_stride = luma_stride / 2;
-		assert(*byte_stride == GRALLOC_ALIGN(*byte_stride, GRALLOC_ALIGN(stride_align / 2, 16)));
-		assert(*byte_stride & 15 == 0);
+	// https://developer.android.com/reference/android/graphics/ImageFormat#YV12
+	if (plane == 0) {
+		// stride_align has to be honored as GPU alignment still requires the format to be
+		// 64 bytes aligned. Though that does not break the contract as long as the
+		// horizontal stride for chroma is half the luma stride and aligned to 16.
+		*byte_stride = GRALLOC_ALIGN(luma_stride, GRALLOC_ALIGN(stride_align, 16));
+	} else {
+		*byte_stride = GRALLOC_ALIGN(luma_stride / 2, 16);
 	}
 }
 #endif
@@ -646,10 +641,10 @@
 			/*
 			 * Update YV12 stride with both CPU & HW usage due to constraint of chroma stride.
 			 * Width is anyway aligned to 16px for luma and chroma (has_cpu_usage).
-                         *
-                         * Note: To prevent luma stride misalignment with GPU stride alignment.
-                         * The luma plane will maintain the same `stride` size, and the chroma plane
-                         * will align to `stride/2`.
+			 *
+			 * Note: To prevent luma stride misalignment with GPU stride alignment.
+			 * The luma plane will maintain the same `stride` size, and the chroma plane
+			 * will align to `stride/2`.
 			 */
 			if (format.id == MALI_GRALLOC_FORMAT_INTERNAL_YV12 && has_hw_usage && has_cpu_usage)
 			{
@@ -792,12 +787,12 @@
 		buffer_descriptor_t *bufDescriptor,
 		format_info_t format_info)
 {
-	int fd_count = 1;
 	int w = bufDescriptor->width;
 	int h = bufDescriptor->height;
 	uint64_t usage = bufDescriptor->producer_usage | bufDescriptor->consumer_usage;
 	int plane_count = 2;
 	int format = MALI_GRALLOC_INTFMT_FMT_MASK & bufDescriptor->alloc_format;
+	int fd_count = get_exynos_fd_count(format);
 
 	if (usage & (GRALLOC_USAGE_HW_VIDEO_ENCODER | GRALLOC_USAGE_HW_VIDEO_DECODER))
 	{
@@ -806,23 +801,6 @@
 		bufDescriptor->consumer_usage |= GRALLOC_USAGE_VIDEO_PRIVATE_DATA;
 	}
 
-	/* set SBWC format fd_count */
-	fd_count = 1;
-	switch (format)
-	{
-		case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_SBWC:
-		case HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M_SBWC:
-		case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_10B_SBWC:
-		case HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M_10B_SBWC:
-		case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_SBWC_L50:
-		case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_SBWC_L75:
-		case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_10B_SBWC_L40:
-		case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_10B_SBWC_L60:
-		case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_10B_SBWC_L80:
-			fd_count = 2;
-			break;
-	}
-
 	/* SWBC Formats have special size requirements */
 	switch (format)
 	{
@@ -864,7 +842,6 @@
 			break;
 
 		case HAL_PIXEL_FORMAT_YCrCb_420_SP:
-			fd_count = 1;
 			h = GRALLOC_ALIGN(h, 2);
 			plane_count = setup_420_sp(w, h, fd_count, bufDescriptor->plane_info);
 			break;
@@ -873,20 +850,17 @@
 		case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_P_M:
 			w = GRALLOC_ALIGN(w, 32);
 			h = GRALLOC_ALIGN(h, 16);
-			fd_count = 3;
 			plane_count = setup_420_p(w, h, fd_count, bufDescriptor->plane_info);
 			break;
 
 		case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_TILED:
 			w = GRALLOC_ALIGN(w, 16);
 			h = GRALLOC_ALIGN(h, 32);
-			fd_count = 2;
 			plane_count = setup_420_sp_tiled(w, h, fd_count, bufDescriptor->plane_info);
 			break;
 
 		case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_P:
 			w = GRALLOC_ALIGN(w, 16);
-			fd_count = 1;
 			plane_count = setup_420_p(w, h, fd_count, bufDescriptor->plane_info);
 			break;
 
@@ -895,14 +869,12 @@
 		case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M:
 			w = GRALLOC_ALIGN(w, 16);
 			h = GRALLOC_ALIGN(h, 32);
-			fd_count = 2;
 			plane_count = setup_420_sp(w, h, fd_count, bufDescriptor->plane_info);
 			break;
 
 		case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN:
 			w = GRALLOC_ALIGN(w, 64);
 			h = GRALLOC_ALIGN(h, 16);
-			fd_count = 1;
 			plane_count = setup_420_sp(w, h, fd_count, bufDescriptor->plane_info);
 			break;
 
@@ -910,28 +882,24 @@
 			/* This is 64 pixel align for now */
 			w = GRALLOC_ALIGN(w, BOARD_EXYNOS_S10B_FORMAT_ALIGN);
 			h = GRALLOC_ALIGN(h, 16);
-			fd_count = 2;
 			plane_count = setup_420_sp_s10b(w, h, fd_count, bufDescriptor->plane_info);
 			break;
 
 		case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_S10B:
 			w = GRALLOC_ALIGN(w, BOARD_EXYNOS_S10B_FORMAT_ALIGN);
 			h = GRALLOC_ALIGN(h, 16);
-			fd_count = 1;
 			plane_count = setup_420_sp_s10b(w, h, fd_count, bufDescriptor->plane_info);
 			break;
 
 		case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_P010_M:
 			w = GRALLOC_ALIGN(w, 16);
 			h = GRALLOC_ALIGN(h, 16);
-			fd_count = 2;
 			plane_count = setup_p010_sp(w, h, fd_count, bufDescriptor->plane_info);
 			break;
 
 		case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_P010_SPN:
 			w = GRALLOC_ALIGN(w, 64);
 			h = GRALLOC_ALIGN(h, 16);
-			fd_count = 1;
 			plane_count = setup_p010_sp(w, h, fd_count, bufDescriptor->plane_info);
 			break;
 
@@ -1002,7 +970,6 @@
 		bufDescriptor->alloc_sizes[fidx] = size;
 	}
 
-
 	bufDescriptor->fd_count = fd_count;
 	bufDescriptor->plane_count = plane_count;
 
@@ -1024,6 +991,22 @@
 	bufDescriptor->alloc_format = mali_gralloc_select_format(bufDescriptor->hal_format,
 	                                                         bufDescriptor->format_type,
 	                                                         usage);
+
+	int base_format = bufDescriptor->alloc_format & MALI_GRALLOC_INTFMT_FMT_MASK;
+
+	// TODO(b/182885532): Delete all multi-fd related dead code from gralloc
+	if (is_exynos_format(base_format) && get_exynos_fd_count(base_format) != 1)
+	{
+		static std::set<uint32_t> seen_formats;
+		if (seen_formats.find(base_format) == seen_formats.end()) {
+			MALI_GRALLOC_LOGW("Multi-fd format (%s 0x%" PRIx64 ") have been deprecated. Requested format: %s 0x%" PRIx64
+					". Consider changing the format to one of the single-fd options.",
+					format_name(base_format), static_cast<uint64_t>(base_format),
+					format_name(bufDescriptor->hal_format), bufDescriptor->hal_format);
+			seen_formats.insert(base_format);
+		}
+	}
+
 	if (bufDescriptor->alloc_format == MALI_GRALLOC_FORMAT_INTERNAL_UNDEFINED)
 	{
 		MALI_GRALLOC_LOGE("ERROR: Unrecognized and/or unsupported format (%s 0x%" PRIx64 ") and usage (%s 0x%" PRIx64 ")",
@@ -1032,7 +1015,7 @@
 		return -EINVAL;
 	}
 
-	int32_t format_idx = get_format_index(bufDescriptor->alloc_format & MALI_GRALLOC_INTFMT_FMT_MASK);
+	int32_t format_idx = get_format_index(base_format);
 	if (format_idx == -1)
 	{
 		return -EINVAL;
@@ -1054,7 +1037,7 @@
 		return -EINVAL;
 	}
 
-	if (is_exynos_format(bufDescriptor->alloc_format))
+	if (is_exynos_format(base_format))
 	{
 		prepare_descriptor_exynos_formats(bufDescriptor, formats[format_idx]);
 	}
@@ -1087,7 +1070,7 @@
 	}
 
 	/* Set pixel stride differently for RAW formats */
-	switch (MALI_GRALLOC_INTFMT_FMT_MASK & bufDescriptor->alloc_format)
+	switch (base_format)
 	{
 		case MALI_GRALLOC_FORMAT_INTERNAL_RAW12:
 		case MALI_GRALLOC_FORMAT_INTERNAL_RAW10:
@@ -1134,7 +1117,6 @@
 	return 0;
 }
 
-
 int mali_gralloc_buffer_allocate(const gralloc_buffer_descriptor_t *descriptors,
                                  uint32_t numDescriptors, buffer_handle_t *pHandle, bool *shared_backend,
                                  int fd)
diff --git a/gralloc4/src/core/mali_gralloc_formats.cpp b/gralloc4/src/core/mali_gralloc_formats.cpp
index 1baaada..5048cac 100644
--- a/gralloc4/src/core/mali_gralloc_formats.cpp
+++ b/gralloc4/src/core/mali_gralloc_formats.cpp
@@ -1382,7 +1382,7 @@
 
 		if ((usage & GRALLOC_USAGE_HW_TEXTURE) || (usage & GRALLOC_USAGE_HW_COMPOSER))
 		{
-			base_format = HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M;    //NV21M narrow
+			base_format = HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN;
 		}
 		else if ((producers & MALI_GRALLOC_PRODUCER_CAM) &&
 			 !(producers & MALI_GRALLOC_PRODUCER_GPU) &&
@@ -1393,9 +1393,9 @@
 			// 2. GPU is not one of the producers
 			// 3. MFC is the sole consumer
 			if (property_get_bool("debug.vendor.gpu.record_sbwc", true)) {
-				base_format = HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_SBWC;
+				base_format = HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_SBWC;
 			} else {
-				base_format = HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M;
+				base_format = HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN;
 			}
 		}
 		else if (get_consumers(usage) & GOOGLE_GRALLOC_CONSUMER_BIG)
@@ -1404,20 +1404,20 @@
 		}
 		else if (usage & GRALLOC_USAGE_HW_VIDEO_ENCODER)
 		{
-			base_format = HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M;    //NV21M narrow
+			base_format = HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN;
 		}
 		else if (usage & GRALLOC_USAGE_VIDEO_PRIVATE_DATA)
 		{
-			base_format = HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M;
+			base_format = HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN;
 		}
 		else if ((usage & GRALLOC_USAGE_HW_CAMERA_READ) && (usage & GRALLOC_USAGE_HW_CAMERA_WRITE))
 		{
-			// Camera IMPLEMENTATION_DEFINED format output maps to NV21M.
-			base_format = HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M;
+			// Camera IMPLEMENTATION_DEFINED format output maps to NV21.
+			base_format = HAL_PIXEL_FORMAT_YCrCb_420_SP;
 		}
 		else
 		{
-			base_format = HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M;    //NV21M narrow
+			base_format = HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN;
 		}
 	}
 	else if (req_format == HAL_PIXEL_FORMAT_YCbCr_420_888)
@@ -1428,21 +1428,23 @@
 		}
 		else if (usage & (GRALLOC_USAGE_HW_VIDEO_ENCODER | GRALLOC_USAGE_HW_VIDEO_DECODER))
 		{
-			base_format = HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M;
+			base_format = HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN;
 		}
-		else if ((usage & GRALLOC_USAGE_HW_TEXTURE) && (usage & GRALLOC_USAGE_HW_CAMERA_WRITE))
+		else if (usage & GRALLOC_USAGE_HW_CAMERA_WRITE)
 		{
-			// Camera flexible YUV format output maps to NV21M.
-			base_format = HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M;
-		}
-		else if (usage & (GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE))
-		{
-			base_format = HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M;
+			// Catchall for camera write. DO NOT CHANGE WITHOUT TESTING THESE SCENARIOS:
+			// 1. Camera capture and initial photo processing
+			// 2. Other major camera operations - video recording, portrait etc
+			// 3. Faceauth
+			// 4. Multi-profile user photo add
+			// 5. Capture and resize - use chat app to capture a photo
+			// Re-run these steps with GPU composition:
+			// adb shell service call SurfaceFlinger 1008 i32 1
+			base_format = HAL_PIXEL_FORMAT_YCrCb_420_SP;
 		}
 		else
 		{
-			// Flexible framework-accessible YUV format; map to NV21 for now
-			base_format = HAL_PIXEL_FORMAT_YCrCb_420_SP;
+			base_format = HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN;
 		}
 	}
 	else if (req_format == HAL_PIXEL_FORMAT_YCBCR_P010)
@@ -1625,3 +1627,30 @@
 	return false;
 }
 
+uint8_t get_exynos_fd_count(uint32_t format) {
+	switch (format)
+	{
+		case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_SBWC:
+		case HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M_SBWC:
+		case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_10B_SBWC:
+		case HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M_10B_SBWC:
+		case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_SBWC_L50:
+		case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_SBWC_L75:
+		case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_10B_SBWC_L40:
+		case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_10B_SBWC_L60:
+		case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_10B_SBWC_L80:
+		case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_TILED:
+		case HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M:
+		case HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M_FULL:
+		case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M:
+		case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_S10B:
+		case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_P010_M:
+			return 2;
+		case HAL_PIXEL_FORMAT_EXYNOS_YV12_M:
+		case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_P_M:
+			return 3;
+	}
+
+	return 1;
+}
+
diff --git a/gralloc4/src/core/mali_gralloc_reference.cpp b/gralloc4/src/core/mali_gralloc_reference.cpp
index 8f12975..b84cbb4 100644
--- a/gralloc4/src/core/mali_gralloc_reference.cpp
+++ b/gralloc4/src/core/mali_gralloc_reference.cpp
@@ -26,10 +26,7 @@
 #include <mutex>
 
 #include "allocator/mali_gralloc_ion.h"
-#include "allocator/mali_gralloc_shared_memory.h"
 #include "mali_gralloc_buffer.h"
-#include "mali_gralloc_bufferallocation.h"
-#include "mali_gralloc_usages.h"
 
 class BufferManager {
 private:
@@ -48,17 +45,6 @@
     std::mutex lock;
     std::map<const private_handle_t *, std::unique_ptr<MappedData>> buffer_map GUARDED_BY(lock);
 
-    static bool should_map_dmabuf(buffer_handle_t handle) {
-        private_handle_t *hnd = (private_handle_t *)handle;
-
-        // TODO(b/187145254): CPU_READ/WRITE buffer is not being properly locked from
-        // MFC. This is a WA for the time being.
-        constexpr auto cpu_access_usage =
-                (GRALLOC_USAGE_SW_WRITE_OFTEN | GRALLOC_USAGE_SW_READ_OFTEN |
-                 GRALLOC_USAGE_SW_WRITE_RARELY | GRALLOC_USAGE_SW_READ_RARELY);
-        return hnd->get_usage() & cpu_access_usage;
-    }
-
     static off_t get_buffer_size(unsigned int fd) {
         off_t current = lseek(fd, 0, SEEK_CUR);
         off_t size = lseek(fd, 0, SEEK_END);
@@ -213,8 +199,7 @@
         auto &data = *(it->second.get());
 
         data.ref_count++;
-        if (!should_map_dmabuf(handle)) return 0;
-        return map_locked(handle);
+        return 0;
     }
 
     int map(buffer_handle_t handle) EXCLUDES(lock) {
diff --git a/gralloc4/src/core/mfc_macros_local.h b/gralloc4/src/core/mfc_macros_local.h
deleted file mode 100644
index ab66d17..0000000
--- a/gralloc4/src/core/mfc_macros_local.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2020 Samsung Electronics Co. Ltd.
- * Copyright (C) 2021 Google LLC.
- *
- * 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.
- */
-
-#pragma once
-
-#if __has_include(<video/mfc_macros.h>)
-#error "This header should not be included if mfc_macros is available in UAPI"
-#endif
-
-/* helper macros */
-#ifndef __ALIGN_UP
-#define __ALIGN_UP(x, a)					(((x) + ((a) - 1)) & ~((a) - 1))
-#endif
-
-/* SBWC align macros */
-#define SBWC_8B_STRIDE(w)					(128 * (((w) + 31) / 32))
-#define SBWC_10B_STRIDE(w)					(160 * (((w) + 31) / 32))
-#define SBWC_HEADER_STRIDE(w)				((((((w) + 63) / 64) + 15) / 16) * 16)
-
-#define SBWC_Y_VSTRIDE_BLOCKS(h)			((__ALIGN_UP((h), 16) + 3) / 4)
-#define SBWC_CBCR_VSTRIDE_BLOCKS(h)			(((__ALIGN_UP((h), 16) / 2) + 3) / 4)
-
-#define SBWC_8B_Y_SIZE(w, h)				((SBWC_8B_STRIDE(w) * ((__ALIGN_UP((h), 16) + 3) / 4)) + 64)
-#define SBWC_8B_Y_HEADER_SIZE(w, h)			__ALIGN_UP(((SBWC_HEADER_STRIDE(w) * ((__ALIGN_UP((h), 16) + 3) / 4)) + 256), 32)
-#define SBWC_8B_CBCR_SIZE(w, h)				((SBWC_8B_STRIDE(w) * (((__ALIGN_UP((h), 16) / 2) + 3) / 4)) + 64)
-#define SBWC_8B_CBCR_HEADER_SIZE(w, h)		((SBWC_HEADER_STRIDE(w) * (((__ALIGN_UP((h), 16) / 2) + 3) / 4)) + 128)
-
-#define SBWC_10B_Y_SIZE(w, h)				((SBWC_10B_STRIDE(w) * ((__ALIGN_UP((h), 16) + 3) / 4)) + 64)
-#define SBWC_10B_Y_HEADER_SIZE(w, h)		__ALIGN_UP((((__ALIGN_UP((w), 32) * __ALIGN_UP((h), 16) * 2) + 256) - SBWC_10B_Y_SIZE(w, h)), 32)
-#define SBWC_10B_CBCR_SIZE(w, h)			((SBWC_10B_STRIDE(w) * (((__ALIGN_UP((h), 16) / 2) + 3) / 4)) + 64)
-#define SBWC_10B_CBCR_HEADER_SIZE(w, h)		(((__ALIGN_UP((w), 32) * __ALIGN_UP((h), 16)) + 256) - SBWC_10B_CBCR_SIZE(w, h))
-
-/* SBWC Lossy align macros */
-#define SBWCL_8B_STRIDE(w, r)				(((128 * (r)) / 100) * (((w) + 31) / 32))
-#define SBWCL_10B_STRIDE(w, r)				(((160 * (r)) / 100) * (((w) + 31) / 32))
-
-#define SBWCL_8B_Y_SIZE(w, h, r)			((SBWCL_8B_STRIDE(w, r) * ((__ALIGN_UP((h), 8) + 3) / 4)) + 64)
-#define SBWCL_8B_CBCR_SIZE(w, h, r)			((SBWCL_8B_STRIDE(w, r) * (((__ALIGN_UP((h), 8) / 2) + 3) / 4)) + 64)
-
-#define SBWCL_10B_Y_SIZE(w, h, r)			((SBWCL_10B_STRIDE(w, r) * ((__ALIGN_UP((h), 8) + 3) / 4)) + 64)
-#define SBWCL_10B_CBCR_SIZE(w, h, r)		((SBWCL_10B_STRIDE(w, r) * (((__ALIGN_UP((h), 8) / 2) + 3) / 4)) + 64)
-
-#define SBWCL_8B_CBCR_BASE(base, w, h, r)	((base) + SBWCL_8B_Y_SIZE(w, h, r))
-#define SBWCL_10B_CBCR_BASE(base, w, h, r)	((base) + SBWCL_10B_Y_SIZE(w, h, r))
-
diff --git a/gralloc4/src/hidl_common/MapperMetadata.cpp b/gralloc4/src/hidl_common/MapperMetadata.cpp
index cb0a820..fb79930 100644
--- a/gralloc4/src/hidl_common/MapperMetadata.cpp
+++ b/gralloc4/src/hidl_common/MapperMetadata.cpp
@@ -286,7 +286,8 @@
 static android::status_t get_plane_layouts(const private_handle_t *handle, std::vector<PlaneLayout> *layouts)
 {
 	const int num_planes = get_num_planes(handle);
-	int32_t format_index = get_format_index(handle->alloc_format & MALI_GRALLOC_INTFMT_FMT_MASK);
+	uint32_t base_format = handle->alloc_format & MALI_GRALLOC_INTFMT_FMT_MASK;
+	int32_t format_index = get_format_index(base_format);
 	if (format_index < 0)
 	{
 		MALI_GRALLOC_LOGE("Negative format index in get_plane_layouts");
@@ -304,10 +305,15 @@
 			int64_t sample_increment_in_bits = format_info.bpp[plane_index];
 			int64_t offset = handle->plane_info[plane_index].offset;
 
-			// TODO(b/182885532): Allocate the complete buffer contiguously
-			if (handle->plane_info[plane_index].fd_idx == plane_index)
-			{
-				offset = (int64_t)handle->bases[plane_index] - handle->bases[0];
+			static bool warn_multifd = true;
+			if (warn_multifd) {
+				uint8_t fd_count = get_exynos_fd_count(base_format);
+				if (fd_count != 1) {
+					warn_multifd = false;
+					MALI_GRALLOC_LOGW("Offsets in plane layouts of multi-fd format (%s %" PRIu64
+							") are not reliable. This can lead to image corruption.",
+							format_name(base_format), handle->alloc_format);
+				}
 			}
 
 			PlaneLayout layout = {.offsetInBytes = offset,
diff --git a/gralloc4/src/mali_gralloc_formats.h b/gralloc4/src/mali_gralloc_formats.h
index 0d16a50..e4120fa 100644
--- a/gralloc4/src/mali_gralloc_formats.h
+++ b/gralloc4/src/mali_gralloc_formats.h
@@ -371,4 +371,6 @@
 
 bool is_exynos_format(uint32_t base_format);
 
+uint8_t get_exynos_fd_count(uint32_t format);
+
 #endif /* MALI_GRALLOC_FORMATS_H_ */
diff --git a/include/VendorVideoAPI.h b/include/VendorVideoAPI.h
index 89f88ad..e744e4c 100644
--- a/include/VendorVideoAPI.h
+++ b/include/VendorVideoAPI.h
@@ -81,37 +81,72 @@
     };
 } ExynosHdrStaticInfo;
 
-typedef struct _ExynosHdrDynamicInfo {
-    unsigned int valid;
+typedef struct _ExynosHdrData_ST2094_40 {
+    unsigned char  country_code;
+    unsigned short provider_code;
+    unsigned short provider_oriented_code;
+
+    unsigned char  application_identifier;
+    unsigned char  application_version;
+
+    unsigned char num_windows;
+
+    unsigned short window_upper_left_corner_x[2];
+    unsigned short window_upper_left_corner_y[2];
+    unsigned short window_lower_right_corner_x[2];
+    unsigned short window_lower_right_corner_y[2];
+    unsigned short center_of_ellipse_x[2];
+    unsigned short center_of_ellipse_y[2];
+    unsigned char  rotation_angle[2];
+    unsigned short semimajor_axis_internal_ellipse[2];
+    unsigned short semimajor_axis_external_ellipse[2];
+    unsigned short semiminor_axis_external_ellipse[2];
+    unsigned char  overlap_process_option[2];
+
+    unsigned int  targeted_system_display_maximum_luminance;
+    unsigned char targeted_system_display_actual_peak_luminance_flag;
+    unsigned char num_rows_targeted_system_display_actual_peak_luminance;
+    unsigned char num_cols_targeted_system_display_actual_peak_luminance;
+    unsigned char targeted_system_display_actual_peak_luminance[25][25];
+
+    unsigned int maxscl[3][3];
+    unsigned int average_maxrgb[3];
+
+    unsigned char num_maxrgb_percentiles[3];
+    unsigned char maxrgb_percentages[3][15];
+    unsigned int  maxrgb_percentiles[3][15];
+
+    unsigned short fraction_bright_pixels[3];
+
+    unsigned char mastering_display_actual_peak_luminance_flag;
+    unsigned char num_rows_mastering_display_actual_peak_luminance;
+    unsigned char num_cols_mastering_display_actual_peak_luminance;
+    unsigned char mastering_display_actual_peak_luminance[25][25];
 
     struct {
-        unsigned char  country_code;
-        unsigned short provider_code;
-        unsigned short provider_oriented_code;
+        unsigned char   tone_mapping_flag[3];
+        unsigned short  knee_point_x[3];
+        unsigned short  knee_point_y[3];
+        unsigned char   num_bezier_curve_anchors[3];
+        unsigned short  bezier_curve_anchors[3][15];
+    } tone_mapping;
 
-        unsigned char  application_identifier;
-        unsigned short application_version;
+    unsigned char color_saturation_mapping_flag[3];
+    unsigned char color_saturation_weight[3];
+} ExynosHdrData_ST2094_40;
 
-        unsigned int  display_maximum_luminance;
-
-        unsigned int maxscl[3];
-
-        unsigned char num_maxrgb_percentiles;
-        unsigned char maxrgb_percentages[15];
-        unsigned int  maxrgb_percentiles[15];
-
-        struct {
-            unsigned short  tone_mapping_flag;
-            unsigned short  knee_point_x;
-            unsigned short  knee_point_y;
-            unsigned short  num_bezier_curve_anchors;
-            unsigned short  bezier_curve_anchors[15];
-        } tone_mapping;
-    } data;
-
+typedef struct _ExynosHdrDynamicInfo {
+    unsigned int valid;
     unsigned int reserved[42];
+
+    ExynosHdrData_ST2094_40 data;
 } ExynosHdrDynamicInfo;
 
+typedef struct _ExynosHdrDynamicBlob {
+    int  nSize;
+    char pData[1020];
+} ExynosHdrDynamicBlob;
+
 typedef struct _ExynosVideoCrop {
     int left;
     int top;
@@ -138,23 +173,31 @@
 } ExynosVideoEncData;
 
 typedef struct _ExynosVideoMeta {
-    ExynosVideoInfoType eType;
+    /***********************************************/
+    /****** WARNING: DO NOT MODIFY THIS AREA *******/
+    /**/                                         /**/
+    /**/  ExynosVideoInfoType eType;             /**/
+    /**/  int                 nHDRType;          /**/
+    /**/                                         /**/
+    /**/  ExynosColorAspects   sColorAspects;    /**/
+    /**/  ExynosHdrStaticInfo  sHdrStaticInfo;   /**/
+    /**/  ExynosHdrDynamicInfo sHdrDynamicInfo;  /**/
+    /**/                                         /**/
+    /****** WARNING: DO NOT MODIFY THIS AREA *******/
+    /***********************************************/
 
-    ExynosHdrStaticInfo  sHdrStaticInfo;
-    ExynosColorAspects   sColorAspects;
+    int nPixelFormat;
+    ExynosVideoCrop crop;
 
     union {
         ExynosVideoDecData dec;
         ExynosVideoEncData enc;
     } data;
 
-    ExynosHdrDynamicInfo sHdrDynamicInfo;
-
-    int nPixelFormat;
-    ExynosVideoCrop crop;
+    int reserved[20];   /* reserved filed for additional info */
 } ExynosVideoMeta;
 
-int Exynos_parsing_user_data_registered_itu_t_t35(ExynosHdrDynamicInfo *dest, void *src);
+int Exynos_parsing_user_data_registered_itu_t_t35(ExynosHdrDynamicInfo *dest, void *src, int size);
 int Exynos_dynamic_meta_to_itu_t_t35(ExynosHdrDynamicInfo *src, char *dst);
 
 #ifdef __cplusplus
diff --git a/videoapi/Android.mk b/videoapi/Android.mk
index c877d03..0fd176c 100644
--- a/videoapi/Android.mk
+++ b/videoapi/Android.mk
@@ -19,6 +19,8 @@
 LOCAL_MODULE_TAGS := optional
 LOCAL_PROPRIETARY_MODULE := true
 
+LOCAL_CFLAGS :=
+
 LOCAL_SRC_FILES := \
 	VendorVideoAPI.cpp
 
diff --git a/videoapi/VendorVideoAPI.cpp b/videoapi/VendorVideoAPI.cpp
index 34af549..e439051 100644
--- a/videoapi/VendorVideoAPI.cpp
+++ b/videoapi/VendorVideoAPI.cpp
@@ -26,6 +26,15 @@
 //#define LOG_NDEBUG 0
 #define LOG_TAG "VendorVideoAPI"
 
+/* Check data boundary before read it */
+#define CHECK_BOUNDARY(bit_offset, size) {                      \
+    if ((bit_offset) > (size) * 8) {                            \
+        ALOGE("[%s][%d] read bit offset(%d) > total bits(%d)",  \
+              __func__, __LINE__, (bit_offset), (size) * 8);    \
+        return -1;                                              \
+    }                                                           \
+}
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -39,7 +48,9 @@
 
 int Exynos_parsing_user_data_registered_itu_t_t35 (
     ExynosHdrDynamicInfo *dest,
-    void                 *src)
+    void                 *src,
+    int                  size)
+
 {
     int   bit_offset = 0;
     int   data       = 0;
@@ -65,6 +76,7 @@
 
     pHdr10PlusInfo = dest;
 
+    CHECK_BOUNDARY(bit_offset + 8, size);
     /* country_code : 8bit */
     for (i = 0; i < 1; i++) {
         for (j = 0; j < 8; j++) {
@@ -75,6 +87,7 @@
     pHdr10PlusInfo->data.country_code = data;
     data = 0;
 
+    CHECK_BOUNDARY(bit_offset + 16, size);
     /* terminal_provider_code : 16bit */
     for (i = 0; i < 2; i++) {
         for (j = 0; j < 8; j++) {
@@ -85,6 +98,7 @@
     pHdr10PlusInfo->data.provider_code = data;
     data = 0;
 
+    CHECK_BOUNDARY(bit_offset + 16, size);
     /* terminal_provider_oriented_code : 16bit */
     for (i = 0; i < 2; i++) {
         for (j = 0; j < 8; j++) {
@@ -95,6 +109,7 @@
     pHdr10PlusInfo->data.provider_oriented_code = data;
     data = 0;
 
+    CHECK_BOUNDARY(bit_offset + 8, size);
     /* application_identifier : 8bit*/
     for (i = 0; i < 1; i++) {
         for (j = 0; j < 8; j++) {
@@ -105,6 +120,7 @@
     pHdr10PlusInfo->data.application_identifier = data;
     data = 0;
 
+    CHECK_BOUNDARY(bit_offset + 8, size);
     /* application_version : 8bit*/
     for (i = 0; i < 1; i++) {
         for (j = 0; j < 8; j++) {
@@ -115,6 +131,7 @@
     pHdr10PlusInfo->data.application_version = data;
     data = 0;
 
+    CHECK_BOUNDARY(bit_offset + 2, size);
     /* num_windows : 2bit*/
     for (i = 0; i < 1; i++) {
         for (j = 0; j < 2; j++) {
@@ -124,12 +141,11 @@
     bit_offset += 2;
     extraBit   = (bit_offset % 8);
     data       = data >> (8 - extraBit);
-    //pHdr10PlusInfo->data.num_windows = data;
-    windows = data;
+    pHdr10PlusInfo->data.num_windows = data;
     data = 0;
 
-
-    for (i = 1; i < windows; i++) {
+    for (i = 1; i < pHdr10PlusInfo->data.num_windows; i++) {
+        CHECK_BOUNDARY(bit_offset + 16, size);
         /* window_upper_left_corner_x : 16bit */
         if (extraBit > 0)
             extraByte = 1;
@@ -139,7 +155,7 @@
                 data |= (*((char *)src + (bit_offset / 8) + j) & (1 << (7 - k)));
             }
 
-            if (j < 2)
+            if (j < 2 + extraByte - 1)
                 data = data << 8;
 
             extraBit += (k - extraBit);
@@ -149,10 +165,10 @@
         extraByte   = 0;
         extraBit    = bit_offset % 8;
         data        = (extraBit != 0) ? (data >> (8 - extraBit)) : data;
-        //pHdr10PlusInfo->data.window_upper_left_corner_x[i] = data;
+        pHdr10PlusInfo->data.window_upper_left_corner_x[i - 1] = data;
         data = 0;
 
-
+        CHECK_BOUNDARY(bit_offset + 16, size);
         /* window_upper_left_corner_y : 16bit */
         if (extraBit > 0)
             extraByte = 1;
@@ -162,7 +178,7 @@
                 data |= (*((char *)src + (bit_offset / 8) + j) & (1 << (7 - k)));
             }
 
-            if (j < 2)
+            if (j < 2 + extraByte - 1)
                 data = data << 8;
 
             extraBit += (k - extraBit);
@@ -172,11 +188,11 @@
         extraByte   = 0;
         extraBit    = bit_offset % 8;
         data        = (extraBit != 0) ? (data >> (8 - extraBit)) : data;
-        //pHdr10PlusInfo->data.window_upper_left_corner_y[i] = data;
+        pHdr10PlusInfo->data.window_upper_left_corner_y[i - 1] = data;
         data = 0;
 
-
-        /* window_upper_right_corner_x : 16bit */
+        CHECK_BOUNDARY(bit_offset + 16, size);
+        /* window_lower_right_corner_x : 16bit */
         if (extraBit > 0)
             extraByte = 1;
 
@@ -185,7 +201,7 @@
                 data |= (*((char *)src + (bit_offset / 8) + j) & (1 << (7 - k)));
             }
 
-            if (j < 2)
+            if (j < 2 + extraByte - 1)
                 data = data << 8;
 
             extraBit += (k - extraBit);
@@ -195,11 +211,11 @@
         extraByte   = 0;
         extraBit    = bit_offset % 8;
         data        = (extraBit != 0) ? (data >> (8 - extraBit)) : data;
-        //pHdr10PlusInfo->data.window_upper_right_corner_x[i] = data;
+        pHdr10PlusInfo->data.window_lower_right_corner_x[i - 1] = data;
         data = 0;
 
-
-        /* window_upper_right_corner_y : 16bit */
+        CHECK_BOUNDARY(bit_offset + 16, size);
+        /* window_lower_right_corner_y : 16bit */
         if (extraBit > 0)
             extraByte = 1;
 
@@ -208,7 +224,7 @@
                 data |= (*((char *)src + (bit_offset / 8) + j) & (1 << (7 - k)));
             }
 
-            if (j < 2)
+            if (j < 2 + extraByte - 1)
                 data = data << 8;
 
             extraBit += (k - extraBit);
@@ -218,10 +234,10 @@
         extraByte   = 0;
         extraBit    = bit_offset % 8;
         data        = (extraBit != 0) ? (data >> (8 - extraBit)) : data;
-        //pHdr10PlusInfo->data.window_upper_right_corner_y[i] = data;
+        pHdr10PlusInfo->data.window_lower_right_corner_y[i - 1] = data;
         data = 0;
 
-
+        CHECK_BOUNDARY(bit_offset + 16, size);
         /* center_of_ellipse_x : 16bit */
         if (extraBit > 0)
             extraByte = 1;
@@ -231,7 +247,7 @@
                 data |= (*((char *)src + (bit_offset / 8) + j) & (1 << (7 - k)));
             }
 
-            if (j < 2)
+            if (j < 2 + extraByte - 1)
                 data = data << 8;
 
             extraBit += (k - extraBit);
@@ -241,10 +257,10 @@
         extraByte   = 0;
         extraBit    = bit_offset % 8;
         data        = (extraBit != 0) ? (data >> (8 - extraBit)) : data;
-        //pHdr10PlusInfo->data.window_upper_right_corner_y[i] = data;
+        pHdr10PlusInfo->data.center_of_ellipse_x[i - 1] = data;
         data = 0;
 
-
+        CHECK_BOUNDARY(bit_offset + 16, size);
         /* center_of_ellipse_y : 16bit */
         if (extraBit > 0)
             extraByte = 1;
@@ -254,7 +270,7 @@
                 data |= (*((char *)src + (bit_offset / 8) + j) & (1 << (7 - k)));
             }
 
-            if (j < 2)
+            if (j < 2 + extraByte - 1)
                 data = data << 8;
 
             extraBit += (k - extraBit);
@@ -264,10 +280,10 @@
         extraByte   = 0;
         extraBit    = bit_offset % 8;
         data        = (extraBit != 0) ? (data >> (8 - extraBit)) : data;
-        //pHdr10PlusInfo->data.window_upper_right_corner_y[i] = data;
+        pHdr10PlusInfo->data.center_of_ellipse_y[i - 1] = data;
         data = 0;
 
-
+        CHECK_BOUNDARY(bit_offset + 8, size);
         /* rotation_angle : 8bit */
         if (extraBit > 0)
             extraByte = 1;
@@ -277,7 +293,7 @@
                 data |= (*((char *)src + (bit_offset / 8) + j) & (1 << (7 - k)));
             }
 
-            if (j < 1)
+            if (j < 1 + extraByte - 1)
                 data = data << 8;
 
             extraBit += (k - extraBit);
@@ -287,10 +303,10 @@
         extraByte   = 0;
         extraBit    = bit_offset % 8;
         data        = (extraBit != 0) ? (data >> (8 - extraBit)) : data;
-        //pHdr10PlusInfo->data.rotation_angle[i] = data;
+        pHdr10PlusInfo->data.rotation_angle[i - 1] = data;
         data = 0;
 
-
+        CHECK_BOUNDARY(bit_offset + 16, size);
         /* semimajor_axis_internal_ellipse : 16bit */
         if (extraBit > 0)
             extraByte = 1;
@@ -300,7 +316,7 @@
                 data |= (*((char *)src + (bit_offset / 8) + j) & (1 << (7 - k)));
             }
 
-            if (j < 2)
+            if (j < 2 + extraByte - 1)
                 data = data << 8;
 
             extraBit += (k - extraBit);
@@ -310,10 +326,10 @@
         extraByte   = 0;
         extraBit    = bit_offset % 8;
         data        = (extraBit != 0) ? (data >> (8 - extraBit)) : data;
-        //pHdr10PlusInfo->data.semimajor_axis_internal_ellipse[i] = data;
+        pHdr10PlusInfo->data.semimajor_axis_internal_ellipse[i - 1] = data;
         data = 0;
 
-
+        CHECK_BOUNDARY(bit_offset + 16, size);
         /* semimajor_axis_external_ellipse : 16bit */
         if (extraBit > 0)
             extraByte = 1;
@@ -323,7 +339,7 @@
                 data |= (*((char *)src + (bit_offset / 8) + j) & (1 << (7 - k)));
             }
 
-            if (j < 2)
+            if (j < 2 + extraByte - 1)
                 data = data << 8;
 
             extraBit += (k - extraBit);
@@ -333,10 +349,10 @@
         extraByte   = 0;
         extraBit    = bit_offset % 8;
         data        = (extraBit != 0) ? (data >> (8 - extraBit)) : data;
-        //pHdr10PlusInfo->data.semimajor_axis_external_ellipse[i] = data;
+        pHdr10PlusInfo->data.semimajor_axis_external_ellipse[i - 1] = data;
         data = 0;
 
-
+        CHECK_BOUNDARY(bit_offset + 16, size);
         /* semiminor_axis_external_ellipse : 16bit */
         if (extraBit > 0)
             extraByte = 1;
@@ -346,7 +362,7 @@
                 data |= (*((char *)src + (bit_offset / 8) + j) & (1 << (7 - k)));
             }
 
-            if (j < 2)
+            if (j < 2 + extraByte - 1)
                 data = data << 8;
 
             extraBit += (k - extraBit);
@@ -356,10 +372,10 @@
         extraByte   = 0;
         extraBit    = bit_offset % 8;
         data        = (extraBit != 0) ? (data >> (8 - extraBit)) : data;
-        //pHdr10PlusInfo->data.semiminor_axis_external_ellipse[i] = data;
+        pHdr10PlusInfo->data.semiminor_axis_external_ellipse[i - 1] = data;
         data = 0;
 
-
+        CHECK_BOUNDARY(bit_offset + 1, size);
         /* overlap_process_option : 1bit */
         data |= (*((char *)src + (bit_offset / 8)) & (1 << (7 - extraBit)));
 
@@ -367,11 +383,11 @@
         extraByte    = 0;
         extraBit     = bit_offset % 8;
         data        = (extraBit != 0) ? (data >> (8 - extraBit)) : data;
-        //pHdr10PlusInfo->data.overlap_process_option[i] = data;
+        pHdr10PlusInfo->data.overlap_process_option[i - 1] = data;
         data = 0;
     }
 
-
+    CHECK_BOUNDARY(bit_offset + 27, size);
     /* targeted_system_display_maximum_luminance : 27bit */
     if (extraBit > 5)
         extraByte = 2;
@@ -386,29 +402,29 @@
         if (i < 3 + extraByte - 1)
             data = data << 8;
 
-        extraBit += (k - extraBit);
+        extraBit += (j - extraBit);
         extraBit %= 8;
     }
     bit_offset += 27;
     extraByte   = 0;
     extraBit    = bit_offset % 8;
     data        = (extraBit != 0) ? (data >> (8 - extraBit)) : data;
-    pHdr10PlusInfo->data.display_maximum_luminance = data;
+    pHdr10PlusInfo->data.targeted_system_display_maximum_luminance = data;
     data = 0;
 
-
+    CHECK_BOUNDARY(bit_offset + 1, size);
     /* targeted_system_display_actual_peak_luminance_flag : 1bit */
     data |= (*((char *)src + (bit_offset / 8)) & (1 << (7 - extraBit)));
 
     bit_offset  += 1;
     extraBit     = bit_offset % 8;
     data        = (extraBit != 0) ? (data >> (8 - extraBit)) : data;
-    //pHdr10PlusInfo->data.targeted_system_display_actual_peak_luminance_flag = data;
+    pHdr10PlusInfo->data.targeted_system_display_actual_peak_luminance_flag = data;
     targeted_system_display_actual_peak_luminance_flag = data;
     data = 0;
 
-
     if (targeted_system_display_actual_peak_luminance_flag) {
+        CHECK_BOUNDARY(bit_offset + 5, size);
         /* num_rows_targeted_system_display_actual_peak_luminance : 5bit */
         if (extraBit > 3)
             extraByte = 1;
@@ -418,7 +434,7 @@
                 data |= (*((char *)src + (bit_offset / 8) + i) & (1 << (7 - j)));
             }
 
-            if (i < 1)
+            if (i < 1 + extraByte - 1)
                 data = data << 8;
 
             extraBit += (j - extraBit);
@@ -428,11 +444,11 @@
         extraByte   = 0;
         extraBit    = bit_offset % 8;
         data        = (extraBit != 0) ? (data >> (8 - extraBit)) : data;
-        //pHdr10PlusInfo->data.num_rows_targeted_system_display_actual_peak_luminance = data;
+        pHdr10PlusInfo->data.num_rows_targeted_system_display_actual_peak_luminance = data;
         num_rows_targeted_system_display_actual_peak_luminance = data;
         data = 0;
 
-
+        CHECK_BOUNDARY(bit_offset + 5, size);
         /* num_cols_targeted_system_display_actual_peak_luminance : 5bit */
         if (extraBit > 3)
             extraByte = 1;
@@ -442,7 +458,7 @@
                 data |= (*((char *)src + (bit_offset / 8) + i) & (1 << (7 - j)));
             }
 
-            if (i < 1)
+            if (i < 1 + extraByte - 1)
                 data = data << 8;
 
             extraBit += (j - extraBit);
@@ -452,14 +468,14 @@
         extraByte   = 0;
         extraBit    = bit_offset % 8;
         data        = (extraBit != 0) ? (data >> (8 - extraBit)) : data;
-        //pHdr10PlusInfo->data.num_cols_targeted_system_display_actual_peak_luminance = data;
+        pHdr10PlusInfo->data.num_cols_targeted_system_display_actual_peak_luminance = data;
         num_cols_targeted_system_display_actual_peak_luminance = data;
         data = 0;
 
-
         for (i = 0; i < num_rows_targeted_system_display_actual_peak_luminance; i++) {
             for (j = 0; j < num_cols_targeted_system_display_actual_peak_luminance; j++) {
-                /* mastering_display_actual_peak_luminance : 4bit */
+                CHECK_BOUNDARY(bit_offset + 4, size);
+                /* targeted_system_display_actual_peak_luminance : 4bit */
                 if (extraBit > 4)
                     extraByte = 1;
 
@@ -468,7 +484,7 @@
                         data |= (*((char *)src + (bit_offset / 8) + k) & (1 << (7 - l)));
                     }
 
-                    if (k < 1)
+                    if (k < 1 + extraByte - 1)
                         data = data << 8;
 
                     extraBit += (l - extraBit);
@@ -478,14 +494,15 @@
                 extraByte   = 0;
                 extraBit    = bit_offset % 8;
                 data        = (extraBit != 0) ? (data >> (8 - extraBit)) : data;
-                //pHdr10PlusInfo->data.mastering_display_actual_peak_luminance = data;
+                pHdr10PlusInfo->data.targeted_system_display_actual_peak_luminance[i][j] = data;
                 data = 0;
             }
         }
     }
 
-    for (i = 0; i < windows; i++) {
+    for (i = 0; i < pHdr10PlusInfo->data.num_windows; i++) {
         for (j = 0; j < 3; j++) {
+            CHECK_BOUNDARY(bit_offset + 17, size);
             /* maxscl : 17bit */
             for (k = 0; k < 3; k++) {
                 for (l = extraBit; l < 8; l++) {
@@ -504,10 +521,11 @@
             if (extraBit != 0)
                 data = data >> (8 - extraBit);
 
-            pHdr10PlusInfo->data.maxscl[j] = data;
+            pHdr10PlusInfo->data.maxscl[i][j] = data;
             data = 0;
         }
 
+        CHECK_BOUNDARY(bit_offset + 17, size);
         /* average_maxrgb : 17bit */
         for (j = 0; j < 3; j++) {
             for (k = extraBit; k < 8; k++) {
@@ -523,10 +541,10 @@
         bit_offset += 17;
         extraBit    = bit_offset % 8;
         data        = (extraBit != 0) ? (data >> (8 - extraBit)) : data;
-        //pHdr10PlusInfo->data.average_maxrgb = data;
+        pHdr10PlusInfo->data.average_maxrgb[i] = data;
         data = 0;
 
-
+        CHECK_BOUNDARY(bit_offset + 4, size);
         /* num_distribution_maxrgb_percentiles : 4bit */
         if (extraBit > 4)
             extraByte = 1;
@@ -536,10 +554,8 @@
                 data |= (*((char *)src + (bit_offset / 8) + j) & (1 << (7 - k)));
             }
 
-            if (extraByte > 0) {
-                if (j < 1)
-                    data = data << 8;
-            }
+            if (j < 1 + extraByte - 1)
+                data = data << 8;
 
             extraBit += (k - extraBit);
             extraBit %= 8;
@@ -548,11 +564,11 @@
         extraByte   = 0;
         extraBit    = bit_offset % 8;
         data        = (extraBit != 0) ? (data >> (8 - extraBit)) : data;
-        pHdr10PlusInfo->data.num_maxrgb_percentiles = data;
+        pHdr10PlusInfo->data.num_maxrgb_percentiles[i] = data;
         data = 0;
 
-
-        for (j = 0; j < pHdr10PlusInfo->data.num_maxrgb_percentiles; j++) {
+        for (j = 0; j < pHdr10PlusInfo->data.num_maxrgb_percentiles[i]; j++) {
+            CHECK_BOUNDARY(bit_offset + 7, size);
             /* distribution_maxrgb_percentages : 7bit */
             if (extraBit > 1)
                 extraByte = 1;
@@ -562,7 +578,7 @@
                     data |= (*((char *)src + (bit_offset / 8) + k) & (1 << (7 - l)));
                 }
 
-                if (k < 1)
+                if (k < 1 + extraByte - 1)
                     data = data << 8;
 
                 extraBit += (l - extraBit);
@@ -572,10 +588,10 @@
             extraByte   = 0;
             extraBit    = bit_offset % 8;
             data        = (extraBit != 0) ? (data >> (8 - extraBit)) : data;
-            pHdr10PlusInfo->data.maxrgb_percentages[j] = data;
+            pHdr10PlusInfo->data.maxrgb_percentages[i][j] = data;
             data = 0;
 
-
+            CHECK_BOUNDARY(bit_offset + 17, size);
             /* distribution_maxrgb_percentiles : 17bit */
             if (extraBit >= 0)
                 extraByte = 1;
@@ -585,7 +601,7 @@
                     data |= (*((char *)src + (bit_offset / 8) + k) & (1 << (7 - l)));
                 }
 
-                if (k < 2)
+                if (k < 2 + extraByte - 1)
                     data = data << 8;
 
                 extraBit += (l - extraBit);
@@ -595,11 +611,11 @@
             extraByte   = 0;
             extraBit    = bit_offset % 8;
             data        = (extraBit != 0) ? (data >> (8 - extraBit)) : data;
-            pHdr10PlusInfo->data.maxrgb_percentiles[j] = data;
+            pHdr10PlusInfo->data.maxrgb_percentiles[i][j] = data;
             data = 0;
         }
 
-
+        CHECK_BOUNDARY(bit_offset + 10, size);
         /* fraction_bright_pixels : 10bit*/
         if (extraBit > 6)
             extraByte = 2;
@@ -611,7 +627,7 @@
                 data |= (*((char *)src + (bit_offset / 8) + j) & (1 << (7 - k)));
             }
 
-            if (j < 2)
+            if (j < 1 + extraByte - 1)
                 data = data << 8;
 
             extraBit += (k - extraBit);
@@ -621,23 +637,23 @@
         extraByte   = 0;
         extraBit    = bit_offset % 8;
         data        = (extraBit != 0) ? (data >> (8 - extraBit)) : data;
-        //pHdr10PlusInfo->data.fraction_bright_pixels = data;
+        pHdr10PlusInfo->data.fraction_bright_pixels[i] = data;
         data = 0;
     }
 
-
+    CHECK_BOUNDARY(bit_offset + 1, size);
     /* mastering_display_actual_peak_luminance_flag : 1bit */
     data |= (*((char *)src + (bit_offset / 8)) & (1 << (7 - extraBit)));
 
     bit_offset  += 1;
     extraBit     = bit_offset % 8;
     data        = (extraBit != 0) ? (data >> (8 - extraBit)) : data;
-    //pHdr10PlusInfo->data.mastering_display_actual_peak_luminance_flag = data;
+    pHdr10PlusInfo->data.mastering_display_actual_peak_luminance_flag = data;
     mastering_display_actual_peak_luminance_flag = data;
     data = 0;
 
-
     if (mastering_display_actual_peak_luminance_flag) {
+        CHECK_BOUNDARY(bit_offset + 5, size);
         /* num_rows_mastering_display_actual_peak_luminance : 5bit */
         if (extraBit > 3)
             extraByte = 1;
@@ -647,7 +663,7 @@
                 data |= (*((char *)src + (bit_offset / 8) + i) & (1 << (7 - j)));
             }
 
-            if (i < 1)
+            if (i < 1 + extraByte - 1)
                 data = data << 8;
 
             extraBit += (j - extraBit);
@@ -657,11 +673,11 @@
         extraByte   = 0;
         extraBit    = bit_offset % 8;
         data        = (extraBit != 0) ? (data >> (8 - extraBit)) : data;
-        //pHdr10PlusInfo->data.num_rows_mastering_display_actual_peak_luminance = data;
+        pHdr10PlusInfo->data.num_rows_mastering_display_actual_peak_luminance = data;
         num_rows_mastering_display_actual_peak_luminance = data;
         data = 0;
 
-
+        CHECK_BOUNDARY(bit_offset + 5, size);
         /* num_cols_mastering_display_actual_peak_luminance : 5bit */
         if (extraBit > 3)
             extraByte = 1;
@@ -671,7 +687,7 @@
                 data |= (*((char *)src + (bit_offset / 8) + i) & (1 << (7 - j)));
             }
 
-            if (i < 1)
+            if (i < 1 + extraByte - 1)
                 data = data << 8;
 
             extraBit += (j - extraBit);
@@ -681,13 +697,13 @@
         extraByte   = 0;
         extraBit    = bit_offset % 8;
         data        = (extraBit != 0) ? (data >> (8 - extraBit)) : data;
-        //pHdr10PlusInfo->data.num_cols_mastering_display_actual_peak_luminance = data;
+        pHdr10PlusInfo->data.num_cols_mastering_display_actual_peak_luminance = data;
         num_cols_mastering_display_actual_peak_luminance = data;
         data = 0;
 
-
         for (i = 0; i < num_rows_mastering_display_actual_peak_luminance; i++) {
             for (j = 0; j < num_cols_mastering_display_actual_peak_luminance; j++) {
+                CHECK_BOUNDARY(bit_offset + 4, size);
                 /* mastering_display_actual_peak_luminance : 4bit */
                 if (extraBit > 4)
                     extraByte = 1;
@@ -697,7 +713,7 @@
                         data |= (*((char *)src + (bit_offset / 8) + k) & (1 << (7 - l)));
                     }
 
-                    if (k < 1)
+                    if (k < 1 + extraByte - 1)
                         data = data << 8;
 
                     extraBit += (l - extraBit);
@@ -707,28 +723,29 @@
                 extraByte   = 0;
                 extraBit    = bit_offset % 8;
                 data        = (extraBit != 0) ? (data >> (8 - extraBit)) : data;
-                //pHdr10PlusInfo->data.mastering_display_actual_peak_luminance = data;
+                pHdr10PlusInfo->data.mastering_display_actual_peak_luminance[i][j] = data;
                 data = 0;
             }
         }
     }
 
-    for (i = 0; i < windows; i++) {
+    for (i = 0; i < pHdr10PlusInfo->data.num_windows; i++) {
+        CHECK_BOUNDARY(bit_offset + 1, size);
         /* tone_mapping_flag : 1bit */
         data |= (*((char *)src + (bit_offset / 8)) & (1 << (7 - extraBit)));
 
         bit_offset  += 1;
         extraBit     = bit_offset % 8;
-        data         = data >> (8 - extraBit);
-        pHdr10PlusInfo->data.tone_mapping.tone_mapping_flag = data;
+        data         = (extraBit != 0) ? (data >> (8 - extraBit)) : data;
+        pHdr10PlusInfo->data.tone_mapping.tone_mapping_flag[i] = data;
         data = 0;
 
-
-        if (pHdr10PlusInfo->data.tone_mapping.tone_mapping_flag) {
+        if (pHdr10PlusInfo->data.tone_mapping.tone_mapping_flag[i]) {
+            CHECK_BOUNDARY(bit_offset + 12, size);
             /* knee_point_x : 12bit */
-            if (extraBit > 5)
+            if (extraBit > 4)
                 extraByte = 2;
-            else if (extraBit <= 5)
+            else if (extraBit <= 4)
                 extraByte = 1;
 
             for (j = 0; j < 1 + extraByte; j++) {
@@ -746,14 +763,14 @@
             extraByte   = 0;
             extraBit    = bit_offset % 8;
             data        = (extraBit != 0) ? (data >> (8 - extraBit)) : data;
-            pHdr10PlusInfo->data.tone_mapping.knee_point_x = data;
+            pHdr10PlusInfo->data.tone_mapping.knee_point_x[i] = data;
             data = 0;
 
-
+            CHECK_BOUNDARY(bit_offset + 12, size);
             /* knee_point_y : 12bit */
-            if (extraBit > 5)
+            if (extraBit > 4)
                 extraByte = 2;
-            else if (extraBit <= 5)
+            else if (extraBit <= 4)
                 extraByte = 1;
 
             for (j = 0; j < 1 + extraByte; j++) {
@@ -771,10 +788,10 @@
             extraByte   = 0;
             extraBit    = bit_offset % 8;
             data        = (extraBit != 0) ? (data >> (8 - extraBit)) : data;
-            pHdr10PlusInfo->data.tone_mapping.knee_point_y = data;
+            pHdr10PlusInfo->data.tone_mapping.knee_point_y[i] = data;
             data = 0;
 
-
+            CHECK_BOUNDARY(bit_offset + 4, size);
             /* num_bezier_curve_anchors : 4bit */
             if (extraBit > 4)
                 extraByte = 1;
@@ -794,11 +811,11 @@
             extraByte   = 0;
             extraBit    = bit_offset % 8;
             data        = (extraBit != 0) ? (data >> (8 - extraBit)) : data;
-            pHdr10PlusInfo->data.tone_mapping.num_bezier_curve_anchors = data;
+            pHdr10PlusInfo->data.tone_mapping.num_bezier_curve_anchors[i] = data;
             data = 0;
 
-
-            for (j = 0; j < pHdr10PlusInfo->data.tone_mapping.num_bezier_curve_anchors; j++) {
+            for (j = 0; j < pHdr10PlusInfo->data.tone_mapping.num_bezier_curve_anchors[i]; j++) {
+                CHECK_BOUNDARY(bit_offset + 10, size);
                 /* bezier_curve_anchors : 10bit */
                 if (extraBit > 6)
                     extraByte = 2;
@@ -820,12 +837,12 @@
                 extraByte   = 0;
                 extraBit    = bit_offset % 8;
                 data        = (extraBit != 0) ? (data >> (8 - extraBit)) : data;
-                pHdr10PlusInfo->data.tone_mapping.bezier_curve_anchors[j] = data;
+                pHdr10PlusInfo->data.tone_mapping.bezier_curve_anchors[i][j] = data;
                 data = 0;
             }
         }
 
-
+        CHECK_BOUNDARY(bit_offset + 1, size);
         /* color_saturation_mapping_flag : 1bit */
         data |= (*((char *)src + (bit_offset / 8)) & (1 << (7 - extraBit)));
 
@@ -833,14 +850,13 @@
         extraByte    = 0;
         extraBit     = bit_offset % 8;
         data        = (extraBit != 0) ? (data >> (8 - extraBit)) : data;
-        //pHdr10PlusInfo->data.color_saturation_mapping_flag = data;
-        color_saturation_mapping_flag = data;
+        pHdr10PlusInfo->data.color_saturation_mapping_flag[i] = data;
         data = 0;
 
-
-        if (color_saturation_mapping_flag) {
+        if (pHdr10PlusInfo->data.color_saturation_mapping_flag[i]) {
+            CHECK_BOUNDARY(bit_offset + 6, size);
             /* color_saturation_weight : 6bit */
-            if (extraBit > 3)
+            if (extraBit > 2)
                 extraByte = 1;
 
             for (j = 0; j < 1 + extraByte; j++) {
@@ -858,7 +874,7 @@
             extraByte   = 0;
             extraBit    = bit_offset % 8;
             data        = (extraBit != 0) ? (data >> (8 - extraBit)) : data;
-            //pHdr10PlusInfo->color_saturation_weight = data;
+            pHdr10PlusInfo->data.color_saturation_weight[i] = data;
             data = 0;
         }
     }
@@ -882,7 +898,7 @@
     int buffer     = 0;
     int tempBuffer = 0;
 
-    int i, j, k;
+    int i, j, k, l;
 
     if ((src == NULL) || (dst == NULL)) {
         ALOGE("[%s] invalid parameters", __FUNCTION__);
@@ -903,6 +919,7 @@
         if (bit_offset == offset_limit)
             break;
     }
+    extraBit = (bit_offset % 8);
 
     /* terminal_provider_code: 16bit */
     offset_limit = bit_offset + 16;
@@ -917,6 +934,7 @@
                 break;
         }
     }
+    extraBit = (bit_offset % 8);
 
     /* terminal_provider_oriented_code: 16bit */
     offset_limit = bit_offset + 16;
@@ -931,6 +949,7 @@
                 break;
         }
     }
+    extraBit = (bit_offset % 8);
 
     /* application_identifier: 8bit */
     offset_limit = bit_offset + 8;
@@ -943,6 +962,7 @@
         if (bit_offset == offset_limit)
             break;
     }
+    extraBit = (bit_offset % 8);
 
     /* application_version: 8bit */
     offset_limit = bit_offset + 8;
@@ -955,129 +975,14 @@
         if (bit_offset == offset_limit)
             break;
     }
+    extraBit = (bit_offset % 8);
 
     /* num_windows: 2bit */
     offset_limit = bit_offset + 2;
 
+    tempBuffer = pHDRDynamicInfo->data.num_windows << (6 - extraBit);
     for (i = 0; i < 2; i++) {
         /* num_windows is always 1 now */
-        *((char *)pBlob + (bit_offset / 8)) |= ((char)0x40/* num_windows */ & (1 << (7 - i)));
-        bit_offset++;
-
-        if (bit_offset == offset_limit)
-            break;
-    }
-    extraBit = (bit_offset % 8);
-
-    for (i = 1; i < 1 /* num_windows */; i++) {
-        /* window_upper_left_corner_x: 16bit */
-        bit_offset += 16;
-        extraBit = (bit_offset % 8);
-
-        /* window_upper_left_corner_y: 16bit */
-        bit_offset += 16;
-        extraBit = (bit_offset % 8);
-
-        /* window_upper_right_corner_x: 16bit */
-        bit_offset += 16;
-        extraBit = (bit_offset % 8);
-
-        /* window_upper_right_corner_y: 16bit */
-        bit_offset += 16;
-        extraBit = (bit_offset % 8);
-
-        /* center_of_ellipse_x: 16bit */
-        bit_offset += 16;
-        extraBit = (bit_offset % 8);
-
-        /* center_of_ellipse_y: 16bit */
-        bit_offset += 16;
-        extraBit = (bit_offset % 8);
-
-        /* rotation_angle: 8bit */
-        bit_offset += 8;
-        extraBit = (bit_offset % 8);
-
-        /* semimajor_axis_internal_ellipse: 16bit */
-        bit_offset += 16;
-        extraBit = (bit_offset % 8);
-
-        /* semimajor_axis_external_ellipse: 16bit */
-        bit_offset += 16;
-        extraBit = (bit_offset % 8);
-
-        /* semiminor_axis_external_ellipse: 16bit */
-        bit_offset += 16;
-        extraBit = (bit_offset % 8);
-
-        /* overlap_process_option: 1bit */
-        bit_offset += 1;
-        extraBit = (bit_offset % 8);
-    }
-
-    /* targeted_system_display_maximum_luminance: 27bit */
-    offset_limit = bit_offset + 27;
-
-    tempBuffer = pHDRDynamicInfo->data.display_maximum_luminance << (5 - extraBit);
-    for (i = 0; i < 4; i++) {
-        memcpy((char *)&buffer + i, (char *)&tempBuffer + (3 - i), sizeof(char));
-    }
-
-    for (i = 0; i < 4; i++) {
-        for (j = extraBit; j < 8; j++) {
-            *((char *)pBlob + (bit_offset / 8)) |= (*((char *)&buffer + i) & (1 << (7 - j)));
-            bit_offset++;
-
-            if (bit_offset == offset_limit)
-                break;
-        }
-        extraBit = (bit_offset % 8);
-    }
-    buffer     = 0;
-    tempBuffer = 0;
-
-    /* targeted_system_display_actual_peak_luminance_flag: 1bit (always 0) */
-    bit_offset += 1;
-    extraBit = (bit_offset % 8);
-
-    /* NOTE: These info would not set because targeted_system_display_actual_peak_luminance_flag is always 0
-     * - num_rows_targeted_system_display_actual_peak_luminance: 5bit
-     * - num_cols_targeted_system_display_actual_peak_luminance: 5bit
-     * - targeted_system_display_actual_peak_luminance: 4bit */
-
-    /* maxscl: 17bit */
-    for (i = 0; i < 3; i++) {
-        offset_limit = bit_offset + 17;
-
-        tempBuffer = pHDRDynamicInfo->data.maxscl[i] << (15 - extraBit);
-        for (j = 0; j < 4; j++) {
-            memcpy((char *)&buffer + j, (char *)&tempBuffer + (3 - j), sizeof(char));
-        }
-
-        for (j = 0; j < 3; j++) {
-            for (k = extraBit; k < 8; k++) {
-                *((char *)pBlob + (bit_offset / 8)) |= (*((char *)&buffer + j) & (1 << (7 - k)));
-                bit_offset++;
-
-                if (bit_offset == offset_limit)
-                    break;
-            }
-            extraBit = (bit_offset % 8);
-        }
-        buffer     = 0;
-        tempBuffer = 0;
-    }
-
-    /* average_maxrgb: 17bit */
-    bit_offset += 17;
-    extraBit = (bit_offset % 8);
-
-    /* num_distribution_maxrgb_percentiles: 4bit */
-    offset_limit = bit_offset + 4;
-
-    tempBuffer = pHDRDynamicInfo->data.num_maxrgb_percentiles << (4 - extraBit);
-
-    for (i = extraBit; i < 8; i++) {
         *((char *)pBlob + (bit_offset / 8)) |= (*((char *)&tempBuffer) & (1 << (7 - i)));
         bit_offset++;
 
@@ -1087,117 +992,15 @@
     extraBit = (bit_offset % 8);
     tempBuffer = 0;
 
-    for (i = 0; i < pHDRDynamicInfo->data.num_maxrgb_percentiles; i++) {
-        /* distribution_maxrgb_percentaged: 7bit */
-        offset_limit = bit_offset + 7;
+    for (i = 1; i < pHDRDynamicInfo->data.num_windows; i++) {
+        /* window_upper_left_corner_x: 16bit */
+        offset_limit = bit_offset + 16;
 
-        if (extraBit > 1)
+        if (extraBit > 0)
             extraByte = 1;
 
-        tempBuffer = pHDRDynamicInfo->data.maxrgb_percentages[i];
-        tempBuffer = tempBuffer << (25 - extraBit);
-
-        for (j = 0; j < 4; j++) {
-            memcpy((char *)&buffer + j, (char *)&tempBuffer + (3 - j), sizeof(char));
-        }
-
-        for (j = 0; j < (1 + extraByte); j++) {
-            for (k = extraBit; k < 8; k++) {
-                *((char *)pBlob + (bit_offset / 8)) |= (*((char *)&buffer + j) & (1 << (7 - k)));
-                bit_offset++;
-
-                if (bit_offset == offset_limit) {
-                    break;
-                }
-            }
-            extraBit = (bit_offset % 8);
-        }
-        buffer     = 0;
-        tempBuffer = 0;
-        extraByte  = 0;
-
-        /* distribution_maxrgb_percentiles: 17bit */
-        offset_limit = bit_offset + 17;
-
-        tempBuffer = pHDRDynamicInfo->data.maxrgb_percentiles[i] << (15 - extraBit);
-
-        for (j = 0; j < 4; j++) {
-            memcpy((char *)&buffer + j, (char *)&tempBuffer + (3 - j), sizeof(char));
-        }
-
-        for (j = 0; j < 3; j++) {
-            for (k = extraBit; k < 8; k++) {
-                *((char *)pBlob + (bit_offset / 8)) |= (*((char *)&buffer + j) & (1 << (7 - k)));
-                bit_offset++;
-
-                if (bit_offset == offset_limit) {
-                    break;
-                }
-            }
-            extraBit = (bit_offset % 8);
-        }
-        buffer     = 0;
-        tempBuffer = 0;
-    }
-
-    /* fraction_bright_pixels: 10bit */
-    bit_offset += 10;
-    extraBit = (bit_offset % 8);
-
-    /* mastering_display_actual_peak_luminance_flag: 1bit */
-    bit_offset += 1;
-    extraBit = (bit_offset % 8);
-
-    /* NOTE: These infos would not be set because mastering_display_actual_peak_luminance_flag is always 0.
-     * - num_rows_mastering_display_actual_peak_luminance: 5bit
-     * - num_cols_mastering_display_actual_peak_luminance: 5bit
-     * - mastering_display_actual_peak_luminance: 4bit */
-
-    /* tone_mapping_flag: 1bit */
-    if (pHDRDynamicInfo->data.tone_mapping.tone_mapping_flag) {
-        *((char *)pBlob + (bit_offset / 8)) |= (1 << (7 - extraBit));
-    }
-    bit_offset += 1;
-    extraBit = (bit_offset % 8);
-
-    if (pHDRDynamicInfo->data.tone_mapping.tone_mapping_flag) {
-        /* knee_point_x: 12bit */
-        if (extraBit > 4)
-            extraByte = 1;
-
-        offset_limit = bit_offset + 12;
-
-        tempBuffer = pHDRDynamicInfo->data.tone_mapping.knee_point_x;
-        tempBuffer = tempBuffer << (20 - extraBit);
-
-        for (i = 0; i < 4; i++) {
-            memcpy((char *)&buffer + i, (char *)&tempBuffer + (3 - i), sizeof(char));
-        }
-
-        for (i = 0; i < (2 + extraByte); i++) {
-            for (j = extraBit; j < 8; j++) {
-                *((char *)pBlob + (bit_offset / 8)) |= (*((char *)&buffer + i) & (1 << (7 - j)));
-                bit_offset++;
-
-                if (bit_offset == offset_limit) {
-                    break;
-                }
-            }
-            extraBit = (bit_offset % 8);
-        }
-        buffer     = 0;
-        tempBuffer = 0;
-        extraByte  = 0;
-
-        /* knee_point_y: 12bit */
-        if (extraBit > 4)
-            extraByte = 1;
-
-        offset_limit = bit_offset + 12;
-
-        tempBuffer = pHDRDynamicInfo->data.tone_mapping.knee_point_y;
-        tempBuffer = tempBuffer << (20 - extraBit);
-
+        tempBuffer = pHDRDynamicInfo->data.window_upper_left_corner_x[i - 1];
+        tempBuffer = tempBuffer << (16 - extraBit);
         for (j = 0; j < 4; j++) {
             memcpy((char *)&buffer + j, (char *)&tempBuffer + (3 - j), sizeof(char));
         }
@@ -1217,15 +1020,149 @@
         tempBuffer = 0;
         extraByte  = 0;
 
-        /* num_bezier_curve_anchors: 4bit */
-        if (extraBit > 4)
+        /* window_upper_left_corner_y: 16bit */
+        offset_limit = bit_offset + 16;
+
+        if (extraBit > 0)
             extraByte = 1;
 
-        offset_limit = bit_offset + 4;
+        tempBuffer = pHDRDynamicInfo->data.window_upper_left_corner_y[i - 1];
+        tempBuffer = tempBuffer << (16 - extraBit);
+        for (j = 0; j < 4; j++) {
+            memcpy((char *)&buffer + j, (char *)&tempBuffer + (3 - j), sizeof(char));
+        }
 
-        tempBuffer = pHDRDynamicInfo->data.tone_mapping.num_bezier_curve_anchors;
-        tempBuffer = tempBuffer << (28 - extraBit);
+        for (j = 0; j < (2 + extraByte); j++) {
+            for (k = extraBit; k < 8; k++) {
+                *((char *)pBlob + (bit_offset / 8)) |= (*((char *)&buffer + j) & (1 << (7 - k)));
+                bit_offset++;
 
+                if (bit_offset == offset_limit) {
+                    break;
+                }
+            }
+            extraBit = (bit_offset % 8);
+        }
+        buffer     = 0;
+        tempBuffer = 0;
+        extraByte  = 0;
+
+        /* window_lower_right_corner_x: 16bit */
+        offset_limit = bit_offset + 16;
+
+        if (extraBit > 0)
+            extraByte = 1;
+
+        tempBuffer = pHDRDynamicInfo->data.window_lower_right_corner_x[i - 1];
+        tempBuffer = tempBuffer << (16 - extraBit);
+        for (j = 0; j < 4; j++) {
+            memcpy((char *)&buffer + j, (char *)&tempBuffer + (3 - j), sizeof(char));
+        }
+
+        for (j = 0; j < (2 + extraByte); j++) {
+            for (k = extraBit; k < 8; k++) {
+                *((char *)pBlob + (bit_offset / 8)) |= (*((char *)&buffer + j) & (1 << (7 - k)));
+                bit_offset++;
+
+                if (bit_offset == offset_limit) {
+                    break;
+                }
+            }
+            extraBit = (bit_offset % 8);
+        }
+        buffer     = 0;
+        tempBuffer = 0;
+        extraByte  = 0;
+
+        /* window_lower_right_corner_y: 16bit */
+        offset_limit = bit_offset + 16;
+
+        if (extraBit > 0)
+            extraByte = 1;
+
+        tempBuffer = pHDRDynamicInfo->data.window_lower_right_corner_y[i - 1];
+        tempBuffer = tempBuffer << (16 - extraBit);
+        for (j = 0; j < 4; j++) {
+            memcpy((char *)&buffer + j, (char *)&tempBuffer + (3 - j), sizeof(char));
+        }
+
+        for (j = 0; j < (2 + extraByte); j++) {
+            for (k = extraBit; k < 8; k++) {
+                *((char *)pBlob + (bit_offset / 8)) |= (*((char *)&buffer + j) & (1 << (7 - k)));
+                bit_offset++;
+
+                if (bit_offset == offset_limit) {
+                    break;
+                }
+            }
+            extraBit = (bit_offset % 8);
+        }
+        buffer     = 0;
+        tempBuffer = 0;
+        extraByte  = 0;
+
+        /* center_of_ellipse_x: 16bit */
+        offset_limit = bit_offset + 16;
+
+        if (extraBit > 0)
+            extraByte = 1;
+
+        tempBuffer = pHDRDynamicInfo->data.center_of_ellipse_x[i - 1];
+        tempBuffer = tempBuffer << (16 - extraBit);
+        for (j = 0; j < 4; j++) {
+            memcpy((char *)&buffer + j, (char *)&tempBuffer + (3 - j), sizeof(char));
+        }
+
+        for (j = 0; j < (2 + extraByte); j++) {
+            for (k = extraBit; k < 8; k++) {
+                *((char *)pBlob + (bit_offset / 8)) |= (*((char *)&buffer + j) & (1 << (7 - k)));
+                bit_offset++;
+
+                if (bit_offset == offset_limit) {
+                    break;
+                }
+            }
+            extraBit = (bit_offset % 8);
+        }
+        buffer     = 0;
+        tempBuffer = 0;
+        extraByte  = 0;
+
+        /* center_of_ellipse_y: 16bit */
+        offset_limit = bit_offset + 16;
+
+        if (extraBit > 0)
+            extraByte = 1;
+
+        tempBuffer = pHDRDynamicInfo->data.center_of_ellipse_y[i - 1];
+        tempBuffer = tempBuffer << (16 - extraBit);
+        for (j = 0; j < 4; j++) {
+            memcpy((char *)&buffer + j, (char *)&tempBuffer + (3 - j), sizeof(char));
+        }
+
+        for (j = 0; j < (2 + extraByte); j++) {
+            for (k = extraBit; k < 8; k++) {
+                *((char *)pBlob + (bit_offset / 8)) |= (*((char *)&buffer + j) & (1 << (7 - k)));
+                bit_offset++;
+
+                if (bit_offset == offset_limit) {
+                    break;
+                }
+            }
+            extraBit = (bit_offset % 8);
+        }
+        buffer     = 0;
+        tempBuffer = 0;
+        extraByte  = 0;
+
+        /* rotation_angle: 8bit */
+        offset_limit = bit_offset + 8;
+
+        if (extraBit > 0)
+            extraByte = 1;
+
+        tempBuffer = pHDRDynamicInfo->data.rotation_angle[i - 1];
+        tempBuffer = tempBuffer << (24 - extraBit);
         for (j = 0; j < 4; j++) {
             memcpy((char *)&buffer + j, (char *)&tempBuffer + (3 - j), sizeof(char));
         }
@@ -1245,16 +1182,472 @@
         tempBuffer = 0;
         extraByte  = 0;
 
-        for (i = 0; i < pHDRDynamicInfo->data.tone_mapping.num_bezier_curve_anchors; i++) {
-            /* bezier_curve_anchors: 10bit */
-            if (extraBit > 6)
+        /* semimajor_axis_internal_ellipse: 16bit */
+        offset_limit = bit_offset + 16;
+
+        if (extraBit > 0)
+            extraByte = 1;
+
+        tempBuffer = pHDRDynamicInfo->data.semimajor_axis_internal_ellipse[i - 1];
+        tempBuffer = tempBuffer << (16 - extraBit);
+        for (j = 0; j < 4; j++) {
+            memcpy((char *)&buffer + j, (char *)&tempBuffer + (3 - j), sizeof(char));
+        }
+
+        for (j = 0; j < (2 + extraByte); j++) {
+            for (k = extraBit; k < 8; k++) {
+                *((char *)pBlob + (bit_offset / 8)) |= (*((char *)&buffer + j) & (1 << (7 - k)));
+                bit_offset++;
+
+                if (bit_offset == offset_limit) {
+                    break;
+                }
+            }
+            extraBit = (bit_offset % 8);
+        }
+        buffer     = 0;
+        tempBuffer = 0;
+        extraByte  = 0;
+
+        /* semimajor_axis_external_ellipse: 16bit */
+        offset_limit = bit_offset + 16;
+
+        if (extraBit > 0)
+            extraByte = 1;
+
+        tempBuffer = pHDRDynamicInfo->data.semimajor_axis_external_ellipse[i - 1];
+        tempBuffer = tempBuffer << (16 - extraBit);
+        for (j = 0; j < 4; j++) {
+            memcpy((char *)&buffer + j, (char *)&tempBuffer + (3 - j), sizeof(char));
+        }
+
+        for (j = 0; j < (2 + extraByte); j++) {
+            for (k = extraBit; k < 8; k++) {
+                *((char *)pBlob + (bit_offset / 8)) |= (*((char *)&buffer + j) & (1 << (7 - k)));
+                bit_offset++;
+
+                if (bit_offset == offset_limit) {
+                    break;
+                }
+            }
+            extraBit = (bit_offset % 8);
+        }
+        buffer     = 0;
+        tempBuffer = 0;
+        extraByte  = 0;
+
+        /* semiminor_axis_external_ellipse: 16bit */
+        offset_limit = bit_offset + 16;
+
+        if (extraBit > 0)
+            extraByte = 1;
+
+        tempBuffer = pHDRDynamicInfo->data.semiminor_axis_external_ellipse[i - 1];
+        tempBuffer = tempBuffer << (16 - extraBit);
+        for (j = 0; j < 4; j++) {
+            memcpy((char *)&buffer + j, (char *)&tempBuffer + (3 - j), sizeof(char));
+        }
+
+        for (j = 0; j < (2 + extraByte); j++) {
+            for (k = extraBit; k < 8; k++) {
+                *((char *)pBlob + (bit_offset / 8)) |= (*((char *)&buffer + j) & (1 << (7 - k)));
+                bit_offset++;
+
+                if (bit_offset == offset_limit) {
+                    break;
+                }
+            }
+            extraBit = (bit_offset % 8);
+        }
+        buffer     = 0;
+        tempBuffer = 0;
+        extraByte  = 0;
+
+        /* overlap_process_option: 1bit */
+        if (pHDRDynamicInfo->data.overlap_process_option[i - 1]) {
+            *((char *)pBlob + (bit_offset / 8)) |= (1 << (7 - extraBit));
+        }
+
+        bit_offset += 1;
+        extraBit = (bit_offset % 8);
+    }
+
+    /* targeted_system_display_maximum_luminance: 27bit */
+    offset_limit = bit_offset + 27;
+
+    tempBuffer = pHDRDynamicInfo->data.targeted_system_display_maximum_luminance;
+    tempBuffer = tempBuffer << (5 - extraBit);
+    for (i = 0; i < 4; i++) {
+        memcpy((char *)&buffer + i, (char *)&tempBuffer + (3 - i), sizeof(char));
+    }
+
+    for (i = 0; i < 4; i++) {
+        for (j = extraBit; j < 8; j++) {
+            *((char *)pBlob + (bit_offset / 8)) |= (*((char *)&buffer + i) & (1 << (7 - j)));
+            bit_offset++;
+
+            if (bit_offset == offset_limit)
+                break;
+        }
+        extraBit = (bit_offset % 8);
+    }
+    buffer     = 0;
+    tempBuffer = 0;
+
+    /* targeted_system_display_actual_peak_luminance_flag: 1bit */
+    if (pHDRDynamicInfo->data.targeted_system_display_actual_peak_luminance_flag) {
+        *((char *)pBlob + (bit_offset / 8)) |= (1 << (7 - extraBit));
+    }
+    bit_offset += 1;
+    extraBit = (bit_offset % 8);
+
+    if (pHDRDynamicInfo->data.targeted_system_display_actual_peak_luminance_flag) {
+        /* num_rows_targeted_system_display_actual_peak_luminance: 5bit */
+        offset_limit = bit_offset + 5;
+
+        if (extraBit > 3)
+            extraByte = 1;
+
+        tempBuffer = pHDRDynamicInfo->data.num_rows_targeted_system_display_actual_peak_luminance;
+        tempBuffer = tempBuffer << (27 - extraBit);
+        for (i = 0; i < 4; i++) {
+            memcpy((char *)&buffer + i, (char *)&tempBuffer + (3 - i), sizeof(char));
+        }
+
+        for (i = 0; i < (1 + extraByte); i++) {
+            for (j = extraBit; j < 8; j++) {
+                *((char *)pBlob + (bit_offset / 8)) |= (*((char *)&buffer + i) & (1 << (7 - j)));
+                bit_offset++;
+
+                if (bit_offset == offset_limit) {
+                    break;
+                }
+            }
+            extraBit = (bit_offset % 8);
+        }
+        buffer     = 0;
+        tempBuffer = 0;
+        extraByte  = 0;
+
+        /* num_cols_targeted_system_display_actual_peak_luminance: 5bit */
+        offset_limit = bit_offset + 5;
+
+        if (extraBit > 3)
+            extraByte = 1;
+
+        tempBuffer = pHDRDynamicInfo->data.num_cols_targeted_system_display_actual_peak_luminance;
+        tempBuffer = tempBuffer << (27 - extraBit);
+        for (i = 0; i < 4; i++) {
+            memcpy((char *)&buffer + i, (char *)&tempBuffer + (3 - i), sizeof(char));
+        }
+
+        for (i = 0; i < (1 + extraByte); i++) {
+            for (j = extraBit; j < 8; j++) {
+                *((char *)pBlob + (bit_offset / 8)) |= (*((char *)&buffer + i) & (1 << (7 - j)));
+                bit_offset++;
+
+                if (bit_offset == offset_limit) {
+                    break;
+                }
+            }
+            extraBit = (bit_offset % 8);
+        }
+        buffer     = 0;
+        tempBuffer = 0;
+        extraByte  = 0;
+
+        /* targeted_system_display_actual_peak_luminance[row][col]: 4bit */
+        for (i = 0; i < pHDRDynamicInfo->data.num_rows_targeted_system_display_actual_peak_luminance; i++) {
+            for (j = 0; j < pHDRDynamicInfo->data.num_cols_targeted_system_display_actual_peak_luminance; j++) {
+                offset_limit = bit_offset + 4;
+
+                if (extraBit > 4)
+                    extraByte = 1;
+
+                tempBuffer = pHDRDynamicInfo->data.targeted_system_display_actual_peak_luminance[i][j];
+                tempBuffer = tempBuffer << (28 - extraBit);
+                for (k = 0; k < 4; k++) {
+                    memcpy((char *)&buffer + k, (char *)&tempBuffer + (3 - k), sizeof(char));
+                }
+
+                for (k = 0; k < (1 + extraByte); k++) {
+                    for (l = extraBit; l < 8; l++) {
+                        *((char *)pBlob + (bit_offset / 8)) |= (*((char *)&buffer + k) & (1 << (7 - l)));
+                        bit_offset++;
+
+                        if (bit_offset == offset_limit) {
+                            break;
+                        }
+                    }
+                    extraBit = (bit_offset % 8);
+                }
+                buffer     = 0;
+                tempBuffer = 0;
+                extraByte  = 0;
+            }
+        }
+    }
+
+    for (i = 0; i < pHDRDynamicInfo->data.num_windows; i++) {
+        /* maxscl: 17bit */
+        for (j = 0; j < 3; j++) {
+            offset_limit = bit_offset + 17;
+
+            tempBuffer = pHDRDynamicInfo->data.maxscl[i][j] << (15 - extraBit);
+            for (k = 0; k < 4; k++) {
+                memcpy((char *)&buffer + k, (char *)&tempBuffer + (3 - k), sizeof(char));
+            }
+
+            for (k = 0; k < 3; k++) {
+                for (l = extraBit; l < 8; l++) {
+                    *((char *)pBlob + (bit_offset / 8)) |= (*((char *)&buffer + k) & (1 << (7 - l)));
+                    bit_offset++;
+
+                    if (bit_offset == offset_limit)
+                        break;
+                }
+                extraBit = (bit_offset % 8);
+            }
+            buffer     = 0;
+            tempBuffer = 0;
+        }
+
+        /* average_maxrgb: 17bit */
+        offset_limit = bit_offset + 17;
+
+        tempBuffer = pHDRDynamicInfo->data.average_maxrgb[i] << (15 - extraBit);
+        for (j = 0; j < 4; j++) {
+            memcpy((char *)&buffer + j, (char *)&tempBuffer + (3 - j), sizeof(char));
+        }
+
+        for (j = 0; j < 3; j++) {
+            for (k = extraBit; k < 8; k++) {
+                *((char *)pBlob + (bit_offset / 8)) |= (*((char *)&buffer + j) & (1 << (7 - k)));
+                bit_offset++;
+
+                if (bit_offset == offset_limit)
+                    break;
+            }
+            extraBit = (bit_offset % 8);
+        }
+        buffer     = 0;
+        tempBuffer = 0;
+
+        /* num_distribution_maxrgb_percentiles: 4bit */
+        offset_limit = bit_offset + 4;
+
+        if (extraBit > 4)
+            extraByte = 1;
+
+        tempBuffer = pHDRDynamicInfo->data.num_maxrgb_percentiles[i] << (28 - extraBit);
+        for (j = 0; j < 4; j++) {
+            memcpy((char *)&buffer + j, (char *)&tempBuffer + (3 - j), sizeof(char));
+        }
+
+        for (j = 0; j < (1 + extraByte); j++) {
+            for (k = extraBit; k < 8; k++) {
+                *((char *)pBlob + (bit_offset / 8)) |= (*((char *)&buffer + j) & (1 << (7 - k)));
+                bit_offset++;
+
+                if (bit_offset == offset_limit)
+                    break;
+            }
+            extraBit = (bit_offset % 8);
+        }
+        buffer     = 0;
+        tempBuffer = 0;
+        extraByte  = 0;
+
+        for (j = 0; j < pHDRDynamicInfo->data.num_maxrgb_percentiles[i]; j++) {
+            /* distribution_maxrgb_percentaged: 7bit */
+            offset_limit = bit_offset + 7;
+
+            if (extraBit > 1)
                 extraByte = 1;
 
-            offset_limit = bit_offset + 10;
+            tempBuffer = pHDRDynamicInfo->data.maxrgb_percentages[i][j];
+            tempBuffer = tempBuffer << (25 - extraBit);
+            for (k = 0; k < 4; k++) {
+                memcpy((char *)&buffer + k, (char *)&tempBuffer + (3 - k), sizeof(char));
+            }
 
-            tempBuffer = pHDRDynamicInfo->data.tone_mapping.bezier_curve_anchors[i];
-            tempBuffer = tempBuffer << (22 - extraBit);
+            for (k = 0; k < (1 + extraByte); k++) {
+                for (l = extraBit; l < 8; l++) {
+                    *((char *)pBlob + (bit_offset / 8)) |= (*((char *)&buffer + k) & (1 << (7 - l)));
+                    bit_offset++;
 
+                    if (bit_offset == offset_limit) {
+                        break;
+                    }
+                }
+                extraBit = (bit_offset % 8);
+            }
+            buffer     = 0;
+            tempBuffer = 0;
+            extraByte  = 0;
+
+            /* distribution_maxrgb_percentiles: 17bit */
+            offset_limit = bit_offset + 17;
+
+            tempBuffer = pHDRDynamicInfo->data.maxrgb_percentiles[i][j] << (15 - extraBit);
+            for (k = 0; k < 4; k++) {
+                memcpy((char *)&buffer + k, (char *)&tempBuffer + (3 - k), sizeof(char));
+            }
+
+            for (k = 0; k < 3; k++) {
+                for (l = extraBit; l < 8; l++) {
+                    *((char *)pBlob + (bit_offset / 8)) |= (*((char *)&buffer + k) & (1 << (7 - l)));
+                    bit_offset++;
+
+                    if (bit_offset == offset_limit) {
+                        break;
+                    }
+                }
+                extraBit = (bit_offset % 8);
+            }
+            buffer     = 0;
+            tempBuffer = 0;
+        }
+
+        /* fraction_bright_pixels: 10bit */
+        if (extraBit > 6)
+            extraByte = 1;
+
+        offset_limit = bit_offset + 10;
+
+        tempBuffer = pHDRDynamicInfo->data.fraction_bright_pixels[i];
+        tempBuffer = tempBuffer << (22 - extraBit);
+        for (j = 0; j < 4; j++) {
+            memcpy((char *)&buffer + j, (char *)&tempBuffer + (3 - j), sizeof(char));
+        }
+
+        for (j = 0; j < (2 + extraByte); j++) {
+            for (k = extraBit; k < 8; k++) {
+                *((char *)pBlob + (bit_offset / 8)) |= (*((char *)&buffer + j) & (1 << (7 - k)));
+                bit_offset++;
+
+                if (bit_offset == offset_limit) {
+                    break;
+                }
+            }
+            extraBit = (bit_offset % 8);
+        }
+        buffer     = 0;
+        tempBuffer = 0;
+        extraByte  = 0;
+    }
+
+    /* mastering_display_actual_peak_luminance_flag: 1bit */
+    if (pHDRDynamicInfo->data.mastering_display_actual_peak_luminance_flag) {
+        *((char *)pBlob + (bit_offset / 8)) |= (1 << (7 - extraBit));
+    }
+    bit_offset += 1;
+    extraBit = (bit_offset % 8);
+
+    if (pHDRDynamicInfo->data.mastering_display_actual_peak_luminance_flag) {
+        /* num_rows_mastering_display_actual_peak_luminance: 5bit */
+        offset_limit = bit_offset + 5;
+
+        if (extraBit > 3)
+            extraByte = 1;
+
+        tempBuffer = pHDRDynamicInfo->data.num_rows_mastering_display_actual_peak_luminance;
+        tempBuffer = tempBuffer << (27 - extraBit);
+        for (i = 0; i < 4; i++) {
+            memcpy((char *)&buffer + i, (char *)&tempBuffer + (3 - i), sizeof(char));
+        }
+
+        for (i = 0; i < (1 + extraByte); i++) {
+            for (j = extraBit; j < 8; j++) {
+                *((char *)pBlob + (bit_offset / 8)) |= (*((char *)&buffer + i) & (1 << (7 - j)));
+                bit_offset++;
+
+                if (bit_offset == offset_limit) {
+                    break;
+                }
+            }
+            extraBit = (bit_offset % 8);
+        }
+        buffer     = 0;
+        tempBuffer = 0;
+        extraByte  = 0;
+
+        /* num_cols_mastering_display_actual_peak_luminance: 5bit */
+        offset_limit = bit_offset + 5;
+
+        if (extraBit > 3)
+            extraByte = 1;
+
+        tempBuffer = pHDRDynamicInfo->data.num_cols_mastering_display_actual_peak_luminance;
+        tempBuffer = tempBuffer << (27 - extraBit);
+        for (i = 0; i < 4; i++) {
+            memcpy((char *)&buffer + i, (char *)&tempBuffer + (3 - i), sizeof(char));
+        }
+
+        for (i = 0; i < (1 + extraByte); i++) {
+            for (j = extraBit; j < 8; j++) {
+                *((char *)pBlob + (bit_offset / 8)) |= (*((char *)&buffer + i) & (1 << (7 - j)));
+                bit_offset++;
+
+                if (bit_offset == offset_limit) {
+                    break;
+                }
+            }
+            extraBit = (bit_offset % 8);
+        }
+        buffer     = 0;
+        tempBuffer = 0;
+        extraByte  = 0;
+
+        /* mastering_display_actual_peak_luminance[row][col]: 4bit */
+        for (i = 0; i < pHDRDynamicInfo->data.num_rows_mastering_display_actual_peak_luminance; i++) {
+            for (j = 0; j < pHDRDynamicInfo->data.num_cols_mastering_display_actual_peak_luminance; j++) {
+                offset_limit = bit_offset + 4;
+
+                if (extraBit > 4)
+                    extraByte = 1;
+
+                tempBuffer = pHDRDynamicInfo->data.mastering_display_actual_peak_luminance[i][j];
+                tempBuffer = tempBuffer << (28 - extraBit);
+                for (k = 0; k < 4; k++) {
+                    memcpy((char *)&buffer + k, (char *)&tempBuffer + (3 - k), sizeof(char));
+                }
+
+                for (k = 0; k < (1 + extraByte); k++) {
+                    for (l = extraBit; l < 8; l++) {
+                        *((char *)pBlob + (bit_offset / 8)) |= (*((char *)&buffer + k) & (1 << (7 - l)));
+                        bit_offset++;
+
+                        if (bit_offset == offset_limit) {
+                            break;
+                        }
+                    }
+                    extraBit = (bit_offset % 8);
+                }
+                buffer     = 0;
+                tempBuffer = 0;
+                extraByte  = 0;
+            }
+        }
+    }
+
+    for (i = 0; i < pHDRDynamicInfo->data.num_windows; i++) {
+        /* tone_mapping_flag: 1bit */
+        if (pHDRDynamicInfo->data.tone_mapping.tone_mapping_flag[i]) {
+            *((char *)pBlob + (bit_offset / 8)) |= (1 << (7 - extraBit));
+        }
+        bit_offset += 1;
+        extraBit = (bit_offset % 8);
+
+        if (pHDRDynamicInfo->data.tone_mapping.tone_mapping_flag[i]) {
+            /* knee_point_x: 12bit */
+            if (extraBit > 4)
+                extraByte = 1;
+
+            offset_limit = bit_offset + 12;
+
+            tempBuffer = pHDRDynamicInfo->data.tone_mapping.knee_point_x[i];
+            tempBuffer = tempBuffer << (20 - extraBit);
             for (j = 0; j < 4; j++) {
                 memcpy((char *)&buffer + j, (char *)&tempBuffer + (3 - j), sizeof(char));
             }
@@ -1273,16 +1666,128 @@
             buffer     = 0;
             tempBuffer = 0;
             extraByte  = 0;
+
+            /* knee_point_y: 12bit */
+            if (extraBit > 4)
+                extraByte = 1;
+
+            offset_limit = bit_offset + 12;
+
+            tempBuffer = pHDRDynamicInfo->data.tone_mapping.knee_point_y[i];
+            tempBuffer = tempBuffer << (20 - extraBit);
+            for (j = 0; j < 4; j++) {
+                memcpy((char *)&buffer + j, (char *)&tempBuffer + (3 - j), sizeof(char));
+            }
+
+            for (j = 0; j < (2 + extraByte); j++) {
+                for (k = extraBit; k < 8; k++) {
+                    *((char *)pBlob + (bit_offset / 8)) |= (*((char *)&buffer + j) & (1 << (7 - k)));
+                    bit_offset++;
+
+                    if (bit_offset == offset_limit) {
+                        break;
+                    }
+                }
+                extraBit = (bit_offset % 8);
+            }
+            buffer     = 0;
+            tempBuffer = 0;
+            extraByte  = 0;
+
+            /* num_bezier_curve_anchors: 4bit */
+            if (extraBit > 4)
+                extraByte = 1;
+
+            offset_limit = bit_offset + 4;
+
+            tempBuffer = pHDRDynamicInfo->data.tone_mapping.num_bezier_curve_anchors[i];
+            tempBuffer = tempBuffer << (28 - extraBit);
+            for (j = 0; j < 4; j++) {
+                memcpy((char *)&buffer + j, (char *)&tempBuffer + (3 - j), sizeof(char));
+            }
+
+            for (j = 0; j < (1 + extraByte); j++) {
+                for (k = extraBit; k < 8; k++) {
+                    *((char *)pBlob + (bit_offset / 8)) |= (*((char *)&buffer + j) & (1 << (7 - k)));
+                    bit_offset++;
+
+                    if (bit_offset == offset_limit) {
+                        break;
+                    }
+                }
+                extraBit = (bit_offset % 8);
+            }
+            buffer     = 0;
+            tempBuffer = 0;
+            extraByte  = 0;
+
+            for (j = 0; j < pHDRDynamicInfo->data.tone_mapping.num_bezier_curve_anchors[i]; j++) {
+                /* bezier_curve_anchors: 10bit */
+                if (extraBit > 6)
+                    extraByte = 1;
+
+                offset_limit = bit_offset + 10;
+
+                tempBuffer = pHDRDynamicInfo->data.tone_mapping.bezier_curve_anchors[i][j];
+                tempBuffer = tempBuffer << (22 - extraBit);
+                for (k = 0; k < 4; k++) {
+                    memcpy((char *)&buffer + k, (char *)&tempBuffer + (3 - k), sizeof(char));
+                }
+
+                for (k = 0; k < (2 + extraByte); k++) {
+                    for (l = extraBit; l < 8; l++) {
+                        *((char *)pBlob + (bit_offset / 8)) |= (*((char *)&buffer + k) & (1 << (7 - l)));
+                        bit_offset++;
+
+                        if (bit_offset == offset_limit) {
+                            break;
+                        }
+                    }
+                    extraBit = (bit_offset % 8);
+                }
+                buffer     = 0;
+                tempBuffer = 0;
+                extraByte  = 0;
+            }
+        }
+
+        /* color_saturation_mapping_flag: 1bit */
+        if (pHDRDynamicInfo->data.color_saturation_mapping_flag[i]) {
+            *((char *)pBlob + (bit_offset / 8)) |= (1 << (7 - extraBit));
+        }
+        bit_offset += 1;
+        extraBit = (bit_offset % 8);
+
+        if (pHDRDynamicInfo->data.color_saturation_mapping_flag[i]) {
+            /* color_saturation_weight: 6bit */
+            if (extraBit > 2)
+                extraByte = 1;
+
+            offset_limit = bit_offset + 6;
+
+            tempBuffer = pHDRDynamicInfo->data.color_saturation_weight[i];
+            tempBuffer = tempBuffer << (26 - extraBit);
+            for (j = 0; j < 4; j++) {
+                memcpy((char *)&buffer + j, (char *)&tempBuffer + (3 - j), sizeof(char));
+            }
+
+            for (j = 0; j < (1 + extraByte); j++) {
+                for (k = extraBit; k < 8; k++) {
+                    *((char *)pBlob + (bit_offset / 8)) |= (*((char *)&buffer + j) & (1 << (7 - k)));
+                    bit_offset++;
+
+                    if (bit_offset == offset_limit) {
+                        break;
+                    }
+                }
+                extraBit = (bit_offset % 8);
+            }
+            buffer     = 0;
+            tempBuffer = 0;
+            extraByte  = 0;
         }
     }
 
-    /* color_saturation_mapping_flag: 1bit */
-    bit_offset += 1;
-    extraBit = (bit_offset % 8);
-
-    /* NOTE: This info would not be set because color_saturation_mapping_flag is always 0.
-     * - color_saturation_weight: 6bit */
-
     if(extraBit > 0) {
         size = (bit_offset / 8) + 1;
     } else {