Merge "Include GTS tests covering audio policy use cases in postsubmit." into main
diff --git a/camera/CameraBase.cpp b/camera/CameraBase.cpp
index 2a102d0..6759f3b 100644
--- a/camera/CameraBase.cpp
+++ b/camera/CameraBase.cpp
@@ -180,7 +180,7 @@
         c->mStatus = NO_ERROR;
     } else {
         ALOGW("An error occurred while connecting to camera %d: %s", cameraId,
-                (cs == nullptr) ? "Service not available" : ret.toString8().string());
+                (cs == nullptr) ? "Service not available" : ret.toString8().c_str());
         c.clear();
     }
     return c;
@@ -265,7 +265,7 @@
             &count);
     if (!res.isOk()) {
         ALOGE("Error reading number of cameras: %s",
-                res.toString8().string());
+                res.toString8().c_str());
         count = 0;
     }
     return count;
diff --git a/camera/CameraMetadata.cpp b/camera/CameraMetadata.cpp
index a4ae71b..2e808d1 100644
--- a/camera/CameraMetadata.cpp
+++ b/camera/CameraMetadata.cpp
@@ -289,7 +289,7 @@
         return res;
     }
     // string.size() doesn't count the null termination character.
-    return updateImpl(tag, (const void*)string.string(), string.size() + 1);
+    return updateImpl(tag, (const void*)string.c_str(), string.size() + 1);
 }
 
 status_t CameraMetadata::update(const camera_metadata_ro_entry &entry) {
@@ -809,7 +809,7 @@
     for (size_t i = 0; i < totalSectionCount; ++i) {
 
         const char *str = (i < ANDROID_SECTION_COUNT) ? camera_metadata_section_names[i] :
-                (*vendorSections)[i - ANDROID_SECTION_COUNT].string();
+                (*vendorSections)[i - ANDROID_SECTION_COUNT].c_str();
 
         ALOGV("%s: Trying to match against section '%s'", __FUNCTION__, str);
 
diff --git a/camera/CameraParameters.cpp b/camera/CameraParameters.cpp
index e95c91c..272b113 100644
--- a/camera/CameraParameters.cpp
+++ b/camera/CameraParameters.cpp
@@ -205,7 +205,7 @@
 
 void CameraParameters::unflatten(const String8 &params)
 {
-    const char *a = params.string();
+    const char *a = params.c_str();
     const char *b;
 
     mMap.clear();
@@ -271,7 +271,7 @@
     String8 v = mMap.valueFor(String8(key));
     if (v.length() == 0)
         return 0;
-    return v.string();
+    return v.c_str();
 }
 
 int CameraParameters::getInt(const char *key) const
@@ -463,7 +463,7 @@
         String8 k, v;
         k = mMap.keyAt(i);
         v = mMap.valueAt(i);
-        ALOGD("%s: %s\n", k.string(), v.string());
+        ALOGD("%s: %s\n", k.c_str(), v.c_str());
     }
 }
 
@@ -478,10 +478,10 @@
         String8 k, v;
         k = mMap.keyAt(i);
         v = mMap.valueAt(i);
-        snprintf(buffer, 255, "\t%s: %s\n", k.string(), v.string());
+        snprintf(buffer, 255, "\t%s: %s\n", k.c_str(), v.c_str());
         result.append(buffer);
     }
-    write(fd, result.string(), result.size());
+    write(fd, result.c_str(), result.size());
     return NO_ERROR;
 }
 
diff --git a/camera/CameraParameters2.cpp b/camera/CameraParameters2.cpp
index a1cf355..1ccad08 100644
--- a/camera/CameraParameters2.cpp
+++ b/camera/CameraParameters2.cpp
@@ -52,14 +52,14 @@
             flattened += ";";
     }
 
-    ALOGV("%s: Flattened params = %s", __FUNCTION__, flattened.string());
+    ALOGV("%s: Flattened params = %s", __FUNCTION__, flattened.c_str());
 
     return flattened;
 }
 
 void CameraParameters2::unflatten(const String8 &params)
 {
-    const char *a = params.string();
+    const char *a = params.c_str();
     const char *b;
 
     mMap.clear();
@@ -128,7 +128,7 @@
     if (idx < 0) {
         return NULL;
     } else {
-        return mMap.valueAt(idx).string();
+        return mMap.valueAt(idx).c_str();
     }
 }
 
@@ -305,7 +305,7 @@
 void CameraParameters2::setPreviewFpsRange(int min_fps, int max_fps)
 {
     String8 str = String8::format("%d,%d", min_fps, max_fps);
-    set(CameraParameters::KEY_PREVIEW_FPS_RANGE, str.string());
+    set(CameraParameters::KEY_PREVIEW_FPS_RANGE, str.c_str());
 }
 
 void CameraParameters2::setPreviewFormat(const char *format)
@@ -357,7 +357,7 @@
         String8 k, v;
         k = mMap.keyAt(i);
         v = mMap.valueAt(i);
-        ALOGD("%s: %s\n", k.string(), v.string());
+        ALOGD("%s: %s\n", k.c_str(), v.c_str());
     }
 }
 
@@ -373,10 +373,10 @@
         String8 k, v;
         k = mMap.keyAt(i);
         v = mMap.valueAt(i);
-        snprintf(buffer, 255, "\t%s: %s\n", k.string(), v.string());
+        snprintf(buffer, 255, "\t%s: %s\n", k.c_str(), v.c_str());
         result.append(buffer);
     }
-    write(fd, result.string(), result.size());
+    write(fd, result.c_str(), result.size());
     return NO_ERROR;
 }
 
diff --git a/camera/VendorTagDescriptor.cpp b/camera/VendorTagDescriptor.cpp
index 151b653..ecf8a91 100644
--- a/camera/VendorTagDescriptor.cpp
+++ b/camera/VendorTagDescriptor.cpp
@@ -237,7 +237,7 @@
     if (index < 0) {
         return VENDOR_SECTION_NAME_ERR;
     }
-    return mSections[mTagToSectionMap.valueAt(index)].string();
+    return mSections[mTagToSectionMap.valueAt(index)].c_str();
 }
 
 const char* VendorTagDescriptor::getTagName(uint32_t tag) const {
@@ -245,7 +245,7 @@
     if (index < 0) {
         return VENDOR_TAG_NAME_ERR;
     }
-    return mTagToNameMap.valueAt(index).string();
+    return mTagToNameMap.valueAt(index).c_str();
 }
 
 int VendorTagDescriptor::getTagType(uint32_t tag) const {
@@ -299,13 +299,13 @@
 status_t VendorTagDescriptor::lookupTag(const String8& name, const String8& section, /*out*/uint32_t* tag) const {
     ssize_t index = mReverseMapping.indexOfKey(section);
     if (index < 0) {
-        ALOGE("%s: Section '%s' does not exist.", __FUNCTION__, section.string());
+        ALOGE("%s: Section '%s' does not exist.", __FUNCTION__, section.c_str());
         return BAD_VALUE;
     }
 
     ssize_t nameIndex = mReverseMapping[index]->indexOfKey(name);
     if (nameIndex < 0) {
-        ALOGE("%s: Tag name '%s' does not exist.", __FUNCTION__, name.string());
+        ALOGE("%s: Tag name '%s' does not exist.", __FUNCTION__, name.c_str());
         return BAD_VALUE;
     }
 
@@ -344,7 +344,7 @@
         const char* typeName = (type >= 0 && type < NUM_TYPES) ?
                 camera_metadata_type_names[type] : "UNKNOWN";
         dprintf(fd, "%*s0x%x (%s) with type %d (%s) defined in section %s\n", indentation + 2,
-            "", tag, name.string(), type, typeName, sectionName.string());
+            "", tag, name.c_str(), type, typeName, sectionName.c_str());
     }
 
 }
diff --git a/camera/camera2/OutputConfiguration.cpp b/camera/camera2/OutputConfiguration.cpp
index 33220ce..73b153c 100644
--- a/camera/camera2/OutputConfiguration.cpp
+++ b/camera/camera2/OutputConfiguration.cpp
@@ -249,7 +249,7 @@
     for (auto& surface : surfaceShims) {
         ALOGV("%s: OutputConfiguration: %p, name %s", __FUNCTION__,
                 surface.graphicBufferProducer.get(),
-                toString8(surface.name).string());
+                toString8(surface.name).c_str());
         mGbps.push_back(surface.graphicBufferProducer);
     }
 
diff --git a/camera/include/camera/StringUtils.h b/camera/include/camera/StringUtils.h
index b9dfbfc..547750f 100644
--- a/camera/include/camera/StringUtils.h
+++ b/camera/include/camera/StringUtils.h
@@ -61,12 +61,12 @@
     }
 
     inline std::string toStdString(const String8 &str) {
-        return std::string(str.string());
+        return std::string(str.c_str());
     }
 
     inline std::string toStdString(const String16 &str) {
         std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> convert;
-        return convert.to_bytes(str.string());
+        return convert.to_bytes(str.c_str());
     }
 
     /**
diff --git a/camera/ndk/impl/ACameraDevice.cpp b/camera/ndk/impl/ACameraDevice.cpp
index 8bdb6d4..024ed20 100644
--- a/camera/ndk/impl/ACameraDevice.cpp
+++ b/camera/ndk/impl/ACameraDevice.cpp
@@ -163,7 +163,7 @@
             templateId);
         return ACAMERA_ERROR_INVALID_PARAMETER;
     } else if (!remoteRet.isOk()) {
-        ALOGE("Create capture request failed: %s", remoteRet.toString8().string());
+        ALOGE("Create capture request failed: %s", remoteRet.toString8().c_str());
         return ACAMERA_ERROR_UNKNOWN;
     }
     ACaptureRequest* outReq = new ACaptureRequest();
@@ -317,22 +317,22 @@
         switch (remoteRet.serviceSpecificErrorCode()) {
             case hardware::ICameraService::ERROR_INVALID_OPERATION:
                 ALOGE("Camera device %s invalid operation: %s", getId(),
-                        remoteRet.toString8().string());
+                        remoteRet.toString8().c_str());
                 return ACAMERA_ERROR_INVALID_OPERATION;
                 break;
             case hardware::ICameraService::ERROR_ALREADY_EXISTS:
                 ALOGE("Camera device %s output surface already exists: %s", getId(),
-                        remoteRet.toString8().string());
+                        remoteRet.toString8().c_str());
                 return ACAMERA_ERROR_INVALID_PARAMETER;
                 break;
             case hardware::ICameraService::ERROR_ILLEGAL_ARGUMENT:
                 ALOGE("Camera device %s invalid input argument: %s", getId(),
-                        remoteRet.toString8().string());
+                        remoteRet.toString8().c_str());
                 return ACAMERA_ERROR_INVALID_PARAMETER;
                 break;
             default:
                 ALOGE("Camera device %s failed to add shared output: %s", getId(),
-                        remoteRet.toString8().string());
+                        remoteRet.toString8().c_str());
                 return ACAMERA_ERROR_UNKNOWN;
         }
     }
@@ -546,7 +546,7 @@
             ALOGV("Repeating request is already stopped.");
             return ACAMERA_OK;
         } else if (!remoteRet.isOk()) {
-            ALOGE("Stop repeating request fails in remote: %s", remoteRet.toString8().string());
+            ALOGE("Stop repeating request fails in remote: %s", remoteRet.toString8().c_str());
             return ACAMERA_ERROR_UNKNOWN;
         }
         checkRepeatingSequenceCompleteLocked(repeatingSequenceId, lastFrameNumber);
@@ -598,7 +598,7 @@
     int64_t lastFrameNumber;
     binder::Status remoteRet = mRemote->flush(&lastFrameNumber);
     if (!remoteRet.isOk()) {
-        ALOGE("Abort captures fails in remote: %s", remoteRet.toString8().string());
+        ALOGE("Abort captures fails in remote: %s", remoteRet.toString8().c_str());
         return ACAMERA_ERROR_UNKNOWN;
     }
     if (mRepeatingSequenceId != REQUEST_ID_NONE) {
@@ -622,7 +622,7 @@
 
     binder::Status remoteRet = mRemote->waitUntilIdle();
     if (!remoteRet.isOk()) {
-        ALOGE("Camera device %s waitUntilIdle failed: %s", getId(), remoteRet.toString8().string());
+        ALOGE("Camera device %s waitUntilIdle failed: %s", getId(), remoteRet.toString8().c_str());
         // TODO: define a function to convert status_t -> camera_status_t
         return ACAMERA_ERROR_UNKNOWN;
     }
@@ -732,7 +732,7 @@
 
     binder::Status remoteRet = mRemote->beginConfigure();
     if (!remoteRet.isOk()) {
-        ALOGE("Camera device %s begin configure failed: %s", getId(), remoteRet.toString8().string());
+        ALOGE("Camera device %s begin configure failed: %s", getId(), remoteRet.toString8().c_str());
         return ACAMERA_ERROR_UNKNOWN;
     }
 
@@ -741,7 +741,7 @@
         remoteRet = mRemote->deleteStream(streamId);
         if (!remoteRet.isOk()) {
             ALOGE("Camera device %s failed to remove stream %d: %s", getId(), streamId,
-                    remoteRet.toString8().string());
+                    remoteRet.toString8().c_str());
             return ACAMERA_ERROR_UNKNOWN;
         }
         mConfiguredOutputs.erase(streamId);
@@ -753,7 +753,7 @@
         remoteRet = mRemote->createStream(outputPair.second, &streamId);
         if (!remoteRet.isOk()) {
             ALOGE("Camera device %s failed to create stream: %s", getId(),
-                    remoteRet.toString8().string());
+                    remoteRet.toString8().c_str());
             return ACAMERA_ERROR_UNKNOWN;
         }
         mConfiguredOutputs.insert(std::make_pair(streamId, outputPair));
@@ -768,10 +768,10 @@
             ns2ms(startTimeNs), &offlineStreamIds);
     if (remoteRet.serviceSpecificErrorCode() == hardware::ICameraService::ERROR_ILLEGAL_ARGUMENT) {
         ALOGE("Camera device %s cannnot support app output configuration: %s", getId(),
-                remoteRet.toString8().string());
+                remoteRet.toString8().c_str());
         return ACAMERA_ERROR_STREAM_CONFIGURE_FAIL;
     } else if (!remoteRet.isOk()) {
-        ALOGE("Camera device %s end configure failed: %s", getId(), remoteRet.toString8().string());
+        ALOGE("Camera device %s end configure failed: %s", getId(), remoteRet.toString8().c_str());
         return ACAMERA_ERROR_UNKNOWN;
     }
 
@@ -918,7 +918,7 @@
         if (cbh.mIsLogicalCameraCallback) {
             if (resultExtras.errorPhysicalCameraId.size() > 0) {
                 String8 cameraId = toString8(resultExtras.errorPhysicalCameraId);
-                msg->setString(kFailingPhysicalCameraId, cameraId.string(), cameraId.size());
+                msg->setString(kFailingPhysicalCameraId, cameraId.c_str(), cameraId.size());
             }
             msg->setPointer(kCallbackFpKey, (void*) cbh.mOnLogicalCameraCaptureFailed);
         } else {
diff --git a/camera/ndk/impl/ACameraDevice.h b/camera/ndk/impl/ACameraDevice.h
index 382d6ce..4658d18 100644
--- a/camera/ndk/impl/ACameraDevice.h
+++ b/camera/ndk/impl/ACameraDevice.h
@@ -66,7 +66,7 @@
                   ACameraDevice* wrapper);
     ~CameraDevice();
 
-    inline const char* getId() const { return mCameraId.string(); }
+    inline const char* getId() const { return mCameraId.c_str(); }
 
     camera_status_t createCaptureRequest(
             ACameraDevice_request_template templateId,
diff --git a/camera/ndk/impl/ACameraManager.cpp b/camera/ndk/impl/ACameraManager.cpp
index 299ffc0..5d3b65b 100644
--- a/camera/ndk/impl/ACameraManager.cpp
+++ b/camera/ndk/impl/ACameraManager.cpp
@@ -166,7 +166,7 @@
                 } else {
                     VendorTagDescriptorCache::clearGlobalVendorTagCache();
                     ALOGE("%s: Failed to setup vendor tag cache: %s",
-                            __FUNCTION__, res.toString8().string());
+                            __FUNCTION__, res.toString8().c_str());
                 }
             }
         } else if (ret.serviceSpecificErrorCode() ==
@@ -176,7 +176,7 @@
             VendorTagDescriptor::clearGlobalVendorTagDescriptor();
         } else {
             ALOGE("%s: Failed to get vendor tag descriptors: %s",
-                    __FUNCTION__, ret.toString8().string());
+                    __FUNCTION__, ret.toString8().c_str());
         }
     }
     ALOGE_IF(mCameraService == nullptr, "no CameraService!?");
@@ -707,7 +707,7 @@
                 return ACAMERA_ERROR_INVALID_PARAMETER;
             default:
                 ALOGE("Get camera characteristics from camera service failed: %s",
-                        serviceRet.toString8().string());
+                        serviceRet.toString8().c_str());
                 return ACAMERA_ERROR_UNKNOWN; // should not reach here
         }
     }
@@ -751,7 +751,7 @@
             targetSdkVersion, /*overrideToPortrait*/false, /*out*/&deviceRemote);
 
     if (!serviceRet.isOk()) {
-        ALOGE("%s: connect camera device failed: %s", __FUNCTION__, serviceRet.toString8().string());
+        ALOGE("%s: connect camera device failed: %s", __FUNCTION__, serviceRet.toString8().c_str());
         // Convert serviceRet to camera_status_t
         switch(serviceRet.serviceSpecificErrorCode()) {
             case hardware::ICameraService::ERROR_DISCONNECTED:
diff --git a/camera/ndk/impl/ACameraMetadata.cpp b/camera/ndk/impl/ACameraMetadata.cpp
index 1fd4a86..61c7551 100644
--- a/camera/ndk/impl/ACameraMetadata.cpp
+++ b/camera/ndk/impl/ACameraMetadata.cpp
@@ -142,7 +142,7 @@
         if (ids[i] == '\0') {
             if (start != i) {
                 mStaticPhysicalCameraIdValues.push_back(String8((const char *)ids+start));
-                mStaticPhysicalCameraIds.push_back(mStaticPhysicalCameraIdValues.back().string());
+                mStaticPhysicalCameraIds.push_back(mStaticPhysicalCameraIdValues.back().c_str());
             }
             start = i+1;
         }
diff --git a/cmds/stagefright/stagefright.cpp b/cmds/stagefright/stagefright.cpp
index 2b1f453..989b127 100644
--- a/cmds/stagefright/stagefright.cpp
+++ b/cmds/stagefright/stagefright.cpp
@@ -834,7 +834,7 @@
             case 'd':
             {
                 dumpStream = true;
-                dumpStreamFilename.setTo(optarg);
+                dumpStreamFilename = optarg;
                 break;
             }
 
@@ -842,13 +842,13 @@
             {
                 dumpPCMStream = true;
                 audioOnly = true;
-                dumpStreamFilename.setTo(optarg);
+                dumpStreamFilename = optarg;
                 break;
             }
 
             case 'N':
             {
-                gComponentNameOverride.setTo(optarg);
+                gComponentNameOverride = optarg;
                 break;
             }
 
@@ -886,7 +886,7 @@
             case 'w':
             {
                 gWriteMP4 = true;
-                gWriteMP4Filename.setTo(optarg);
+                gWriteMP4Filename = optarg;
                 break;
             }
 
diff --git a/drm/mediacas/plugins/clearkey/JsonAssetLoader.cpp b/drm/mediacas/plugins/clearkey/JsonAssetLoader.cpp
index ad015bf..a54ae47 100644
--- a/drm/mediacas/plugins/clearkey/JsonAssetLoader.cpp
+++ b/drm/mediacas/plugins/clearkey/JsonAssetLoader.cpp
@@ -128,7 +128,7 @@
             if (nextToken + 1 == mTokens.end())
                 break;
             valueToken = (*(nextToken + 1)).c_str();
-            value->setTo(valueToken);
+            *value = valueToken;
             nextToken++;
             break;
         }
@@ -172,7 +172,7 @@
         pjs = jsonObject.c_str() + mJsmnTokens[j].start;
         if (mJsmnTokens[j].type == JSMN_STRING ||
                 mJsmnTokens[j].type == JSMN_PRIMITIVE) {
-            token.setTo(pjs, mJsmnTokens[j].end - mJsmnTokens[j].start);
+            token = String8(pjs, mJsmnTokens[j].end - mJsmnTokens[j].start);
             tokens->add(token);
             ALOGV("add token: %s", token.c_str());
         }
@@ -221,7 +221,7 @@
     for (int i = 0; i < numTokens; ++i) {
         pjs = jsonAsset.c_str() + mJsmnTokens[i].start;
         if (mJsmnTokens[i].type == JSMN_OBJECT) {
-            token.setTo(pjs, mJsmnTokens[i].end - mJsmnTokens[i].start);
+            token = String8(pjs, mJsmnTokens[i].end - mJsmnTokens[i].start);
             jsonObjects->add(token);
         }
     }
diff --git a/drm/mediadrm/plugins/clearkey/default/JsonWebKey.cpp b/drm/mediadrm/plugins/clearkey/default/JsonWebKey.cpp
index 6f87f9d..a12b1d1 100644
--- a/drm/mediadrm/plugins/clearkey/default/JsonWebKey.cpp
+++ b/drm/mediadrm/plugins/clearkey/default/JsonWebKey.cpp
@@ -160,7 +160,7 @@
             if (nextToken + 1 == mTokens.end())
                 break;
             valueToken = (*(nextToken + 1)).c_str();
-            value->setTo(valueToken);
+            *value = valueToken;
             nextToken++;
             break;
         }
@@ -211,7 +211,7 @@
         pjs = jsonObject.c_str() + mJsmnTokens[j].start;
         if (mJsmnTokens[j].type == JSMN_STRING ||
                 mJsmnTokens[j].type == JSMN_PRIMITIVE) {
-            token.setTo(pjs, mJsmnTokens[j].end - mJsmnTokens[j].start);
+            token = String8(pjs, mJsmnTokens[j].end - mJsmnTokens[j].start);
             tokens->add(token);
         }
     }
@@ -259,7 +259,7 @@
     for (int i = 0; i < numTokens; ++i) {
         pjs = jsonWebKeySet.c_str() + mJsmnTokens[i].start;
         if (mJsmnTokens[i].type == JSMN_OBJECT) {
-            token.setTo(pjs, mJsmnTokens[i].end - mJsmnTokens[i].start);
+            token = String8(pjs, mJsmnTokens[i].end - mJsmnTokens[i].start);
             jsonObjects->add(token);
         }
     }
diff --git a/media/codec2/hal/aidl/Android.bp b/media/codec2/hal/aidl/Android.bp
index 01cd354..3bc7548 100644
--- a/media/codec2/hal/aidl/Android.bp
+++ b/media/codec2/hal/aidl/Android.bp
@@ -12,7 +12,6 @@
     ],
 
     header_libs: [
-        "libcodec2_hal_common",
         "libcodec2_internal", // private
         "libgui_headers",
     ],
@@ -23,6 +22,7 @@
         "libbinder_ndk",
         "libbase",
         "libcodec2",
+        "libcodec2_hal_common",
         "libcodec2_vndk",
         "libcutils",
         "liblog",
@@ -37,6 +37,7 @@
     export_shared_lib_headers: [
         "android.hardware.media.c2-V1-ndk",
         "libcodec2",
+        "libcodec2_hal_common",
     ],
 }
 
diff --git a/media/codec2/hal/common/Android.bp b/media/codec2/hal/common/Android.bp
index e158cd2..f0193d7 100644
--- a/media/codec2/hal/common/Android.bp
+++ b/media/codec2/hal/common/Android.bp
@@ -1,6 +1,6 @@
-cc_library_headers {
+cc_library {
     name: "libcodec2_hal_common",
-    export_include_dirs: ["include/"],
+    double_loadable: true,
     vendor_available: true,
     apex_available: [
         "//apex_available:platform",
@@ -8,4 +8,23 @@
         "com.android.media.swcodec",
     ],
     min_sdk_version: "29",
+
+    srcs: [
+        "BufferTypes.cpp",
+    ],
+
+    export_include_dirs: ["include/"],
+
+    header_libs: [
+        "libcodec2_internal", // private
+        "libgui_headers",
+    ],
+
+    shared_libs: [
+        "libbase",
+        "libcodec2",
+        "libcodec2_vndk",
+        "liblog",
+        "libstagefright_foundation",
+    ],
 }
diff --git a/media/codec2/hal/common/BufferTypes.cpp b/media/codec2/hal/common/BufferTypes.cpp
new file mode 100644
index 0000000..f10a195
--- /dev/null
+++ b/media/codec2/hal/common/BufferTypes.cpp
@@ -0,0 +1,184 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "Codec2-BufferTypes"
+#include <android-base/logging.h>
+
+#include <codec2/common/BufferTypes.h>
+
+#include <C2AllocatorIon.h>
+#include <C2AllocatorGralloc.h>
+#include <C2BlockInternal.h>
+#include <C2Buffer.h>
+#include <C2Component.h>
+#include <C2FenceFactory.h>
+#include <C2PlatformSupport.h>
+#include <C2Work.h>
+
+namespace android {
+
+// C2LinearBlock, vector<C2Param*>, C2Fence -> C2Buffer
+bool CreateLinearBuffer(
+        std::shared_ptr<C2Buffer>* buffer,
+        const std::shared_ptr<C2LinearBlock>& block,
+        const std::vector<C2Param*>& meta,
+        const C2Fence& fence) {
+    // Check the block meta. It should have exactly 1 C2Info:
+    // C2Hal_RangeInfo.
+    if ((meta.size() != 1) || !meta[0]) {
+        LOG(ERROR) << "Invalid C2LinearBlock::meta.";
+        return false;
+    }
+    if (meta[0]->size() != sizeof(C2Hal_RangeInfo)) {
+        LOG(ERROR) << "Invalid range info in C2LinearBlock.";
+        return false;
+    }
+    C2Hal_RangeInfo *rangeInfo =
+            reinterpret_cast<C2Hal_RangeInfo*>(meta[0]);
+
+    // Create C2Buffer from C2LinearBlock.
+    *buffer = C2Buffer::CreateLinearBuffer(block->share(
+            rangeInfo->offset, rangeInfo->length,
+            fence));
+    if (!(*buffer)) {
+        LOG(ERROR) << "CreateLinearBuffer failed.";
+        return false;
+    }
+    return true;
+}
+
+// C2GraphicBlock, vector<C2Param*>, C2Fence -> C2Buffer
+bool CreateGraphicBuffer(
+        std::shared_ptr<C2Buffer>* buffer,
+        const std::shared_ptr<C2GraphicBlock>& block,
+        const std::vector<C2Param*>& meta,
+        const C2Fence& fence) {
+    // Check the block meta. It should have exactly 1 C2Info:
+    // C2Hal_RectInfo.
+    if ((meta.size() != 1) || !meta[0]) {
+        LOG(ERROR) << "Invalid C2GraphicBlock::meta.";
+        return false;
+    }
+    if (meta[0]->size() != sizeof(C2Hal_RectInfo)) {
+        LOG(ERROR) << "Invalid rect info in C2GraphicBlock.";
+        return false;
+    }
+    C2Hal_RectInfo *rectInfo =
+            reinterpret_cast<C2Hal_RectInfo*>(meta[0]);
+
+    // Create C2Buffer from C2GraphicBlock.
+    *buffer = C2Buffer::CreateGraphicBuffer(block->share(
+            C2Rect(rectInfo->width, rectInfo->height).
+            at(rectInfo->left, rectInfo->top),
+            fence));
+    if (!(*buffer)) {
+        LOG(ERROR) << "CreateGraphicBuffer failed.";
+        return false;
+    }
+    return true;
+}
+
+namespace /* unnamed */ {
+
+template <typename BlockProcessor>
+void forEachBlock(C2FrameData& frameData,
+                  BlockProcessor process) {
+    for (const std::shared_ptr<C2Buffer>& buffer : frameData.buffers) {
+        if (buffer) {
+            for (const C2ConstGraphicBlock& block :
+                    buffer->data().graphicBlocks()) {
+                process(block);
+            }
+        }
+    }
+}
+
+template <typename BlockProcessor>
+void forEachBlock(const std::list<std::unique_ptr<C2Work>>& workList,
+                  BlockProcessor process,
+                  bool processInput, bool processOutput) {
+    for (const std::unique_ptr<C2Work>& work : workList) {
+        if (!work) {
+            continue;
+        }
+        if (processInput) {
+            forEachBlock(work->input, process);
+        }
+        if (processOutput) {
+            for (const std::unique_ptr<C2Worklet>& worklet : work->worklets) {
+                if (worklet) {
+                    forEachBlock(worklet->output,
+                                 process);
+                }
+            }
+        }
+    }
+}
+
+} // unnamed namespace
+
+bool BeginTransferBufferQueueBlock(const C2ConstGraphicBlock& block) {
+    std::shared_ptr<_C2BlockPoolData> data =
+            _C2BlockFactory::GetGraphicBlockPoolData(block);
+    if (data && _C2BlockFactory::GetBufferQueueData(data)) {
+        _C2BlockFactory::BeginTransferBlockToClient(data);
+        return true;
+    }
+    return false;
+}
+
+void BeginTransferBufferQueueBlocks(
+        const std::list<std::unique_ptr<C2Work>>& workList,
+        bool processInput, bool processOutput) {
+    forEachBlock(workList, BeginTransferBufferQueueBlock,
+                 processInput, processOutput);
+}
+
+bool EndTransferBufferQueueBlock(
+        const C2ConstGraphicBlock& block,
+        bool transfer) {
+    std::shared_ptr<_C2BlockPoolData> data =
+            _C2BlockFactory::GetGraphicBlockPoolData(block);
+    if (data && _C2BlockFactory::GetBufferQueueData(data)) {
+        _C2BlockFactory::EndTransferBlockToClient(data, transfer);
+        return true;
+    }
+    return false;
+}
+
+void EndTransferBufferQueueBlocks(
+        const std::list<std::unique_ptr<C2Work>>& workList,
+        bool transfer,
+        bool processInput, bool processOutput) {
+    forEachBlock(workList,
+                 std::bind(EndTransferBufferQueueBlock,
+                           std::placeholders::_1, transfer),
+                 processInput, processOutput);
+}
+
+bool DisplayBufferQueueBlock(const C2ConstGraphicBlock& block) {
+    std::shared_ptr<_C2BlockPoolData> data =
+            _C2BlockFactory::GetGraphicBlockPoolData(block);
+    if (data && _C2BlockFactory::GetBufferQueueData(data)) {
+        _C2BlockFactory::DisplayBlockToBufferQueue(data);
+        return true;
+    }
+    return false;
+}
+
+}  // namespace android
+
diff --git a/media/codec2/hal/common/include/codec2/common/BufferPoolSender.h b/media/codec2/hal/common/include/codec2/common/BufferPoolSender.h
new file mode 100644
index 0000000..a9e5942
--- /dev/null
+++ b/media/codec2/hal/common/include/codec2/common/BufferPoolSender.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CODEC2_COMMON_BUFFER_POOL_SENDER_H
+#define CODEC2_COMMON_BUFFER_POOL_SENDER_H
+
+#include <memory>
+
+namespace android {
+
+// Template class to be used in
+// objcpy(std::list<std::unique_ptr<C2Work>> -> WorkBundle).
+template <typename BufferPoolTypes>
+struct BufferPoolSender {
+    // BufferPoolTypes should define the following types:
+    typedef typename BufferPoolTypes::BufferPoolData        BufferPoolData;
+    typedef typename BufferPoolTypes::ResultStatus          ResultStatus;
+    typedef typename BufferPoolTypes::BufferPoolStatus      BufferPoolStatus;
+    typedef typename BufferPoolTypes::BufferStatusMessage   BufferStatusMessage;
+
+    /**
+     * Send bpData and return BufferStatusMessage that can be supplied to
+     * IClientManager::receive() in the receiving process.
+     *
+     * This function will be called from within the function
+     * objcpy(std::list<std::unique_ptr<C2Work>> -> WorkBundle).
+     *
+     * \param[in] bpData BufferPoolData identifying the buffer to send.
+     * \param[out] bpMessage BufferStatusMessage of the transaction. Information
+     *    inside \p bpMessage should be passed to the receiving process by some
+     *    other means so it can call receive() properly.
+     * \return ResultStatus value that determines the success of the operation.
+     *    (See the possible values of ResultStatus in
+     *    hardware/interfaces/media/bufferpool/2.0/types.hal.)
+     */
+    virtual BufferPoolStatus send(
+            const std::shared_ptr<BufferPoolData>& bpData,
+            BufferStatusMessage* bpMessage) = 0;
+
+    virtual ~BufferPoolSender() = default;
+};
+
+}  // namespace android
+
+#endif  // CODEC2_COMMON_BUFFER_POOL_SENDER_H
diff --git a/media/codec2/hal/common/include/codec2/common/BufferTypes.h b/media/codec2/hal/common/include/codec2/common/BufferTypes.h
index 319ba62..8998a6d 100644
--- a/media/codec2/hal/common/include/codec2/common/BufferTypes.h
+++ b/media/codec2/hal/common/include/codec2/common/BufferTypes.h
@@ -14,11 +14,16 @@
  * limitations under the License.
  */
 
-//#define LOG_NDEBUG 0
-#define LOG_TAG "Codec2-types"
+#ifndef CODEC2_COMMON_BUFFER_TYPES_H
+#define CODEC2_COMMON_BUFFER_TYPES_H
+
+#ifndef LOG_TAG
+#define LOG_TAG "Codec2-BufferTypes"
+#endif
 #include <android-base/logging.h>
 
-#include <codec2/hidl/1.0/types.h>
+#include <codec2/common/BufferPoolSender.h>
+#include <codec2/common/ParamTypes.h>
 #include <media/stagefright/foundation/AUtils.h>
 
 #include <C2AllocatorIon.h>
@@ -28,623 +33,50 @@
 #include <C2Component.h>
 #include <C2FenceFactory.h>
 #include <C2Param.h>
-#include <C2ParamInternal.h>
+#include <C2ParamDef.h>
 #include <C2PlatformSupport.h>
 #include <C2Work.h>
-#include <util/C2ParamUtils.h>
 
 #include <algorithm>
 #include <functional>
 #include <iomanip>
-#include <unordered_map>
+#include <map>
 
 namespace android {
-namespace hardware {
-namespace media {
-namespace c2 {
-namespace V1_0 {
-namespace utils {
 
-using ::android::hardware::Return;
-using ::android::hardware::media::bufferpool::BufferPoolData;
-using ::android::hardware::media::bufferpool::V2_0::BufferStatusMessage;
-using ::android::hardware::media::bufferpool::V2_0::ResultStatus;
-using ::android::hardware::media::bufferpool::V2_0::implementation::
-        ClientManager;
-using ::android::hardware::media::bufferpool::V2_0::implementation::
-        TransactionId;
-
-const char* asString(Status status, const char* def) {
-    return asString(static_cast<c2_status_t>(status), def);
-}
-
-namespace /* unnamed */ {
-
-template <typename EnumClass>
-typename std::underlying_type<EnumClass>::type underlying_value(
-        EnumClass x) {
-    return static_cast<typename std::underlying_type<EnumClass>::type>(x);
-}
-
-template <typename Common, typename DstVector, typename SrcVector>
-void copyVector(DstVector* d, const SrcVector& s) {
-    static_assert(sizeof(Common) == sizeof(decltype((*d)[0])),
-            "DstVector's component size does not match Common");
-    static_assert(sizeof(Common) == sizeof(decltype(s[0])),
-            "SrcVector's component size does not match Common");
-    d->resize(s.size());
-    std::copy(
-            reinterpret_cast<const Common*>(&s[0]),
-            reinterpret_cast<const Common*>(&s[0] + s.size()),
-            reinterpret_cast<Common*>(&(*d)[0]));
-}
-
-// C2ParamField -> ParamField
-bool objcpy(ParamField *d, const C2ParamField &s) {
-    d->index = static_cast<ParamIndex>(_C2ParamInspector::GetIndex(s));
-    d->fieldId.offset = static_cast<uint32_t>(_C2ParamInspector::GetOffset(s));
-    d->fieldId.size = static_cast<uint32_t>(_C2ParamInspector::GetSize(s));
-    return true;
-}
-
-struct C2ParamFieldBuilder : public C2ParamField {
-    C2ParamFieldBuilder() : C2ParamField(
-            static_cast<C2Param::Index>(static_cast<uint32_t>(0)), 0, 0) {
-    }
-    // ParamField -> C2ParamField
-    C2ParamFieldBuilder(const ParamField& s) : C2ParamField(
-            static_cast<C2Param::Index>(static_cast<uint32_t>(s.index)),
-            static_cast<uint32_t>(s.fieldId.offset),
-            static_cast<uint32_t>(s.fieldId.size)) {
-    }
+// Types of metadata for Blocks.
+struct C2Hal_Range {
+    uint32_t offset;
+    uint32_t length; // Do not use "size" because the name collides with C2Info::size().
 };
+typedef C2GlobalParam<C2Info, C2Hal_Range, 0> C2Hal_RangeInfo;
 
-// C2WorkOrdinalStruct -> WorkOrdinal
-bool objcpy(WorkOrdinal *d, const C2WorkOrdinalStruct &s) {
-    d->frameIndex = static_cast<uint64_t>(s.frameIndex.peeku());
-    d->timestampUs = static_cast<uint64_t>(s.timestamp.peeku());
-    d->customOrdinal = static_cast<uint64_t>(s.customOrdinal.peeku());
-    return true;
-}
+struct C2Hal_Rect {
+    uint32_t left;
+    uint32_t top;
+    uint32_t width;
+    uint32_t height;
+};
+typedef C2GlobalParam<C2Info, C2Hal_Rect, 1> C2Hal_RectInfo;
 
-// WorkOrdinal -> C2WorkOrdinalStruct
-bool objcpy(C2WorkOrdinalStruct *d, const WorkOrdinal &s) {
-    d->frameIndex = c2_cntr64_t(s.frameIndex);
-    d->timestamp = c2_cntr64_t(s.timestampUs);
-    d->customOrdinal = c2_cntr64_t(s.customOrdinal);
-    return true;
-}
+// Note: The handle is not cloned.
+template <typename BaseBlock>
+void SetHandle(BaseBlock *baseBlock, const C2Handle *handle);
 
-// C2FieldSupportedValues::range's type -> ValueRange
-bool objcpy(
-        ValueRange* d,
-        const decltype(C2FieldSupportedValues::range)& s) {
-    d->min = static_cast<PrimitiveValue>(s.min.u64);
-    d->max = static_cast<PrimitiveValue>(s.max.u64);
-    d->step = static_cast<PrimitiveValue>(s.step.u64);
-    d->num = static_cast<PrimitiveValue>(s.num.u64);
-    d->denom = static_cast<PrimitiveValue>(s.denom.u64);
-    return true;
-}
+template <typename BufferPoolTypes, typename BaseBlock>
+void SetPooledBlock(
+        BaseBlock *baseBlock,
+        const typename BufferPoolTypes::BufferStatusMessage &pooledBlock);
 
-// C2FieldSupportedValues -> FieldSupportedValues
-bool objcpy(FieldSupportedValues *d, const C2FieldSupportedValues &s) {
-    switch (s.type) {
-    case C2FieldSupportedValues::EMPTY: {
-            d->empty(::android::hidl::safe_union::V1_0::Monostate{});
-            break;
-        }
-    case C2FieldSupportedValues::RANGE: {
-            ValueRange range{};
-            if (!objcpy(&range, s.range)) {
-                LOG(ERROR) << "Invalid C2FieldSupportedValues::range.";
-                d->range(range);
-                return false;
-            }
-            d->range(range);
-            break;
-        }
-    case C2FieldSupportedValues::VALUES: {
-            hidl_vec<PrimitiveValue> values;
-            copyVector<uint64_t>(&values, s.values);
-            d->values(values);
-            break;
-        }
-    case C2FieldSupportedValues::FLAGS: {
-            hidl_vec<PrimitiveValue> flags;
-            copyVector<uint64_t>(&flags, s.values);
-            d->flags(flags);
-            break;
-        }
-    default:
-        LOG(DEBUG) << "Unrecognized C2FieldSupportedValues::type_t "
-                   << "with underlying value " << underlying_value(s.type)
-                   << ".";
-        return false;
-    }
-    return true;
-}
+template <typename BufferPoolTypes>
+bool GetBufferPoolData(
+        const std::shared_ptr<const _C2BlockPoolData>& blockPoolData,
+        std::shared_ptr<typename BufferPoolTypes::BufferPoolData> *bpData);
 
-// ValueRange -> C2FieldSupportedValues::range's type
-bool objcpy(
-        decltype(C2FieldSupportedValues::range)* d,
-        const ValueRange& s) {
-    d->min.u64 = static_cast<uint64_t>(s.min);
-    d->max.u64 = static_cast<uint64_t>(s.max);
-    d->step.u64 = static_cast<uint64_t>(s.step);
-    d->num.u64 = static_cast<uint64_t>(s.num);
-    d->denom.u64 = static_cast<uint64_t>(s.denom);
-    return true;
-}
-
-// FieldSupportedValues -> C2FieldSupportedValues
-bool objcpy(C2FieldSupportedValues *d, const FieldSupportedValues &s) {
-    switch (s.getDiscriminator()) {
-    case FieldSupportedValues::hidl_discriminator::empty: {
-            d->type = C2FieldSupportedValues::EMPTY;
-            break;
-        }
-    case FieldSupportedValues::hidl_discriminator::range: {
-            d->type = C2FieldSupportedValues::RANGE;
-            if (!objcpy(&d->range, s.range())) {
-                LOG(ERROR) << "Invalid FieldSupportedValues::range.";
-                return false;
-            }
-            d->values.resize(0);
-            break;
-        }
-    case FieldSupportedValues::hidl_discriminator::values: {
-            d->type = C2FieldSupportedValues::VALUES;
-            copyVector<uint64_t>(&d->values, s.values());
-            break;
-        }
-    case FieldSupportedValues::hidl_discriminator::flags: {
-            d->type = C2FieldSupportedValues::FLAGS;
-            copyVector<uint64_t>(&d->values, s.flags());
-            break;
-        }
-    default:
-        LOG(WARNING) << "Unrecognized FieldSupportedValues::getDiscriminator()";
-        return false;
-    }
-    return true;
-}
-
-} // unnamed namespace
-
-// C2FieldSupportedValuesQuery -> FieldSupportedValuesQuery
-bool objcpy(
-        FieldSupportedValuesQuery* d,
-        const C2FieldSupportedValuesQuery& s) {
-    if (!objcpy(&d->field, s.field())) {
-        LOG(ERROR) << "Invalid C2FieldSupportedValuesQuery::field.";
-        return false;
-    }
-    switch (s.type()) {
-    case C2FieldSupportedValuesQuery::POSSIBLE:
-        d->type = FieldSupportedValuesQuery::Type::POSSIBLE;
-        break;
-    case C2FieldSupportedValuesQuery::CURRENT:
-        d->type = FieldSupportedValuesQuery::Type::CURRENT;
-        break;
-    default:
-        LOG(DEBUG) << "Unrecognized C2FieldSupportedValuesQuery::type_t "
-                   << "with underlying value " << underlying_value(s.type())
-                   << ".";
-        d->type = static_cast<FieldSupportedValuesQuery::Type>(s.type());
-    }
-    return true;
-}
-
-// FieldSupportedValuesQuery -> C2FieldSupportedValuesQuery
-bool objcpy(
-        C2FieldSupportedValuesQuery* d,
-        const FieldSupportedValuesQuery& s) {
-    C2FieldSupportedValuesQuery::type_t dType;
-    switch (s.type) {
-    case FieldSupportedValuesQuery::Type::POSSIBLE:
-        dType = C2FieldSupportedValuesQuery::POSSIBLE;
-        break;
-    case FieldSupportedValuesQuery::Type::CURRENT:
-        dType = C2FieldSupportedValuesQuery::CURRENT;
-        break;
-    default:
-        LOG(DEBUG) << "Unrecognized FieldSupportedValuesQuery::Type "
-                   << "with underlying value " << underlying_value(s.type)
-                   << ".";
-        dType = static_cast<C2FieldSupportedValuesQuery::type_t>(s.type);
-    }
-    *d = C2FieldSupportedValuesQuery(C2ParamFieldBuilder(s.field), dType);
-    return true;
-}
-
-// C2FieldSupportedValuesQuery -> FieldSupportedValuesQueryResult
-bool objcpy(
-        FieldSupportedValuesQueryResult* d,
-        const C2FieldSupportedValuesQuery& s) {
-    d->status = static_cast<Status>(s.status);
-    return objcpy(&d->values, s.values);
-}
-
-// FieldSupportedValuesQuery, FieldSupportedValuesQueryResult ->
-// C2FieldSupportedValuesQuery
-bool objcpy(
-        C2FieldSupportedValuesQuery* d,
-        const FieldSupportedValuesQuery& sq,
-        const FieldSupportedValuesQueryResult& sr) {
-    if (!objcpy(d, sq)) {
-        LOG(ERROR) << "Invalid FieldSupportedValuesQuery.";
-        return false;
-    }
-    d->status = static_cast<c2_status_t>(sr.status);
-    if (!objcpy(&d->values, sr.values)) {
-        LOG(ERROR) << "Invalid FieldSupportedValuesQueryResult::values.";
-        return false;
-    }
-    return true;
-}
-
-// C2Component::Traits -> IComponentStore::ComponentTraits
-bool objcpy(
-        IComponentStore::ComponentTraits *d,
-        const C2Component::Traits &s) {
-    d->name = s.name;
-
-    switch (s.domain) {
-    case C2Component::DOMAIN_VIDEO:
-        d->domain = IComponentStore::ComponentTraits::Domain::VIDEO;
-        break;
-    case C2Component::DOMAIN_AUDIO:
-        d->domain = IComponentStore::ComponentTraits::Domain::AUDIO;
-        break;
-    case C2Component::DOMAIN_IMAGE:
-        d->domain = IComponentStore::ComponentTraits::Domain::IMAGE;
-        break;
-    case C2Component::DOMAIN_OTHER:
-        d->domain = IComponentStore::ComponentTraits::Domain::OTHER;
-        break;
-    default:
-        LOG(DEBUG) << "Unrecognized C2Component::domain_t "
-                   << "with underlying value " << underlying_value(s.domain)
-                   << ".";
-        d->domain = static_cast<IComponentStore::ComponentTraits::Domain>(
-                s.domain);
-    }
-
-    switch (s.kind) {
-    case C2Component::KIND_DECODER:
-        d->kind = IComponentStore::ComponentTraits::Kind::DECODER;
-        break;
-    case C2Component::KIND_ENCODER:
-        d->kind = IComponentStore::ComponentTraits::Kind::ENCODER;
-        break;
-    case C2Component::KIND_OTHER:
-        d->kind = IComponentStore::ComponentTraits::Kind::OTHER;
-        break;
-    default:
-        LOG(DEBUG) << "Unrecognized C2Component::kind_t "
-                   << "with underlying value " << underlying_value(s.kind)
-                   << ".";
-        d->kind = static_cast<IComponentStore::ComponentTraits::Kind>(
-                s.kind);
-    }
-
-    d->rank = static_cast<uint32_t>(s.rank);
-
-    d->mediaType = s.mediaType;
-
-    d->aliases.resize(s.aliases.size());
-    for (size_t ix = s.aliases.size(); ix > 0; ) {
-        --ix;
-        d->aliases[ix] = s.aliases[ix];
-    }
-    return true;
-}
-
-// ComponentTraits -> C2Component::Traits, std::unique_ptr<std::vector<std::string>>
-bool objcpy(
-        C2Component::Traits* d,
-        const IComponentStore::ComponentTraits& s) {
-    d->name = s.name.c_str();
-
-    switch (s.domain) {
-    case IComponentStore::ComponentTraits::Domain::VIDEO:
-        d->domain = C2Component::DOMAIN_VIDEO;
-        break;
-    case IComponentStore::ComponentTraits::Domain::AUDIO:
-        d->domain = C2Component::DOMAIN_AUDIO;
-        break;
-    case IComponentStore::ComponentTraits::Domain::IMAGE:
-        d->domain = C2Component::DOMAIN_IMAGE;
-        break;
-    case IComponentStore::ComponentTraits::Domain::OTHER:
-        d->domain = C2Component::DOMAIN_OTHER;
-        break;
-    default:
-        LOG(DEBUG) << "Unrecognized ComponentTraits::Domain "
-                   << "with underlying value " << underlying_value(s.domain)
-                   << ".";
-        d->domain = static_cast<C2Component::domain_t>(s.domain);
-    }
-
-    switch (s.kind) {
-    case IComponentStore::ComponentTraits::Kind::DECODER:
-        d->kind = C2Component::KIND_DECODER;
-        break;
-    case IComponentStore::ComponentTraits::Kind::ENCODER:
-        d->kind = C2Component::KIND_ENCODER;
-        break;
-    case IComponentStore::ComponentTraits::Kind::OTHER:
-        d->kind = C2Component::KIND_OTHER;
-        break;
-    default:
-        LOG(DEBUG) << "Unrecognized ComponentTraits::Kind "
-                   << "with underlying value " << underlying_value(s.kind)
-                   << ".";
-        d->kind = static_cast<C2Component::kind_t>(s.kind);
-    }
-
-    d->rank = static_cast<C2Component::rank_t>(s.rank);
-    d->mediaType = s.mediaType.c_str();
-    d->aliases.resize(s.aliases.size());
-    for (size_t i = 0; i < s.aliases.size(); ++i) {
-        d->aliases[i] = s.aliases[i];
-    }
-    return true;
-}
-
-namespace /* unnamed */ {
-
-// C2ParamFieldValues -> ParamFieldValues
-bool objcpy(ParamFieldValues *d, const C2ParamFieldValues &s) {
-    if (!objcpy(&d->paramOrField, s.paramOrField)) {
-        LOG(ERROR) << "Invalid C2ParamFieldValues::paramOrField.";
-        return false;
-    }
-    if (s.values) {
-        d->values.resize(1);
-        if (!objcpy(&d->values[0], *s.values)) {
-            LOG(ERROR) << "Invalid C2ParamFieldValues::values.";
-            return false;
-        }
-        return true;
-    }
-    d->values.resize(0);
-    return true;
-}
-
-// ParamFieldValues -> C2ParamFieldValues
-bool objcpy(C2ParamFieldValues *d, const ParamFieldValues &s) {
-    d->paramOrField = C2ParamFieldBuilder(s.paramOrField);
-    if (s.values.size() == 1) {
-        d->values = std::make_unique<C2FieldSupportedValues>();
-        if (!objcpy(d->values.get(), s.values[0])) {
-            LOG(ERROR) << "Invalid ParamFieldValues::values.";
-            return false;
-        }
-        return true;
-    } else if (s.values.size() == 0) {
-        d->values.reset();
-        return true;
-    }
-    LOG(ERROR) << "Invalid ParamFieldValues: "
-                  "Two or more FieldSupportedValues objects exist in "
-                  "ParamFieldValues. "
-                  "Only zero or one is allowed.";
-    return false;
-}
-
-} // unnamed namespace
-
-// C2SettingResult -> SettingResult
-bool objcpy(SettingResult *d, const C2SettingResult &s) {
-    switch (s.failure) {
-    case C2SettingResult::BAD_TYPE:
-        d->failure = SettingResult::Failure::BAD_TYPE;
-        break;
-    case C2SettingResult::BAD_PORT:
-        d->failure = SettingResult::Failure::BAD_PORT;
-        break;
-    case C2SettingResult::BAD_INDEX:
-        d->failure = SettingResult::Failure::BAD_INDEX;
-        break;
-    case C2SettingResult::READ_ONLY:
-        d->failure = SettingResult::Failure::READ_ONLY;
-        break;
-    case C2SettingResult::MISMATCH:
-        d->failure = SettingResult::Failure::MISMATCH;
-        break;
-    case C2SettingResult::BAD_VALUE:
-        d->failure = SettingResult::Failure::BAD_VALUE;
-        break;
-    case C2SettingResult::CONFLICT:
-        d->failure = SettingResult::Failure::CONFLICT;
-        break;
-    case C2SettingResult::UNSUPPORTED:
-        d->failure = SettingResult::Failure::UNSUPPORTED;
-        break;
-    case C2SettingResult::INFO_BAD_VALUE:
-        d->failure = SettingResult::Failure::INFO_BAD_VALUE;
-        break;
-    case C2SettingResult::INFO_CONFLICT:
-        d->failure = SettingResult::Failure::INFO_CONFLICT;
-        break;
-    default:
-        LOG(DEBUG) << "Unrecognized C2SettingResult::Failure "
-                   << "with underlying value " << underlying_value(s.failure)
-                   << ".";
-        d->failure = static_cast<SettingResult::Failure>(s.failure);
-    }
-    if (!objcpy(&d->field, s.field)) {
-        LOG(ERROR) << "Invalid C2SettingResult::field.";
-        return false;
-    }
-    d->conflicts.resize(s.conflicts.size());
-    size_t i = 0;
-    for (const C2ParamFieldValues& sConflict : s.conflicts) {
-        ParamFieldValues &dConflict = d->conflicts[i++];
-        if (!objcpy(&dConflict, sConflict)) {
-            LOG(ERROR) << "Invalid C2SettingResult::conflicts["
-                       << i - 1 << "].";
-            return false;
-        }
-    }
-    return true;
-}
-
-// SettingResult -> std::unique_ptr<C2SettingResult>
-bool objcpy(std::unique_ptr<C2SettingResult> *d, const SettingResult &s) {
-    *d = std::unique_ptr<C2SettingResult>(new C2SettingResult {
-            .field = C2ParamFieldValues(C2ParamFieldBuilder()) });
-    if (!*d) {
-        LOG(ERROR) << "No memory for C2SettingResult.";
-        return false;
-    }
-
-    // failure
-    switch (s.failure) {
-    case SettingResult::Failure::BAD_TYPE:
-        (*d)->failure = C2SettingResult::BAD_TYPE;
-        break;
-    case SettingResult::Failure::BAD_PORT:
-        (*d)->failure = C2SettingResult::BAD_PORT;
-        break;
-    case SettingResult::Failure::BAD_INDEX:
-        (*d)->failure = C2SettingResult::BAD_INDEX;
-        break;
-    case SettingResult::Failure::READ_ONLY:
-        (*d)->failure = C2SettingResult::READ_ONLY;
-        break;
-    case SettingResult::Failure::MISMATCH:
-        (*d)->failure = C2SettingResult::MISMATCH;
-        break;
-    case SettingResult::Failure::BAD_VALUE:
-        (*d)->failure = C2SettingResult::BAD_VALUE;
-        break;
-    case SettingResult::Failure::CONFLICT:
-        (*d)->failure = C2SettingResult::CONFLICT;
-        break;
-    case SettingResult::Failure::UNSUPPORTED:
-        (*d)->failure = C2SettingResult::UNSUPPORTED;
-        break;
-    case SettingResult::Failure::INFO_BAD_VALUE:
-        (*d)->failure = C2SettingResult::INFO_BAD_VALUE;
-        break;
-    case SettingResult::Failure::INFO_CONFLICT:
-        (*d)->failure = C2SettingResult::INFO_CONFLICT;
-        break;
-    default:
-        LOG(DEBUG) << "Unrecognized SettingResult::Failure "
-                   << "with underlying value " << underlying_value(s.failure)
-                   << ".";
-        (*d)->failure = static_cast<C2SettingResult::Failure>(s.failure);
-    }
-
-    // field
-    if (!objcpy(&(*d)->field, s.field)) {
-        LOG(ERROR) << "Invalid SettingResult::field.";
-        return false;
-    }
-
-    // conflicts
-    (*d)->conflicts.clear();
-    (*d)->conflicts.reserve(s.conflicts.size());
-    for (const ParamFieldValues& sConflict : s.conflicts) {
-        (*d)->conflicts.emplace_back(
-                C2ParamFieldValues{ C2ParamFieldBuilder(), nullptr });
-        if (!objcpy(&(*d)->conflicts.back(), sConflict)) {
-            LOG(ERROR) << "Invalid SettingResult::conflicts.";
-            return false;
-        }
-    }
-    return true;
-}
-
-// C2ParamDescriptor -> ParamDescriptor
-bool objcpy(ParamDescriptor *d, const C2ParamDescriptor &s) {
-    d->index = static_cast<ParamIndex>(s.index());
-    d->attrib = static_cast<hidl_bitfield<ParamDescriptor::Attrib>>(
-            _C2ParamInspector::GetAttrib(s));
-    d->name = s.name();
-    copyVector<uint32_t>(&d->dependencies, s.dependencies());
-    return true;
-}
-
-// ParamDescriptor -> C2ParamDescriptor
-bool objcpy(std::shared_ptr<C2ParamDescriptor> *d, const ParamDescriptor &s) {
-    std::vector<C2Param::Index> dDependencies;
-    dDependencies.reserve(s.dependencies.size());
-    for (const ParamIndex& sDependency : s.dependencies) {
-        dDependencies.emplace_back(static_cast<uint32_t>(sDependency));
-    }
-    *d = std::make_shared<C2ParamDescriptor>(
-            C2Param::Index(static_cast<uint32_t>(s.index)),
-            static_cast<C2ParamDescriptor::attrib_t>(s.attrib),
-            C2String(s.name.c_str()),
-            std::move(dDependencies));
-    return true;
-}
-
-// C2StructDescriptor -> StructDescriptor
-bool objcpy(StructDescriptor *d, const C2StructDescriptor &s) {
-    d->type = static_cast<ParamIndex>(s.coreIndex().coreIndex());
-    d->fields.resize(s.numFields());
-    size_t i = 0;
-    for (const auto& sField : s) {
-        FieldDescriptor& dField = d->fields[i++];
-        dField.fieldId.offset = static_cast<uint32_t>(
-                _C2ParamInspector::GetOffset(sField));
-        dField.fieldId.size = static_cast<uint32_t>(
-                _C2ParamInspector::GetSize(sField));
-        dField.type = static_cast<hidl_bitfield<FieldDescriptor::Type>>(
-                sField.type());
-        dField.extent = static_cast<uint32_t>(sField.extent());
-        dField.name = static_cast<hidl_string>(sField.name());
-        const auto& sNamedValues = sField.namedValues();
-        dField.namedValues.resize(sNamedValues.size());
-        size_t j = 0;
-        for (const auto& sNamedValue : sNamedValues) {
-            FieldDescriptor::NamedValue& dNamedValue = dField.namedValues[j++];
-            dNamedValue.name = static_cast<hidl_string>(sNamedValue.first);
-            dNamedValue.value = static_cast<PrimitiveValue>(
-                    sNamedValue.second.u64);
-        }
-    }
-    return true;
-}
-
-// StructDescriptor -> C2StructDescriptor
-bool objcpy(std::unique_ptr<C2StructDescriptor> *d, const StructDescriptor &s) {
-    C2Param::CoreIndex dIndex = C2Param::CoreIndex(static_cast<uint32_t>(s.type));
-    std::vector<C2FieldDescriptor> dFields;
-    dFields.reserve(s.fields.size());
-    for (const auto &sField : s.fields) {
-        C2FieldDescriptor dField = {
-            static_cast<uint32_t>(sField.type),
-            sField.extent,
-            sField.name,
-            sField.fieldId.offset,
-            sField.fieldId.size };
-        C2FieldDescriptor::NamedValuesType namedValues;
-        namedValues.reserve(sField.namedValues.size());
-        for (const auto& sNamedValue : sField.namedValues) {
-            namedValues.emplace_back(
-                sNamedValue.name,
-                C2Value::Primitive(static_cast<uint64_t>(sNamedValue.value)));
-        }
-        _C2ParamInspector::AddNamedValues(dField, std::move(namedValues));
-        dFields.emplace_back(dField);
-    }
-    *d = std::make_unique<C2StructDescriptor>(
-            _C2ParamInspector::CreateStructDescriptor(dIndex, std::move(dFields)));
-    return true;
-}
-
-namespace /* unnamed */ {
-
-// Find or add a hidl BaseBlock object from a given C2Handle* to a list and an
+// Find or add a HAL BaseBlock object from a given C2Handle* to a list and an
 // associated map.
 // Note: The handle is not cloned.
+template <typename BaseBlock>
 bool _addBaseBlock(
         uint32_t* index,
         const C2Handle* handle,
@@ -663,20 +95,18 @@
         baseBlocks->emplace_back();
 
         BaseBlock &dBaseBlock = baseBlocks->back();
-        // This does not clone the handle.
-        dBaseBlock.nativeBlock(
-                reinterpret_cast<const native_handle_t*>(handle));
-
+        SetHandle(&dBaseBlock, handle);
     }
     return true;
 }
 
 // Find or add a hidl BaseBlock object from a given BufferPoolData to a list and
 // an associated map.
+template <typename BufferPoolTypes, typename BaseBlock>
 bool _addBaseBlock(
         uint32_t* index,
-        const std::shared_ptr<BufferPoolData> bpData,
-        BufferPoolSender* bufferPoolSender,
+        const std::shared_ptr<typename BufferPoolTypes::BufferPoolData> &bpData,
+        BufferPoolSender<BufferPoolTypes>* bufferPoolSender,
         std::list<BaseBlock>* baseBlocks,
         std::map<const void*, uint32_t>* baseBlockIndices) {
     if (!bpData) {
@@ -694,28 +124,28 @@
         BaseBlock &dBaseBlock = baseBlocks->back();
 
         if (bufferPoolSender) {
-            BufferStatusMessage pooledBlock;
-            ResultStatus bpStatus = bufferPoolSender->send(
-                    bpData,
-                    &pooledBlock);
+            typename BufferPoolTypes::BufferStatusMessage pooledBlock;
+            typename BufferPoolTypes::BufferPoolStatus bpStatus =
+                bufferPoolSender->send(bpData, &pooledBlock);
 
-            if (bpStatus != ResultStatus::OK) {
+            if (bpStatus != BufferPoolTypes::ResultStatus::OK) {
                 LOG(ERROR) << "Failed to send buffer with BufferPool. Error: "
                            << static_cast<int32_t>(bpStatus)
                            << ".";
                 return false;
             }
-            dBaseBlock.pooledBlock(pooledBlock);
+            SetPooledBlock<BufferPoolTypes>(&dBaseBlock, pooledBlock);
         }
     }
     return true;
 }
 
+template <typename BufferPoolTypes, typename BaseBlock>
 bool addBaseBlock(
         uint32_t* index,
         const C2Handle* handle,
         const std::shared_ptr<const _C2BlockPoolData>& blockPoolData,
-        BufferPoolSender* bufferPoolSender,
+        BufferPoolSender<BufferPoolTypes>* bufferPoolSender,
         std::list<BaseBlock>* baseBlocks,
         std::map<const void*, uint32_t>* baseBlockIndices) {
     if (!blockPoolData) {
@@ -727,9 +157,8 @@
     switch (blockPoolData->getType()) {
     case _C2BlockPoolData::TYPE_BUFFERPOOL: {
             // BufferPoolData
-            std::shared_ptr<BufferPoolData> bpData;
-            if (!_C2BlockFactory::GetBufferPoolData(blockPoolData, &bpData)
-                    || !bpData) {
+            std::shared_ptr<typename BufferPoolTypes::BufferPoolData> bpData;
+            if (!GetBufferPoolData<BufferPoolTypes>(blockPoolData, &bpData) || !bpData) {
                 LOG(ERROR) << "BufferPoolData unavailable in a block.";
                 return false;
             }
@@ -756,10 +185,11 @@
     }
 }
 
-// C2Fence -> hidl_handle
+// C2Fence -> Handle
 // Note: File descriptors are not duplicated. The original file descriptor must
 // not be closed before the transaction is complete.
-bool objcpy(hidl_handle* d, const C2Fence& s) {
+template <typename Handle>
+bool objcpy(Handle* d, const C2Fence& s) {
     d->setTo(nullptr);
     native_handle_t* handle = _C2FenceFactory::CreateNativeHandle(s);
     if (handle) {
@@ -775,23 +205,24 @@
 // C2ConstLinearBlock -> Block
 // Note: Native handles are not duplicated. The original handles must not be
 // closed before the transaction is complete.
+template <typename Block, typename BufferPoolTypes, typename BaseBlock>
 bool objcpy(Block* d, const C2ConstLinearBlock& s,
-        BufferPoolSender* bufferPoolSender,
+        BufferPoolSender<BufferPoolTypes>* bufferPoolSender,
         std::list<BaseBlock>* baseBlocks,
         std::map<const void*, uint32_t>* baseBlockIndices) {
     std::shared_ptr<const _C2BlockPoolData> bpData =
             _C2BlockFactory::GetLinearBlockPoolData(s);
-    if (!addBaseBlock(&d->index, s.handle(), bpData,
+    if (!addBaseBlock((uint32_t *)&d->index, s.handle(), bpData,
             bufferPoolSender, baseBlocks, baseBlockIndices)) {
         LOG(ERROR) << "Invalid block data in C2ConstLinearBlock.";
         return false;
     }
 
     // Create the metadata.
-    C2Hidl_RangeInfo dRangeInfo;
+    C2Hal_RangeInfo dRangeInfo;
     dRangeInfo.offset = static_cast<uint32_t>(s.offset());
     dRangeInfo.length = static_cast<uint32_t>(s.size());
-    if (!createParamsBlob(&d->meta, std::vector<C2Param*>{ &dRangeInfo })) {
+    if (!_createParamsBlob(&d->meta, std::vector<C2Param*>{ &dRangeInfo })) {
         LOG(ERROR) << "Invalid range info in C2ConstLinearBlock.";
         return false;
     }
@@ -807,26 +238,27 @@
 // C2ConstGraphicBlock -> Block
 // Note: Native handles are not duplicated. The original handles must not be
 // closed before the transaction is complete.
+template <typename Block, typename BufferPoolTypes, typename BaseBlock>
 bool objcpy(Block* d, const C2ConstGraphicBlock& s,
-        BufferPoolSender* bufferPoolSender,
+        BufferPoolSender<BufferPoolTypes>* bufferPoolSender,
         std::list<BaseBlock>* baseBlocks,
         std::map<const void*, uint32_t>* baseBlockIndices) {
     std::shared_ptr<const _C2BlockPoolData> bpData =
             _C2BlockFactory::GetGraphicBlockPoolData(s);
-    if (!addBaseBlock(&d->index, s.handle(), bpData,
+    if (!addBaseBlock((uint32_t *)&d->index, s.handle(), bpData,
             bufferPoolSender, baseBlocks, baseBlockIndices)) {
         LOG(ERROR) << "Invalid block data in C2ConstGraphicBlock.";
         return false;
     }
 
     // Create the metadata.
-    C2Hidl_RectInfo dRectInfo;
+    C2Hal_RectInfo dRectInfo;
     C2Rect sRect = s.crop();
     dRectInfo.left = static_cast<uint32_t>(sRect.left);
     dRectInfo.top = static_cast<uint32_t>(sRect.top);
     dRectInfo.width = static_cast<uint32_t>(sRect.width);
     dRectInfo.height = static_cast<uint32_t>(sRect.height);
-    if (!createParamsBlob(&d->meta, std::vector<C2Param*>{ &dRectInfo })) {
+    if (!_createParamsBlob(&d->meta, std::vector<C2Param*>{ &dRectInfo })) {
         LOG(ERROR) << "Invalid rect info in C2ConstGraphicBlock.";
         return false;
     }
@@ -841,8 +273,9 @@
 
 // C2BufferData -> Buffer
 // This function only fills in d->blocks.
+template <typename Buffer, typename BufferPoolTypes, typename BaseBlock>
 bool objcpy(Buffer* d, const C2BufferData& s,
-        BufferPoolSender* bufferPoolSender,
+        BufferPoolSender<BufferPoolTypes>* bufferPoolSender,
         std::list<BaseBlock>* baseBlocks,
         std::map<const void*, uint32_t>* baseBlockIndices) {
     d->blocks.resize(
@@ -850,7 +283,7 @@
             s.graphicBlocks().size());
     size_t i = 0;
     for (const C2ConstLinearBlock& linearBlock : s.linearBlocks()) {
-        Block& dBlock = d->blocks[i++];
+        auto& dBlock = d->blocks[i++];
         if (!objcpy(
                 &dBlock, linearBlock,
                 bufferPoolSender, baseBlocks, baseBlockIndices)) {
@@ -860,7 +293,7 @@
         }
     }
     for (const C2ConstGraphicBlock& graphicBlock : s.graphicBlocks()) {
-        Block& dBlock = d->blocks[i++];
+        auto& dBlock = d->blocks[i++];
         if (!objcpy(
                 &dBlock, graphicBlock,
                 bufferPoolSender, baseBlocks, baseBlockIndices)) {
@@ -873,11 +306,12 @@
 }
 
 // C2Buffer -> Buffer
+template <typename Buffer, typename BufferPoolTypes, typename BaseBlock>
 bool objcpy(Buffer* d, const C2Buffer& s,
-        BufferPoolSender* bufferPoolSender,
+        BufferPoolSender<BufferPoolTypes>* bufferPoolSender,
         std::list<BaseBlock>* baseBlocks,
         std::map<const void*, uint32_t>* baseBlockIndices) {
-    if (!createParamsBlob(&d->info, s.info())) {
+    if (!_createParamsBlob(&d->info, s.info())) {
         LOG(ERROR) << "Invalid C2Buffer::info.";
         return false;
     }
@@ -889,12 +323,13 @@
 }
 
 // C2InfoBuffer -> InfoBuffer
+template <typename InfoBuffer, typename BufferPoolTypes, typename BaseBlock>
 bool objcpy(InfoBuffer* d, const C2InfoBuffer& s,
-        BufferPoolSender* bufferPoolSender,
+        BufferPoolSender<BufferPoolTypes>* bufferPoolSender,
         std::list<BaseBlock>* baseBlocks,
         std::map<const void*, uint32_t>* baseBlockIndices) {
-    d->index = static_cast<ParamIndex>(s.index());
-    Buffer& dBuffer = d->buffer;
+    d->index = static_cast<decltype(d->index)>(s.index());
+    auto& dBuffer = d->buffer;
     if (!objcpy(&dBuffer, s.data(), bufferPoolSender, baseBlocks, baseBlockIndices)) {
         LOG(ERROR) << "Invalid C2InfoBuffer::data";
         return false;
@@ -903,11 +338,12 @@
 }
 
 // C2FrameData -> FrameData
+template <typename FrameData, typename BufferPoolTypes, typename BaseBlock>
 bool objcpy(FrameData* d, const C2FrameData& s,
-        BufferPoolSender* bufferPoolSender,
+        BufferPoolSender<BufferPoolTypes>* bufferPoolSender,
         std::list<BaseBlock>* baseBlocks,
         std::map<const void*, uint32_t>* baseBlockIndices) {
-    d->flags = static_cast<hidl_bitfield<FrameData::Flags>>(s.flags);
+    d->flags = static_cast<decltype(d->flags)>(s.flags);
     if (!objcpy(&d->ordinal, s.ordinal)) {
         LOG(ERROR) << "Invalid C2FrameData::ordinal.";
         return false;
@@ -916,11 +352,12 @@
     d->buffers.resize(s.buffers.size());
     size_t i = 0;
     for (const std::shared_ptr<C2Buffer>& sBuffer : s.buffers) {
-        Buffer& dBuffer = d->buffers[i++];
+        auto& dBuffer = d->buffers[i++];
         if (!sBuffer) {
             // A null (pointer to) C2Buffer corresponds to a Buffer with empty
             // info and blocks.
-            dBuffer.info.resize(0);
+            auto *dInfo = GetBlob(&dBuffer.info);
+            dInfo->resize(0);
             dBuffer.blocks.resize(0);
             continue;
         }
@@ -933,7 +370,7 @@
         }
     }
 
-    if (!createParamsBlob(&d->configUpdate, s.configUpdate)) {
+    if (!_createParamsBlob(&d->configUpdate, s.configUpdate)) {
         LOG(ERROR) << "Invalid C2FrameData::configUpdate.";
         return false;
     }
@@ -941,7 +378,7 @@
     d->infoBuffers.resize(s.infoBuffers.size());
     i = 0;
     for (const C2InfoBuffer& sInfoBuffer : s.infoBuffers) {
-        InfoBuffer& dInfoBuffer = d->infoBuffers[i++];
+        auto& dInfoBuffer = d->infoBuffers[i++];
         if (!objcpy(&dInfoBuffer, sInfoBuffer,
                 bufferPoolSender, baseBlocks, baseBlockIndices)) {
             LOG(ERROR) << "Invalid C2FrameData::infoBuffers["
@@ -953,113 +390,14 @@
     return true;
 }
 
-} // unnamed namespace
-
-// DefaultBufferPoolSender's implementation
-
-DefaultBufferPoolSender::DefaultBufferPoolSender(
-        const sp<IClientManager>& receiverManager,
-        std::chrono::steady_clock::duration refreshInterval)
-    : mReceiverManager(receiverManager),
-      mRefreshInterval(refreshInterval) {
-}
-
-void DefaultBufferPoolSender::setReceiver(
-        const sp<IClientManager>& receiverManager,
-        std::chrono::steady_clock::duration refreshInterval) {
-    std::lock_guard<std::mutex> lock(mMutex);
-    if (mReceiverManager != receiverManager) {
-        mReceiverManager = receiverManager;
-        mConnections.clear();
-    }
-    mRefreshInterval = refreshInterval;
-}
-
-ResultStatus DefaultBufferPoolSender::send(
-        const std::shared_ptr<BufferPoolData>& bpData,
-        BufferStatusMessage* bpMessage) {
-    int64_t connectionId = bpData->mConnectionId;
-    if (connectionId == 0) {
-        LOG(WARNING) << "registerSender -- invalid sender connection id (0).";
-        return ResultStatus::CRITICAL_ERROR;
-    }
-    std::lock_guard<std::mutex> lock(mMutex);
-    if (!mReceiverManager) {
-        LOG(ERROR) << "No access to receiver's BufferPool.";
-        return ResultStatus::NOT_FOUND;
-    }
-    if (!mSenderManager) {
-        mSenderManager = ClientManager::getInstance();
-        if (!mSenderManager) {
-            LOG(ERROR) << "Failed to retrieve local BufferPool ClientManager.";
-            return ResultStatus::CRITICAL_ERROR;
-        }
-    }
-
-    int64_t receiverConnectionId{0};
-    auto foundConnection = mConnections.find(connectionId);
-    bool isNewConnection = foundConnection == mConnections.end();
-    std::chrono::steady_clock::time_point now =
-            std::chrono::steady_clock::now();
-    if (isNewConnection ||
-            (now - foundConnection->second.lastSent > mRefreshInterval)) {
-        // Initialize the bufferpool connection.
-        ResultStatus rs =
-                mSenderManager->registerSender(mReceiverManager,
-                                               connectionId,
-                                               &receiverConnectionId);
-        if ((rs != ResultStatus::OK) && (rs != ResultStatus::ALREADY_EXISTS)) {
-            LOG(WARNING) << "registerSender -- returned error: "
-                         << static_cast<int32_t>(rs)
-                         << ".";
-            return rs;
-        } else if (receiverConnectionId == 0) {
-            LOG(WARNING) << "registerSender -- "
-                            "invalid receiver connection id (0).";
-            return ResultStatus::CRITICAL_ERROR;
-        } else {
-            if (isNewConnection) {
-                foundConnection = mConnections.try_emplace(
-                        connectionId, receiverConnectionId, now).first;
-            } else {
-                foundConnection->second.receiverConnectionId = receiverConnectionId;
-            }
-        }
-    } else {
-        receiverConnectionId = foundConnection->second.receiverConnectionId;
-    }
-
-    uint64_t transactionId;
-    int64_t timestampUs;
-    ResultStatus rs = mSenderManager->postSend(
-            receiverConnectionId, bpData, &transactionId, &timestampUs);
-    if (rs != ResultStatus::OK) {
-        LOG(ERROR) << "ClientManager::postSend -- returned error: "
-                   << static_cast<int32_t>(rs)
-                   << ".";
-        mConnections.erase(foundConnection);
-        return rs;
-    }
-    if (!bpMessage) {
-        LOG(ERROR) << "Null output parameter for BufferStatusMessage.";
-        mConnections.erase(foundConnection);
-        return ResultStatus::CRITICAL_ERROR;
-    }
-    bpMessage->connectionId = receiverConnectionId;
-    bpMessage->bufferId = bpData->mId;
-    bpMessage->transactionId = transactionId;
-    bpMessage->timestampUs = timestampUs;
-    foundConnection->second.lastSent = now;
-    return rs;
-}
-
 // std::list<std::unique_ptr<C2Work>> -> WorkBundle
+template <typename WorkBundle, typename BufferPoolTypes>
 bool objcpy(
         WorkBundle* d,
         const std::list<std::unique_ptr<C2Work>>& s,
-        BufferPoolSender* bufferPoolSender) {
+        BufferPoolSender<BufferPoolTypes>* bufferPoolSender) {
     // baseBlocks holds a list of BaseBlock objects that Blocks can refer to.
-    std::list<BaseBlock> baseBlocks;
+    std::list<typename decltype(d->baseBlocks)::value_type> baseBlocks;
 
     // baseBlockIndices maps a raw pointer to native_handle_t or BufferPoolData
     // inside baseBlocks to the corresponding index into baseBlocks. The keys
@@ -1075,7 +413,7 @@
     d->works.resize(s.size());
     size_t i = 0;
     for (const std::unique_ptr<C2Work>& sWork : s) {
-        Work &dWork = d->works[i++];
+        auto &dWork = d->works[i++];
         if (!sWork) {
             LOG(WARNING) << "Null C2Work encountered.";
             continue;
@@ -1095,7 +433,7 @@
             LOG(DEBUG) << "Work with no worklets.";
         } else {
             // Parcel the worklets.
-            hidl_vec<Worklet> &dWorklets = dWork.worklets;
+            auto &dWorklets = dWork.worklets;
             dWorklets.resize(sWork->worklets.size());
             size_t j = 0;
             for (const std::unique_ptr<C2Worklet>& sWorklet : sWork->worklets)
@@ -1105,14 +443,14 @@
                                  << j << "].";
                     continue;
                 }
-                Worklet &dWorklet = dWorklets[j++];
+                auto &dWorklet = dWorklets[j++];
 
                 // component id
                 dWorklet.componentId = static_cast<uint32_t>(
                         sWorklet->component);
 
                 // tunings
-                if (!createParamsBlob(&dWorklet.tunings, sWorklet->tunings)) {
+                if (!_createParamsBlob(&dWorklet.tunings, sWorklet->tunings)) {
                     LOG(ERROR) << "Invalid C2Work::worklets["
                                << j - 1 << "]->tunings.";
                     return false;
@@ -1151,23 +489,21 @@
         dWork.workletsProcessed = sWork->workletsProcessed;
 
         // result
-        dWork.result = static_cast<Status>(sWork->result);
+        SetStatus(&dWork.result, sWork->result);
     }
 
-    // Copy std::list<BaseBlock> to hidl_vec<BaseBlock>.
+    // Move std::list<BaseBlock> to vector<BaseBlock>.
     {
         d->baseBlocks.resize(baseBlocks.size());
         size_t i = 0;
-        for (const BaseBlock& baseBlock : baseBlocks) {
-            d->baseBlocks[i++] = baseBlock;
+        for (auto&& baseBlock : baseBlocks) {
+            d->baseBlocks[i++] = std::move(baseBlock);
         }
     }
 
     return true;
 }
 
-namespace /* unnamed */ {
-
 struct C2BaseBlock {
     enum type_t {
         LINEAR,
@@ -1178,78 +514,33 @@
     std::shared_ptr<C2GraphicBlock> graphic;
 };
 
-// hidl_handle -> C2Fence
+// Handle -> C2Fence
 // Note: File descriptors are not duplicated. The original file descriptor must
 // not be closed before the transaction is complete.
-bool objcpy(C2Fence* d, const hidl_handle& s) {
+template <typename Handle>
+bool objcpy(C2Fence* d, const Handle& s) {
     const native_handle_t* handle = s.getNativeHandle();
     *d = _C2FenceFactory::CreateFromNativeHandle(handle);
     return true;
 }
 
 // C2LinearBlock, vector<C2Param*>, C2Fence -> C2Buffer
-bool createLinearBuffer(
+bool CreateLinearBuffer(
         std::shared_ptr<C2Buffer>* buffer,
         const std::shared_ptr<C2LinearBlock>& block,
         const std::vector<C2Param*>& meta,
-        const C2Fence& fence) {
-    // Check the block meta. It should have exactly 1 C2Info:
-    // C2Hidl_RangeInfo.
-    if ((meta.size() != 1) || !meta[0]) {
-        LOG(ERROR) << "Invalid C2LinearBlock::meta.";
-        return false;
-    }
-    if (meta[0]->size() != sizeof(C2Hidl_RangeInfo)) {
-        LOG(ERROR) << "Invalid range info in C2LinearBlock.";
-        return false;
-    }
-    C2Hidl_RangeInfo *rangeInfo =
-            reinterpret_cast<C2Hidl_RangeInfo*>(meta[0]);
-
-    // Create C2Buffer from C2LinearBlock.
-    *buffer = C2Buffer::CreateLinearBuffer(block->share(
-            rangeInfo->offset, rangeInfo->length,
-            fence));
-    if (!(*buffer)) {
-        LOG(ERROR) << "CreateLinearBuffer failed.";
-        return false;
-    }
-    return true;
-}
+        const C2Fence& fence);
 
 // C2GraphicBlock, vector<C2Param*>, C2Fence -> C2Buffer
-bool createGraphicBuffer(
+bool CreateGraphicBuffer(
         std::shared_ptr<C2Buffer>* buffer,
         const std::shared_ptr<C2GraphicBlock>& block,
         const std::vector<C2Param*>& meta,
-        const C2Fence& fence) {
-    // Check the block meta. It should have exactly 1 C2Info:
-    // C2Hidl_RectInfo.
-    if ((meta.size() != 1) || !meta[0]) {
-        LOG(ERROR) << "Invalid C2GraphicBlock::meta.";
-        return false;
-    }
-    if (meta[0]->size() != sizeof(C2Hidl_RectInfo)) {
-        LOG(ERROR) << "Invalid rect info in C2GraphicBlock.";
-        return false;
-    }
-    C2Hidl_RectInfo *rectInfo =
-            reinterpret_cast<C2Hidl_RectInfo*>(meta[0]);
-
-    // Create C2Buffer from C2GraphicBlock.
-    *buffer = C2Buffer::CreateGraphicBuffer(block->share(
-            C2Rect(rectInfo->width, rectInfo->height).
-            at(rectInfo->left, rectInfo->top),
-            fence));
-    if (!(*buffer)) {
-        LOG(ERROR) << "CreateGraphicBuffer failed.";
-        return false;
-    }
-    return true;
-}
+        const C2Fence& fence);
 
 // Buffer -> C2Buffer
 // Note: The native handles will be cloned.
+template <typename Buffer>
 bool objcpy(std::shared_ptr<C2Buffer>* d, const Buffer& s,
         const std::vector<C2BaseBlock>& baseBlocks) {
     *d = nullptr;
@@ -1263,7 +554,7 @@
         return false;
     }
 
-    const Block &sBlock = s.blocks[0];
+    const auto &sBlock = s.blocks[0];
     if (sBlock.index >= baseBlocks.size()) {
         LOG(ERROR) << "Invalid Buffer::blocks[0].index: "
                       "Array index out of range.";
@@ -1288,13 +579,13 @@
     // Construct a block.
     switch (baseBlock.type) {
     case C2BaseBlock::LINEAR:
-        if (!createLinearBuffer(d, baseBlock.linear, sBlockMeta, dFence)) {
+        if (!CreateLinearBuffer(d, baseBlock.linear, sBlockMeta, dFence)) {
             LOG(ERROR) << "Invalid C2BaseBlock::linear.";
             return false;
         }
         break;
     case C2BaseBlock::GRAPHIC:
-        if (!createGraphicBuffer(d, baseBlock.graphic, sBlockMeta, dFence)) {
+        if (!CreateGraphicBuffer(d, baseBlock.graphic, sBlockMeta, dFence)) {
             LOG(ERROR) << "Invalid C2BaseBlock::graphic.";
             return false;
         }
@@ -1333,7 +624,10 @@
 }
 
 // InfoBuffer -> C2InfoBuffer
-bool objcpy(std::vector<C2InfoBuffer> *d, const InfoBuffer& s,
+template <typename InfoBuffer>
+bool objcpy(
+        std::vector<C2InfoBuffer> *d,
+        const InfoBuffer& s,
         const std::vector<C2BaseBlock>& baseBlocks) {
 
     // Currently, a non-null C2InfoBufer must contain exactly 1 block.
@@ -1345,7 +639,7 @@
         return false;
     }
 
-    const Block &sBlock = s.buffer.blocks[0];
+    const auto &sBlock = s.buffer.blocks[0];
     if (sBlock.index >= baseBlocks.size()) {
         LOG(ERROR) << "Invalid InfoBuffer::Buffer::blocks[0].index: "
                       "Array index out of range.";
@@ -1371,11 +665,11 @@
     switch (baseBlock.type) {
     case C2BaseBlock::LINEAR:
         if (sBlockMeta.size() == 1 && sBlockMeta[0] != nullptr &&
-            sBlockMeta[0]->size() == sizeof(C2Hidl_RangeInfo)) {
-            C2Hidl_RangeInfo *rangeInfo =
-                    reinterpret_cast<C2Hidl_RangeInfo*>(sBlockMeta[0]);
+            sBlockMeta[0]->size() == sizeof(C2Hal_RangeInfo)) {
+            C2Hal_RangeInfo *rangeInfo =
+                    reinterpret_cast<C2Hal_RangeInfo*>(sBlockMeta[0]);
             d->emplace_back(C2InfoBuffer::CreateLinearBuffer(
-                    s.index,
+                    uint32_t(s.index),
                     baseBlock.linear->share(
                             rangeInfo->offset, rangeInfo->length, dFence)));
             return true;
@@ -1395,6 +689,7 @@
 }
 
 // FrameData -> C2FrameData
+template <typename FrameData>
 bool objcpy(C2FrameData* d, const FrameData& s,
         const std::vector<C2BaseBlock>& baseBlocks) {
     d->flags = static_cast<C2FrameData::flags_t>(s.flags);
@@ -1404,7 +699,7 @@
     }
     d->buffers.clear();
     d->buffers.reserve(s.buffers.size());
-    for (const Buffer& sBuffer : s.buffers) {
+    for (const auto& sBuffer : s.buffers) {
         std::shared_ptr<C2Buffer> dBuffer;
         if (!objcpy(&dBuffer, sBuffer, baseBlocks)) {
             LOG(ERROR) << "Invalid FrameData::buffers.";
@@ -1434,7 +729,7 @@
         return true;
     }
     d->infoBuffers.reserve(s.infoBuffers.size());
-    for (const InfoBuffer &sInfoBuffer: s.infoBuffers) {
+    for (const auto &sInfoBuffer: s.infoBuffers) {
         if (!objcpy(&(d->infoBuffers), sInfoBuffer, baseBlocks)) {
             LOG(ERROR) << "Invalid Framedata::infoBuffers.";
             return false;
@@ -1444,95 +739,11 @@
 }
 
 // BaseBlock -> C2BaseBlock
-bool objcpy(C2BaseBlock* d, const BaseBlock& s) {
-    switch (s.getDiscriminator()) {
-    case BaseBlock::hidl_discriminator::nativeBlock: {
-            if (s.nativeBlock() == nullptr) {
-                LOG(ERROR) << "Null BaseBlock::nativeBlock handle";
-                return false;
-            }
-            native_handle_t* sHandle =
-                    native_handle_clone(s.nativeBlock());
-            if (sHandle == nullptr) {
-                LOG(ERROR) << "Null BaseBlock::nativeBlock.";
-                return false;
-            }
-            const C2Handle *sC2Handle =
-                    reinterpret_cast<const C2Handle*>(sHandle);
-
-            d->linear = _C2BlockFactory::CreateLinearBlock(sC2Handle);
-            if (d->linear) {
-                d->type = C2BaseBlock::LINEAR;
-                return true;
-            }
-
-            d->graphic = _C2BlockFactory::CreateGraphicBlock(sC2Handle);
-            if (d->graphic) {
-                d->type = C2BaseBlock::GRAPHIC;
-                return true;
-            }
-
-            LOG(ERROR) << "Unknown handle type in BaseBlock::nativeBlock.";
-            if (sHandle) {
-                native_handle_close(sHandle);
-                native_handle_delete(sHandle);
-            }
-            return false;
-        }
-    case BaseBlock::hidl_discriminator::pooledBlock: {
-            const BufferStatusMessage &bpMessage =
-                    s.pooledBlock();
-            sp<ClientManager> bp = ClientManager::getInstance();
-            std::shared_ptr<BufferPoolData> bpData;
-            native_handle_t *cHandle;
-            ResultStatus bpStatus = bp->receive(
-                    bpMessage.connectionId,
-                    bpMessage.transactionId,
-                    bpMessage.bufferId,
-                    bpMessage.timestampUs,
-                    &cHandle,
-                    &bpData);
-            if (bpStatus != ResultStatus::OK) {
-                LOG(ERROR) << "Failed to receive buffer from bufferpool -- "
-                           << "resultStatus = " << underlying_value(bpStatus)
-                           << ".";
-                return false;
-            } else if (!bpData) {
-                LOG(ERROR) << "No data in bufferpool transaction.";
-                return false;
-            }
-
-            d->linear = _C2BlockFactory::CreateLinearBlock(cHandle, bpData);
-            if (d->linear) {
-                d->type = C2BaseBlock::LINEAR;
-                return true;
-            }
-
-            d->graphic = _C2BlockFactory::CreateGraphicBlock(cHandle, bpData);
-            if (d->graphic) {
-                d->type = C2BaseBlock::GRAPHIC;
-                return true;
-            }
-            if (cHandle) {
-                // Though we got cloned handle, creating block failed.
-                native_handle_close(cHandle);
-                native_handle_delete(cHandle);
-            }
-
-            LOG(ERROR) << "Unknown handle type in BaseBlock::pooledBlock.";
-            return false;
-        }
-    default:
-        LOG(ERROR) << "Unrecognized BaseBlock's discriminator with "
-                   << "underlying value "
-                   << underlying_value(s.getDiscriminator()) << ".";
-        return false;
-    }
-}
-
-} // unnamed namespace
+template <typename BaseBlock>
+bool objcpy(C2BaseBlock* d, const BaseBlock& s);
 
 // WorkBundle -> std::list<std::unique_ptr<C2Work>>
+template <typename WorkBundle>
 bool objcpy(std::list<std::unique_ptr<C2Work>>* d, const WorkBundle& s) {
     // Convert BaseBlocks to C2BaseBlocks.
     std::vector<C2BaseBlock> dBaseBlocks(s.baseBlocks.size());
@@ -1545,7 +756,7 @@
     }
 
     d->clear();
-    for (const Work& sWork : s.works) {
+    for (const auto& sWork : s.works) {
         d->emplace_back(std::make_unique<C2Work>());
         C2Work& dWork = *d->back();
 
@@ -1559,7 +770,7 @@
 
         // worklet(s)
         dWork.worklets.clear();
-        for (const Worklet& sWorklet : sWork.worklets) {
+        for (const auto& sWorklet : sWork.worklets) {
             std::unique_ptr<C2Worklet> dWorklet = std::make_unique<C2Worklet>();
 
             // component id
@@ -1567,7 +778,7 @@
                     sWorklet.componentId);
 
             // tunings
-            if (!copyParamsFromBlob(&dWorklet->tunings, sWorklet.tunings)) {
+            if (!_copyParamsFromBlob(&dWorklet->tunings, sWorklet.tunings)) {
                 LOG(ERROR) << "Invalid Worklet::tunings";
                 return false;
             }
@@ -1575,7 +786,7 @@
             // failures
             dWorklet->failures.clear();
             dWorklet->failures.reserve(sWorklet.failures.size());
-            for (const SettingResult& sFailure : sWorklet.failures) {
+            for (const auto& sFailure : sWorklet.failures) {
                 std::unique_ptr<C2SettingResult> dFailure;
                 if (!objcpy(&dFailure, sFailure)) {
                     LOG(ERROR) << "Invalid Worklet::failures.";
@@ -1597,332 +808,56 @@
         dWork.workletsProcessed = sWork.workletsProcessed;
 
         // result
-        dWork.result = static_cast<c2_status_t>(sWork.result);
+        dWork.result = GetStatus(sWork.result);
     }
 
     return true;
 }
 
-constexpr size_t PARAMS_ALIGNMENT = 8;  // 64-bit alignment
-static_assert(PARAMS_ALIGNMENT % alignof(C2Param) == 0, "C2Param alignment mismatch");
-static_assert(PARAMS_ALIGNMENT % alignof(C2Info) == 0, "C2Param alignment mismatch");
-static_assert(PARAMS_ALIGNMENT % alignof(C2Tuning) == 0, "C2Param alignment mismatch");
+// BufferQueue-Based Block Operations
+// ==================================
 
-// Params -> std::vector<C2Param*>
-bool parseParamsBlob(std::vector<C2Param*> *params, const hidl_vec<uint8_t> &blob) {
-    // assuming blob is const here
-    size_t size = blob.size();
-    size_t ix = 0;
-    size_t old_ix = 0;
-    const uint8_t *data = blob.data();
-    C2Param *p = nullptr;
+// Call before transferring block to other processes.
+//
+// The given block is ready to transfer to other processes. This will guarantee
+// the given block data is not mutated by bufferqueue migration.
+bool BeginTransferBufferQueueBlock(const C2ConstGraphicBlock& block);
 
-    do {
-        p = C2ParamUtils::ParseFirst(data + ix, size - ix);
-        if (p) {
-            params->emplace_back(p);
-            old_ix = ix;
-            ix += p->size();
-            ix = align(ix, PARAMS_ALIGNMENT);
-            if (ix <= old_ix || ix > size) {
-                android_errorWriteLog(0x534e4554, "238083570");
-                break;
-            }
-        }
-    } while (p);
-
-    if (ix != size) {
-        LOG(ERROR) << "parseParamsBlob -- inconsistent sizes.";
-        return false;
-    }
-    return true;
-}
-
-namespace /* unnamed */ {
-
-/**
- * Concatenates a list of C2Params into a params blob. T is a container type
- * whose member type is compatible with C2Param*.
- *
- * \param[out] blob target blob
- * \param[in] params parameters to concatenate
- * \retval C2_OK if the blob was successfully created
- * \retval C2_BAD_VALUE if the blob was not successful created (this only
- *         happens if the parameters were not const)
- */
-template <typename T>
-bool _createParamsBlob(hidl_vec<uint8_t> *blob, const T &params) {
-    // assuming the parameter values are const
-    size_t size = 0;
-    for (const auto &p : params) {
-        if (!p) {
-            continue;
-        }
-        size += p->size();
-        size = align(size, PARAMS_ALIGNMENT);
-    }
-    blob->resize(size);
-    size_t ix = 0;
-    for (const auto &p : params) {
-        if (!p) {
-            continue;
-        }
-        // NEVER overwrite even if param values (e.g. size) changed
-        size_t paramSize = std::min(p->size(), size - ix);
-        std::copy(
-                reinterpret_cast<const uint8_t*>(&*p),
-                reinterpret_cast<const uint8_t*>(&*p) + paramSize,
-                &(*blob)[ix]);
-        ix += paramSize;
-        ix = align(ix, PARAMS_ALIGNMENT);
-    }
-    blob->resize(ix);
-    if (ix != size) {
-        LOG(ERROR) << "createParamsBlob -- inconsistent sizes.";
-        return false;
-    }
-    return true;
-}
-
-/**
- * Parses a params blob and create a vector of new T objects that contain copies
- * of the params in the blob. T is C2Param or its compatible derived class.
- *
- * \param[out] params the resulting vector
- * \param[in] blob parameter blob to parse
- * \retval C2_OK if the full blob was parsed and params was constructed
- * \retval C2_BAD_VALUE otherwise
- */
-template <typename T>
-bool _copyParamsFromBlob(
-        std::vector<std::unique_ptr<T>>* params,
-        Params blob) {
-
-    std::vector<C2Param*> paramPointers;
-    if (!parseParamsBlob(&paramPointers, blob)) {
-        LOG(ERROR) << "copyParamsFromBlob -- failed to parse.";
-        return false;
-    }
-
-    params->resize(paramPointers.size());
-    size_t i = 0;
-    for (C2Param* const& paramPointer : paramPointers) {
-        if (!paramPointer) {
-            LOG(ERROR) << "copyParamsFromBlob -- null paramPointer.";
-            return false;
-        }
-        (*params)[i++].reset(reinterpret_cast<T*>(
-                C2Param::Copy(*paramPointer).release()));
-    }
-    return true;
-}
-
-} // unnamed namespace
-
-// std::vector<const C2Param*> -> Params
-bool createParamsBlob(
-        hidl_vec<uint8_t> *blob,
-        const std::vector<const C2Param*> &params) {
-    return _createParamsBlob(blob, params);
-}
-
-// std::vector<C2Param*> -> Params
-bool createParamsBlob(
-        hidl_vec<uint8_t> *blob,
-        const std::vector<C2Param*> &params) {
-    return _createParamsBlob(blob, params);
-}
-
-// std::vector<std::unique_ptr<C2Param>> -> Params
-bool createParamsBlob(
-        hidl_vec<uint8_t> *blob,
-        const std::vector<std::unique_ptr<C2Param>> &params) {
-    return _createParamsBlob(blob, params);
-}
-
-// std::vector<std::unique_ptr<C2Tuning>> -> Params
-bool createParamsBlob(
-        hidl_vec<uint8_t> *blob,
-        const std::vector<std::unique_ptr<C2Tuning>> &params) {
-    return _createParamsBlob(blob, params);
-}
-
-// std::vector<std::shared_ptr<const C2Info>> -> Params
-bool createParamsBlob(
-        hidl_vec<uint8_t> *blob,
-        const std::vector<std::shared_ptr<const C2Info>> &params) {
-    return _createParamsBlob(blob, params);
-}
-
-// Params -> std::vector<std::unique_ptr<C2Param>>
-bool copyParamsFromBlob(
-        std::vector<std::unique_ptr<C2Param>>* params,
-        Params blob) {
-    return _copyParamsFromBlob(params, blob);
-}
-
-// Params -> std::vector<std::unique_ptr<C2Tuning>>
-bool copyParamsFromBlob(
-        std::vector<std::unique_ptr<C2Tuning>>* params,
-        Params blob) {
-    return _copyParamsFromBlob(params, blob);
-}
-
-// Params -> update std::vector<std::unique_ptr<C2Param>>
-bool updateParamsFromBlob(
-        const std::vector<C2Param*>& params,
-        const Params& blob) {
-    std::unordered_map<uint32_t, C2Param*> index2param;
-    for (C2Param* const& param : params) {
-        if (!param) {
-            LOG(ERROR) << "updateParamsFromBlob -- null output param.";
-            return false;
-        }
-        if (index2param.find(param->index()) == index2param.end()) {
-            index2param.emplace(param->index(), param);
-        }
-    }
-
-    std::vector<C2Param*> paramPointers;
-    if (!parseParamsBlob(&paramPointers, blob)) {
-        LOG(ERROR) << "updateParamsFromBlob -- failed to parse.";
-        return false;
-    }
-
-    for (C2Param* const& paramPointer : paramPointers) {
-        if (!paramPointer) {
-            LOG(ERROR) << "updateParamsFromBlob -- null input param.";
-            return false;
-        }
-        decltype(index2param)::iterator i = index2param.find(
-                paramPointer->index());
-        if (i == index2param.end()) {
-            LOG(DEBUG) << "updateParamsFromBlob -- index "
-                       << paramPointer->index() << " not found. Skipping...";
-            continue;
-        }
-        if (!i->second->updateFrom(*paramPointer)) {
-            LOG(ERROR) << "updateParamsFromBlob -- size mismatch: "
-                       << params.size() << " vs " << paramPointer->size()
-                       << " (index = " << i->first << ").";
-            return false;
-        }
-    }
-    return true;
-}
-
-// Convert BufferPool ResultStatus to c2_status_t.
-c2_status_t toC2Status(ResultStatus rs) {
-    switch (rs) {
-    case ResultStatus::OK:
-        return C2_OK;
-    case ResultStatus::NO_MEMORY:
-        return C2_NO_MEMORY;
-    case ResultStatus::ALREADY_EXISTS:
-        return C2_DUPLICATE;
-    case ResultStatus::NOT_FOUND:
-        return C2_NOT_FOUND;
-    case ResultStatus::CRITICAL_ERROR:
-        return C2_CORRUPTED;
-    default:
-        LOG(WARNING) << "Unrecognized BufferPool ResultStatus: "
-                     << static_cast<int32_t>(rs) << ".";
-        return C2_CORRUPTED;
-    }
-}
-
-namespace /* unnamed */ {
-
-template <typename BlockProcessor>
-void forEachBlock(C2FrameData& frameData,
-                  BlockProcessor process) {
-    for (const std::shared_ptr<C2Buffer>& buffer : frameData.buffers) {
-        if (buffer) {
-            for (const C2ConstGraphicBlock& block :
-                    buffer->data().graphicBlocks()) {
-                process(block);
-            }
-        }
-    }
-}
-
-template <typename BlockProcessor>
-void forEachBlock(const std::list<std::unique_ptr<C2Work>>& workList,
-                  BlockProcessor process,
-                  bool processInput, bool processOutput) {
-    for (const std::unique_ptr<C2Work>& work : workList) {
-        if (!work) {
-            continue;
-        }
-        if (processInput) {
-            forEachBlock(work->input, process);
-        }
-        if (processOutput) {
-            for (const std::unique_ptr<C2Worklet>& worklet : work->worklets) {
-                if (worklet) {
-                    forEachBlock(worklet->output,
-                                 process);
-                }
-            }
-        }
-    }
-}
-
-} // unnamed namespace
-
-bool beginTransferBufferQueueBlock(const C2ConstGraphicBlock& block) {
-    std::shared_ptr<_C2BlockPoolData> data =
-            _C2BlockFactory::GetGraphicBlockPoolData(block);
-    if (data && _C2BlockFactory::GetBufferQueueData(data)) {
-        _C2BlockFactory::BeginTransferBlockToClient(data);
-        return true;
-    }
-    return false;
-}
-
-void beginTransferBufferQueueBlocks(
+// Call beginTransferBufferQueueBlock() on blocks in the given workList.
+// processInput determines whether input blocks are yielded. processOutput
+// works similarly on output blocks. (The default value of processInput is
+// false while the default value of processOutput is true. This implies that in
+// most cases, only output buffers contain bufferqueue-based blocks.)
+void BeginTransferBufferQueueBlocks(
         const std::list<std::unique_ptr<C2Work>>& workList,
-        bool processInput, bool processOutput) {
-    forEachBlock(workList, beginTransferBufferQueueBlock,
-                 processInput, processOutput);
-}
+        bool processInput = false,
+        bool processOutput = true);
 
-bool endTransferBufferQueueBlock(
-        const C2ConstGraphicBlock& block,
-        bool transfer) {
-    std::shared_ptr<_C2BlockPoolData> data =
-            _C2BlockFactory::GetGraphicBlockPoolData(block);
-    if (data && _C2BlockFactory::GetBufferQueueData(data)) {
-        _C2BlockFactory::EndTransferBlockToClient(data, transfer);
-        return true;
-    }
-    return false;
-}
+// Call after transferring block is finished and make sure that
+// beginTransferBufferQueueBlock() is called before.
+//
+// The transfer of given block is finished. If transfer is successful the given
+// block is not owned by process anymore. Since transfer is finished the given
+// block data is OK to mutate by bufferqueue migration after this call.
+bool EndTransferBufferQueueBlock(const C2ConstGraphicBlock& block,
+                                 bool transfer);
 
-void endTransferBufferQueueBlocks(
+// Call endTransferBufferQueueBlock() on blocks in the given workList.
+// processInput determines whether input blocks are yielded. processOutput
+// works similarly on output blocks. (The default value of processInput is
+// false while the default value of processOutput is true. This implies that in
+// most cases, only output buffers contain bufferqueue-based blocks.)
+void EndTransferBufferQueueBlocks(
         const std::list<std::unique_ptr<C2Work>>& workList,
         bool transfer,
-        bool processInput, bool processOutput) {
-    forEachBlock(workList,
-                 std::bind(endTransferBufferQueueBlock,
-                           std::placeholders::_1, transfer),
-                 processInput, processOutput);
-}
+        bool processInput = false,
+        bool processOutput = true);
 
-bool displayBufferQueueBlock(const C2ConstGraphicBlock& block) {
-    std::shared_ptr<_C2BlockPoolData> data =
-            _C2BlockFactory::GetGraphicBlockPoolData(block);
-    if (data && _C2BlockFactory::GetBufferQueueData(data)) {
-        _C2BlockFactory::DisplayBlockToBufferQueue(data);
-        return true;
-    }
-    return false;
-}
+// The given block is ready to be rendered. the given block is not owned by
+// process anymore. If migration is in progress, this returns false in order
+// not to render.
+bool DisplayBufferQueueBlock(const C2ConstGraphicBlock& block);
 
-}  // namespace utils
-}  // namespace V1_0
-}  // namespace c2
-}  // namespace media
-}  // namespace hardware
 }  // namespace android
 
+#endif  // CODEC2_COMMON_BUFFER_TYPES_H
diff --git a/media/codec2/hal/hidl/1.0/utils/Android.bp b/media/codec2/hal/hidl/1.0/utils/Android.bp
index 2933940..2f2ecd1 100644
--- a/media/codec2/hal/hidl/1.0/utils/Android.bp
+++ b/media/codec2/hal/hidl/1.0/utils/Android.bp
@@ -19,7 +19,6 @@
     ],
 
     header_libs: [
-        "libcodec2_hal_common",
         "libcodec2_internal", // private
     ],
 
@@ -28,6 +27,7 @@
         "android.hardware.media.c2@1.0",
         "libbase",
         "libcodec2",
+        "libcodec2_hal_common",
         "libcodec2_vndk",
         "libcutils",
         "libgui",
@@ -45,6 +45,7 @@
     export_shared_lib_headers: [
         "android.hardware.media.c2@1.0",
         "libcodec2",
+        "libcodec2_hal_common",
         "libgui",
         "libstagefright_bufferpool@2.0.1",
         "libui",
@@ -78,7 +79,6 @@
 
     header_libs: [
         "libbinder_headers",
-        "libcodec2_hal_common",
         "libcodec2_internal", // private
         "libsystem_headers",
     ],
@@ -93,8 +93,9 @@
         "android.hardware.media.omx@1.0",
         "libbase",
         "libcodec2",
-        "libcodec2_vndk",
+        "libcodec2_hal_common",
         "libcodec2_hidl_plugin_stub",
+        "libcodec2_vndk",
         "libcutils",
         "libhidlbase",
         "liblog",
@@ -130,6 +131,7 @@
     export_shared_lib_headers: [
         "android.hardware.media.c2@1.0",
         "libcodec2",
+        "libcodec2_hal_common",
         "libcodec2_vndk",
         "libhidlbase",
         "libstagefright_bufferpool@2.0.1",
diff --git a/media/codec2/hal/hidl/1.0/utils/include/codec2/hidl/1.0/types.h b/media/codec2/hal/hidl/1.0/utils/include/codec2/hidl/1.0/types.h
index f111f81..20e3fb5 100644
--- a/media/codec2/hal/hidl/1.0/utils/include/codec2/hidl/1.0/types.h
+++ b/media/codec2/hal/hidl/1.0/utils/include/codec2/hidl/1.0/types.h
@@ -23,6 +23,7 @@
 #include <android/hardware/media/c2/1.0/IComponentStore.h>
 #include <android/hardware/media/c2/1.0/types.h>
 #include <android/hidl/safe_union/1.0/types.h>
+#include <codec2/common/BufferPoolSender.h>
 
 #include <C2Component.h>
 #include <C2Param.h>
@@ -42,8 +43,6 @@
 namespace utils {
 
 using ::android::hardware::hidl_bitfield;
-using ::android::hardware::hidl_handle;
-using ::android::hardware::hidl_string;
 using ::android::hardware::hidl_vec;
 using ::android::status_t;
 using ::android::sp;
@@ -134,38 +133,15 @@
         std::unique_ptr<C2StructDescriptor>* d,
         const StructDescriptor& s);
 
-// Abstract class to be used in
-// objcpy(std::list<std::unique_ptr<C2Work>> -> WorkBundle).
-struct BufferPoolSender {
-    typedef ::android::hardware::media::bufferpool::V2_0::
-            ResultStatus ResultStatus;
-    typedef ::android::hardware::media::bufferpool::V2_0::
-            BufferStatusMessage BufferStatusMessage;
-    typedef ::android::hardware::media::bufferpool::
-            BufferPoolData BufferPoolData;
-
-    /**
-     * Send bpData and return BufferStatusMessage that can be supplied to
-     * IClientManager::receive() in the receiving process.
-     *
-     * This function will be called from within the function
-     * objcpy(std::list<std::unique_ptr<C2Work>> -> WorkBundle).
-     *
-     * \param[in] bpData BufferPoolData identifying the buffer to send.
-     * \param[out] bpMessage BufferStatusMessage of the transaction. Information
-     *    inside \p bpMessage should be passed to the receiving process by some
-     *    other means so it can call receive() properly.
-     * \return ResultStatus value that determines the success of the operation.
-     *    (See the possible values of ResultStatus in
-     *    hardware/interfaces/media/bufferpool/2.0/types.hal.)
-     */
-    virtual ResultStatus send(
-            const std::shared_ptr<BufferPoolData>& bpData,
-            BufferStatusMessage* bpMessage) = 0;
-
-    virtual ~BufferPoolSender() = default;
+struct BufferPoolTypes {
+    typedef bufferpool::BufferPoolData              BufferPoolData;
+    typedef bufferpool::V2_0::ResultStatus          BufferPoolStatus;
+    typedef bufferpool::V2_0::ResultStatus          ResultStatus;
+    typedef bufferpool::V2_0::BufferStatusMessage   BufferStatusMessage;
 };
 
+typedef ::android::BufferPoolSender<BufferPoolTypes> BufferPoolSender;
+
 // Default implementation of BufferPoolSender.
 //
 // To use DefaultBufferPoolSender, the IClientManager instance of the receiving
@@ -198,7 +174,7 @@
     // Implementation of BufferPoolSender::send(). send() will establish a
     // bufferpool connection if needed, then send the bufferpool data over to
     // the receiving process.
-    virtual ResultStatus send(
+    ResultStatus send(
             const std::shared_ptr<BufferPoolData>& bpData,
             BufferStatusMessage* bpMessage) override;
 
diff --git a/media/codec2/hal/hidl/1.0/utils/types.cpp b/media/codec2/hal/hidl/1.0/utils/types.cpp
index e17aad4..abe5494 100644
--- a/media/codec2/hal/hidl/1.0/utils/types.cpp
+++ b/media/codec2/hal/hidl/1.0/utils/types.cpp
@@ -18,6 +18,8 @@
 #define LOG_TAG "Codec2-types"
 #include <android-base/logging.h>
 
+#include <bufferpool/ClientManager.h>
+#include <codec2/common/BufferTypes.h>
 #include <codec2/common/ParamTypes.h>
 #include <codec2/hidl/1.0/types.h>
 
@@ -32,9 +34,12 @@
 
 namespace android {
 
+using hardware::media::bufferpool::V2_0::implementation::ClientManager;
+using hardware::media::c2::V1_0::BaseBlock;
 using hardware::media::c2::V1_0::FieldSupportedValues;
 using hardware::media::c2::V1_0::PrimitiveValue;
 using hardware::media::c2::V1_0::ValueRange;
+using hardware::media::c2::V1_0::utils::BufferPoolTypes;
 using hardware::hidl_vec;
 
 // C2FieldSupportedValues -> FieldSupportedValues
@@ -112,6 +117,112 @@
     return true;
 }
 
+template<>
+bool objcpy(C2BaseBlock* d, const BaseBlock& s) {
+    switch (s.getDiscriminator()) {
+    case BaseBlock::hidl_discriminator::nativeBlock: {
+            if (s.nativeBlock() == nullptr) {
+                LOG(ERROR) << "Null BaseBlock::nativeBlock handle";
+                return false;
+            }
+            native_handle_t* sHandle =
+                    native_handle_clone(s.nativeBlock());
+            if (sHandle == nullptr) {
+                LOG(ERROR) << "Null BaseBlock::nativeBlock.";
+                return false;
+            }
+            const C2Handle *sC2Handle =
+                    reinterpret_cast<const C2Handle*>(sHandle);
+
+            d->linear = _C2BlockFactory::CreateLinearBlock(sC2Handle);
+            if (d->linear) {
+                d->type = C2BaseBlock::LINEAR;
+                return true;
+            }
+
+            d->graphic = _C2BlockFactory::CreateGraphicBlock(sC2Handle);
+            if (d->graphic) {
+                d->type = C2BaseBlock::GRAPHIC;
+                return true;
+            }
+
+            LOG(ERROR) << "Unknown handle type in BaseBlock::nativeBlock.";
+            if (sHandle) {
+                native_handle_close(sHandle);
+                native_handle_delete(sHandle);
+            }
+            return false;
+        }
+    case BaseBlock::hidl_discriminator::pooledBlock: {
+            const BufferPoolTypes::BufferStatusMessage &bpMessage =
+                    s.pooledBlock();
+            sp<ClientManager> bp = ClientManager::getInstance();
+            std::shared_ptr<BufferPoolTypes::BufferPoolData> bpData;
+            native_handle_t *cHandle;
+            BufferPoolTypes::BufferPoolStatus bpStatus = bp->receive(
+                    bpMessage.connectionId,
+                    bpMessage.transactionId,
+                    bpMessage.bufferId,
+                    bpMessage.timestampUs,
+                    &cHandle,
+                    &bpData);
+            if (bpStatus != BufferPoolTypes::ResultStatus::OK) {
+                LOG(ERROR) << "Failed to receive buffer from bufferpool -- "
+                           << "resultStatus = " << underlying_value(bpStatus)
+                           << ".";
+                return false;
+            } else if (!bpData) {
+                LOG(ERROR) << "No data in bufferpool transaction.";
+                return false;
+            }
+
+            d->linear = _C2BlockFactory::CreateLinearBlock(cHandle, bpData);
+            if (d->linear) {
+                d->type = C2BaseBlock::LINEAR;
+                return true;
+            }
+
+            d->graphic = _C2BlockFactory::CreateGraphicBlock(cHandle, bpData);
+            if (d->graphic) {
+                d->type = C2BaseBlock::GRAPHIC;
+                return true;
+            }
+            if (cHandle) {
+                // Though we got cloned handle, creating block failed.
+                native_handle_close(cHandle);
+                native_handle_delete(cHandle);
+            }
+
+            LOG(ERROR) << "Unknown handle type in BaseBlock::pooledBlock.";
+            return false;
+        }
+    default:
+        LOG(ERROR) << "Unrecognized BaseBlock's discriminator with "
+                   << "underlying value "
+                   << underlying_value(s.getDiscriminator()) << ".";
+        return false;
+    }
+}
+
+template<>
+void SetHandle(BaseBlock *block, const C2Handle *handle) {
+    block->nativeBlock(reinterpret_cast<const native_handle_t*>(handle));
+}
+
+template<>
+void SetPooledBlock<BufferPoolTypes>(
+        BaseBlock *baseBlock,
+        const typename BufferPoolTypes::BufferStatusMessage &pooledBlock) {
+    baseBlock->pooledBlock(pooledBlock);
+}
+
+template<>
+bool GetBufferPoolData<BufferPoolTypes>(
+        const std::shared_ptr<const _C2BlockPoolData>& blockPoolData,
+        std::shared_ptr<typename BufferPoolTypes::BufferPoolData> *bpData) {
+    return _C2BlockFactory::GetBufferPoolData(blockPoolData, bpData);
+}
+
 namespace hardware {
 namespace media {
 namespace c2 {
@@ -119,11 +230,8 @@
 namespace utils {
 
 using ::android::hardware::media::bufferpool::BufferPoolData;
-using ::android::hardware::media::bufferpool::V2_0::BufferStatusMessage;
 using ::android::hardware::media::bufferpool::V2_0::ResultStatus;
 using ::android::hardware::media::bufferpool::V2_0::implementation::
-        ClientManager;
-using ::android::hardware::media::bufferpool::V2_0::implementation::
         TransactionId;
 
 const char* asString(Status status, const char* def) {
@@ -204,320 +312,6 @@
     return ::android::objcpy(d, s);
 }
 
-namespace /* unnamed */ {
-
-// Find or add a hidl BaseBlock object from a given C2Handle* to a list and an
-// associated map.
-// Note: The handle is not cloned.
-bool _addBaseBlock(
-        uint32_t* index,
-        const C2Handle* handle,
-        std::list<BaseBlock>* baseBlocks,
-        std::map<const void*, uint32_t>* baseBlockIndices) {
-    if (!handle) {
-        LOG(ERROR) << "addBaseBlock called on a null C2Handle.";
-        return false;
-    }
-    auto it = baseBlockIndices->find(handle);
-    if (it != baseBlockIndices->end()) {
-        *index = it->second;
-    } else {
-        *index = baseBlocks->size();
-        baseBlockIndices->emplace(handle, *index);
-        baseBlocks->emplace_back();
-
-        BaseBlock &dBaseBlock = baseBlocks->back();
-        // This does not clone the handle.
-        dBaseBlock.nativeBlock(
-                reinterpret_cast<const native_handle_t*>(handle));
-    }
-    return true;
-}
-
-// Find or add a hidl BaseBlock object from a given BufferPoolData to a list and
-// an associated map.
-bool _addBaseBlock(
-        uint32_t* index,
-        const std::shared_ptr<BufferPoolData> bpData,
-        BufferPoolSender* bufferPoolSender,
-        std::list<BaseBlock>* baseBlocks,
-        std::map<const void*, uint32_t>* baseBlockIndices) {
-    if (!bpData) {
-        LOG(ERROR) << "addBaseBlock called on a null BufferPoolData.";
-        return false;
-    }
-    auto it = baseBlockIndices->find(bpData.get());
-    if (it != baseBlockIndices->end()) {
-        *index = it->second;
-    } else {
-        *index = baseBlocks->size();
-        baseBlockIndices->emplace(bpData.get(), *index);
-        baseBlocks->emplace_back();
-
-        BaseBlock &dBaseBlock = baseBlocks->back();
-
-        if (bufferPoolSender) {
-            BufferStatusMessage pooledBlock;
-            ResultStatus bpStatus = bufferPoolSender->send(
-                    bpData,
-                    &pooledBlock);
-
-            if (bpStatus != ResultStatus::OK) {
-                LOG(ERROR) << "Failed to send buffer with BufferPool. Error: "
-                           << static_cast<int32_t>(bpStatus)
-                           << ".";
-                return false;
-            }
-            dBaseBlock.pooledBlock(pooledBlock);
-        }
-    }
-    return true;
-}
-
-bool addBaseBlock(
-        uint32_t* index,
-        const C2Handle* handle,
-        const std::shared_ptr<const _C2BlockPoolData>& blockPoolData,
-        BufferPoolSender* bufferPoolSender,
-        std::list<BaseBlock>* baseBlocks,
-        std::map<const void*, uint32_t>* baseBlockIndices) {
-    if (!blockPoolData) {
-        // No BufferPoolData ==> NATIVE block.
-        return _addBaseBlock(
-                index, handle,
-                baseBlocks, baseBlockIndices);
-    }
-    switch (blockPoolData->getType()) {
-    case _C2BlockPoolData::TYPE_BUFFERPOOL: {
-            // BufferPoolData
-            std::shared_ptr<BufferPoolData> bpData;
-            if (!_C2BlockFactory::GetBufferPoolData(blockPoolData, &bpData)
-                    || !bpData) {
-                LOG(ERROR) << "BufferPoolData unavailable in a block.";
-                return false;
-            }
-            return _addBaseBlock(
-                    index, bpData,
-                    bufferPoolSender, baseBlocks, baseBlockIndices);
-        }
-    case _C2BlockPoolData::TYPE_BUFFERQUEUE:
-        uint32_t gen;
-        uint64_t bqId;
-        int32_t bqSlot;
-        // Update handle if migration happened.
-        if (_C2BlockFactory::GetBufferQueueData(
-                blockPoolData, &gen, &bqId, &bqSlot)) {
-            android::MigrateNativeCodec2GrallocHandle(
-                    const_cast<native_handle_t*>(handle), gen, bqId, bqSlot);
-        }
-        return _addBaseBlock(
-                index, handle,
-                baseBlocks, baseBlockIndices);
-    default:
-        LOG(ERROR) << "Unknown C2BlockPoolData type.";
-        return false;
-    }
-}
-
-// C2Fence -> hidl_handle
-// Note: File descriptors are not duplicated. The original file descriptor must
-// not be closed before the transaction is complete.
-bool objcpy(hidl_handle* d, const C2Fence& s) {
-    d->setTo(nullptr);
-    native_handle_t* handle = _C2FenceFactory::CreateNativeHandle(s);
-    if (handle) {
-        d->setTo(handle, true /* owns */);
-//  } else if (!s.ready()) {
-//      // TODO: we should wait for unmarshallable fences but this may not be
-//      // the best place for it. We can safely ignore here as at this time
-//      // all fences used here are marshallable.
-    }
-    return true;
-}
-
-// C2ConstLinearBlock -> Block
-// Note: Native handles are not duplicated. The original handles must not be
-// closed before the transaction is complete.
-bool objcpy(Block* d, const C2ConstLinearBlock& s,
-        BufferPoolSender* bufferPoolSender,
-        std::list<BaseBlock>* baseBlocks,
-        std::map<const void*, uint32_t>* baseBlockIndices) {
-    std::shared_ptr<const _C2BlockPoolData> bpData =
-            _C2BlockFactory::GetLinearBlockPoolData(s);
-    if (!addBaseBlock(&d->index, s.handle(), bpData,
-            bufferPoolSender, baseBlocks, baseBlockIndices)) {
-        LOG(ERROR) << "Invalid block data in C2ConstLinearBlock.";
-        return false;
-    }
-
-    // Create the metadata.
-    C2Hidl_RangeInfo dRangeInfo;
-    dRangeInfo.offset = static_cast<uint32_t>(s.offset());
-    dRangeInfo.length = static_cast<uint32_t>(s.size());
-    if (!createParamsBlob(&d->meta, std::vector<C2Param*>{ &dRangeInfo })) {
-        LOG(ERROR) << "Invalid range info in C2ConstLinearBlock.";
-        return false;
-    }
-
-    // Copy the fence
-    if (!objcpy(&d->fence, s.fence())) {
-        LOG(ERROR) << "Invalid C2ConstLinearBlock::fence.";
-        return false;
-    }
-    return true;
-}
-
-// C2ConstGraphicBlock -> Block
-// Note: Native handles are not duplicated. The original handles must not be
-// closed before the transaction is complete.
-bool objcpy(Block* d, const C2ConstGraphicBlock& s,
-        BufferPoolSender* bufferPoolSender,
-        std::list<BaseBlock>* baseBlocks,
-        std::map<const void*, uint32_t>* baseBlockIndices) {
-    std::shared_ptr<const _C2BlockPoolData> bpData =
-            _C2BlockFactory::GetGraphicBlockPoolData(s);
-    if (!addBaseBlock(&d->index, s.handle(), bpData,
-            bufferPoolSender, baseBlocks, baseBlockIndices)) {
-        LOG(ERROR) << "Invalid block data in C2ConstGraphicBlock.";
-        return false;
-    }
-
-    // Create the metadata.
-    C2Hidl_RectInfo dRectInfo;
-    C2Rect sRect = s.crop();
-    dRectInfo.left = static_cast<uint32_t>(sRect.left);
-    dRectInfo.top = static_cast<uint32_t>(sRect.top);
-    dRectInfo.width = static_cast<uint32_t>(sRect.width);
-    dRectInfo.height = static_cast<uint32_t>(sRect.height);
-    if (!createParamsBlob(&d->meta, std::vector<C2Param*>{ &dRectInfo })) {
-        LOG(ERROR) << "Invalid rect info in C2ConstGraphicBlock.";
-        return false;
-    }
-
-    // Copy the fence
-    if (!objcpy(&d->fence, s.fence())) {
-        LOG(ERROR) << "Invalid C2ConstGraphicBlock::fence.";
-        return false;
-    }
-    return true;
-}
-
-// C2BufferData -> Buffer
-// This function only fills in d->blocks.
-bool objcpy(Buffer* d, const C2BufferData& s,
-        BufferPoolSender* bufferPoolSender,
-        std::list<BaseBlock>* baseBlocks,
-        std::map<const void*, uint32_t>* baseBlockIndices) {
-    d->blocks.resize(
-            s.linearBlocks().size() +
-            s.graphicBlocks().size());
-    size_t i = 0;
-    for (const C2ConstLinearBlock& linearBlock : s.linearBlocks()) {
-        Block& dBlock = d->blocks[i++];
-        if (!objcpy(
-                &dBlock, linearBlock,
-                bufferPoolSender, baseBlocks, baseBlockIndices)) {
-            LOG(ERROR) << "Invalid C2BufferData::linearBlocks. "
-                       << "(Destination index = " << i - 1 << ".)";
-            return false;
-        }
-    }
-    for (const C2ConstGraphicBlock& graphicBlock : s.graphicBlocks()) {
-        Block& dBlock = d->blocks[i++];
-        if (!objcpy(
-                &dBlock, graphicBlock,
-                bufferPoolSender, baseBlocks, baseBlockIndices)) {
-            LOG(ERROR) << "Invalid C2BufferData::graphicBlocks. "
-                       << "(Destination index = " << i - 1 << ".)";
-            return false;
-        }
-    }
-    return true;
-}
-
-// C2Buffer -> Buffer
-bool objcpy(Buffer* d, const C2Buffer& s,
-        BufferPoolSender* bufferPoolSender,
-        std::list<BaseBlock>* baseBlocks,
-        std::map<const void*, uint32_t>* baseBlockIndices) {
-    if (!createParamsBlob(&d->info, s.info())) {
-        LOG(ERROR) << "Invalid C2Buffer::info.";
-        return false;
-    }
-    if (!objcpy(d, s.data(), bufferPoolSender, baseBlocks, baseBlockIndices)) {
-        LOG(ERROR) << "Invalid C2Buffer::data.";
-        return false;
-    }
-    return true;
-}
-
-// C2InfoBuffer -> InfoBuffer
-bool objcpy(InfoBuffer* d, const C2InfoBuffer& s,
-        BufferPoolSender* bufferPoolSender,
-        std::list<BaseBlock>* baseBlocks,
-        std::map<const void*, uint32_t>* baseBlockIndices) {
-    d->index = static_cast<ParamIndex>(s.index());
-    Buffer& dBuffer = d->buffer;
-    if (!objcpy(&dBuffer, s.data(), bufferPoolSender, baseBlocks, baseBlockIndices)) {
-        LOG(ERROR) << "Invalid C2InfoBuffer::data";
-        return false;
-    }
-    return true;
-}
-
-// C2FrameData -> FrameData
-bool objcpy(FrameData* d, const C2FrameData& s,
-        BufferPoolSender* bufferPoolSender,
-        std::list<BaseBlock>* baseBlocks,
-        std::map<const void*, uint32_t>* baseBlockIndices) {
-    d->flags = static_cast<hidl_bitfield<FrameData::Flags>>(s.flags);
-    if (!::android::objcpy(&d->ordinal, s.ordinal)) {
-        LOG(ERROR) << "Invalid C2FrameData::ordinal.";
-        return false;
-    }
-
-    d->buffers.resize(s.buffers.size());
-    size_t i = 0;
-    for (const std::shared_ptr<C2Buffer>& sBuffer : s.buffers) {
-        Buffer& dBuffer = d->buffers[i++];
-        if (!sBuffer) {
-            // A null (pointer to) C2Buffer corresponds to a Buffer with empty
-            // info and blocks.
-            dBuffer.info.resize(0);
-            dBuffer.blocks.resize(0);
-            continue;
-        }
-        if (!objcpy(
-                &dBuffer, *sBuffer,
-                bufferPoolSender, baseBlocks, baseBlockIndices)) {
-            LOG(ERROR) << "Invalid C2FrameData::buffers["
-                       << i - 1 << "].";
-            return false;
-        }
-    }
-
-    if (!createParamsBlob(&d->configUpdate, s.configUpdate)) {
-        LOG(ERROR) << "Invalid C2FrameData::configUpdate.";
-        return false;
-    }
-
-    d->infoBuffers.resize(s.infoBuffers.size());
-    i = 0;
-    for (const C2InfoBuffer& sInfoBuffer : s.infoBuffers) {
-        InfoBuffer& dInfoBuffer = d->infoBuffers[i++];
-        if (!objcpy(&dInfoBuffer, sInfoBuffer,
-                bufferPoolSender, baseBlocks, baseBlockIndices)) {
-            LOG(ERROR) << "Invalid C2FrameData::infoBuffers["
-                       << i - 1 << "].";
-            return false;
-        }
-    }
-
-    return true;
-}
-
-} // unnamed namespace
-
 // DefaultBufferPoolSender's implementation
 
 DefaultBufferPoolSender::DefaultBufferPoolSender(
@@ -621,549 +415,12 @@
         WorkBundle* d,
         const std::list<std::unique_ptr<C2Work>>& s,
         BufferPoolSender* bufferPoolSender) {
-    // baseBlocks holds a list of BaseBlock objects that Blocks can refer to.
-    std::list<BaseBlock> baseBlocks;
-
-    // baseBlockIndices maps a raw pointer to native_handle_t or BufferPoolData
-    // inside baseBlocks to the corresponding index into baseBlocks. The keys
-    // (pointers) are used to identify blocks that have the same "base block" in
-    // s, a list of C2Work objects. Because baseBlocks will be copied into a
-    // hidl_vec eventually, the values of baseBlockIndices are zero-based
-    // integer indices instead of list iterators.
-    //
-    // Note that the pointers can be raw because baseBlockIndices has a shorter
-    // lifespan than all of base blocks.
-    std::map<const void*, uint32_t> baseBlockIndices;
-
-    d->works.resize(s.size());
-    size_t i = 0;
-    for (const std::unique_ptr<C2Work>& sWork : s) {
-        Work &dWork = d->works[i++];
-        if (!sWork) {
-            LOG(WARNING) << "Null C2Work encountered.";
-            continue;
-        }
-
-        // chain info is not in use currently.
-
-        // input
-        if (!objcpy(&dWork.input, sWork->input,
-                bufferPoolSender, &baseBlocks, &baseBlockIndices)) {
-            LOG(ERROR) << "Invalid C2Work::input.";
-            return false;
-        }
-
-        // worklets
-        if (sWork->worklets.size() == 0) {
-            LOG(DEBUG) << "Work with no worklets.";
-        } else {
-            // Parcel the worklets.
-            hidl_vec<Worklet> &dWorklets = dWork.worklets;
-            dWorklets.resize(sWork->worklets.size());
-            size_t j = 0;
-            for (const std::unique_ptr<C2Worklet>& sWorklet : sWork->worklets)
-            {
-                if (!sWorklet) {
-                    LOG(WARNING) << "Null C2Work::worklets["
-                                 << j << "].";
-                    continue;
-                }
-                Worklet &dWorklet = dWorklets[j++];
-
-                // component id
-                dWorklet.componentId = static_cast<uint32_t>(
-                        sWorklet->component);
-
-                // tunings
-                if (!createParamsBlob(&dWorklet.tunings, sWorklet->tunings)) {
-                    LOG(ERROR) << "Invalid C2Work::worklets["
-                               << j - 1 << "]->tunings.";
-                    return false;
-                }
-
-                // failures
-                dWorklet.failures.resize(sWorklet->failures.size());
-                size_t k = 0;
-                for (const std::unique_ptr<C2SettingResult>& sFailure :
-                        sWorklet->failures) {
-                    if (!sFailure) {
-                        LOG(WARNING) << "Null C2Work::worklets["
-                                     << j - 1 << "]->failures["
-                                     << k << "].";
-                        continue;
-                    }
-                    if (!objcpy(&dWorklet.failures[k++], *sFailure)) {
-                        LOG(ERROR) << "Invalid C2Work::worklets["
-                                   << j - 1 << "]->failures["
-                                   << k - 1 << "].";
-                        return false;
-                    }
-                }
-
-                // output
-                if (!objcpy(&dWorklet.output, sWorklet->output,
-                        bufferPoolSender, &baseBlocks, &baseBlockIndices)) {
-                    LOG(ERROR) << "Invalid C2Work::worklets["
-                               << j - 1 << "]->output.";
-                    return false;
-                }
-            }
-        }
-
-        // worklets processed
-        dWork.workletsProcessed = sWork->workletsProcessed;
-
-        // result
-        dWork.result = static_cast<Status>(sWork->result);
-    }
-
-    // Copy std::list<BaseBlock> to hidl_vec<BaseBlock>.
-    {
-        d->baseBlocks.resize(baseBlocks.size());
-        size_t i = 0;
-        for (const BaseBlock& baseBlock : baseBlocks) {
-            d->baseBlocks[i++] = baseBlock;
-        }
-    }
-
-    return true;
+    return ::android::objcpy(d, s, bufferPoolSender);
 }
 
-namespace /* unnamed */ {
-
-struct C2BaseBlock {
-    enum type_t {
-        LINEAR,
-        GRAPHIC,
-    };
-    type_t type;
-    std::shared_ptr<C2LinearBlock> linear;
-    std::shared_ptr<C2GraphicBlock> graphic;
-};
-
-// hidl_handle -> C2Fence
-// Note: File descriptors are not duplicated. The original file descriptor must
-// not be closed before the transaction is complete.
-bool objcpy(C2Fence* d, const hidl_handle& s) {
-    const native_handle_t* handle = s.getNativeHandle();
-    *d = _C2FenceFactory::CreateFromNativeHandle(handle);
-    return true;
-}
-
-// C2LinearBlock, vector<C2Param*>, C2Fence -> C2Buffer
-bool createLinearBuffer(
-        std::shared_ptr<C2Buffer>* buffer,
-        const std::shared_ptr<C2LinearBlock>& block,
-        const std::vector<C2Param*>& meta,
-        const C2Fence& fence) {
-    // Check the block meta. It should have exactly 1 C2Info:
-    // C2Hidl_RangeInfo.
-    if ((meta.size() != 1) || !meta[0]) {
-        LOG(ERROR) << "Invalid C2LinearBlock::meta.";
-        return false;
-    }
-    if (meta[0]->size() != sizeof(C2Hidl_RangeInfo)) {
-        LOG(ERROR) << "Invalid range info in C2LinearBlock.";
-        return false;
-    }
-    C2Hidl_RangeInfo *rangeInfo =
-            reinterpret_cast<C2Hidl_RangeInfo*>(meta[0]);
-
-    // Create C2Buffer from C2LinearBlock.
-    *buffer = C2Buffer::CreateLinearBuffer(block->share(
-            rangeInfo->offset, rangeInfo->length,
-            fence));
-    if (!(*buffer)) {
-        LOG(ERROR) << "CreateLinearBuffer failed.";
-        return false;
-    }
-    return true;
-}
-
-// C2GraphicBlock, vector<C2Param*>, C2Fence -> C2Buffer
-bool createGraphicBuffer(
-        std::shared_ptr<C2Buffer>* buffer,
-        const std::shared_ptr<C2GraphicBlock>& block,
-        const std::vector<C2Param*>& meta,
-        const C2Fence& fence) {
-    // Check the block meta. It should have exactly 1 C2Info:
-    // C2Hidl_RectInfo.
-    if ((meta.size() != 1) || !meta[0]) {
-        LOG(ERROR) << "Invalid C2GraphicBlock::meta.";
-        return false;
-    }
-    if (meta[0]->size() != sizeof(C2Hidl_RectInfo)) {
-        LOG(ERROR) << "Invalid rect info in C2GraphicBlock.";
-        return false;
-    }
-    C2Hidl_RectInfo *rectInfo =
-            reinterpret_cast<C2Hidl_RectInfo*>(meta[0]);
-
-    // Create C2Buffer from C2GraphicBlock.
-    *buffer = C2Buffer::CreateGraphicBuffer(block->share(
-            C2Rect(rectInfo->width, rectInfo->height).
-            at(rectInfo->left, rectInfo->top),
-            fence));
-    if (!(*buffer)) {
-        LOG(ERROR) << "CreateGraphicBuffer failed.";
-        return false;
-    }
-    return true;
-}
-
-// Buffer -> C2Buffer
-// Note: The native handles will be cloned.
-bool objcpy(std::shared_ptr<C2Buffer>* d, const Buffer& s,
-        const std::vector<C2BaseBlock>& baseBlocks) {
-    *d = nullptr;
-
-    // Currently, a non-null C2Buffer must contain exactly 1 block.
-    if (s.blocks.size() == 0) {
-        return true;
-    } else if (s.blocks.size() != 1) {
-        LOG(ERROR) << "Invalid Buffer: "
-                      "Currently, a C2Buffer must contain exactly 1 block.";
-        return false;
-    }
-
-    const Block &sBlock = s.blocks[0];
-    if (sBlock.index >= baseBlocks.size()) {
-        LOG(ERROR) << "Invalid Buffer::blocks[0].index: "
-                      "Array index out of range.";
-        return false;
-    }
-    const C2BaseBlock &baseBlock = baseBlocks[sBlock.index];
-
-    // Parse meta.
-    std::vector<C2Param*> sBlockMeta;
-    if (!parseParamsBlob(&sBlockMeta, sBlock.meta)) {
-        LOG(ERROR) << "Invalid Buffer::blocks[0].meta.";
-        return false;
-    }
-
-    // Copy fence.
-    C2Fence dFence;
-    if (!objcpy(&dFence, sBlock.fence)) {
-        LOG(ERROR) << "Invalid Buffer::blocks[0].fence.";
-        return false;
-    }
-
-    // Construct a block.
-    switch (baseBlock.type) {
-    case C2BaseBlock::LINEAR:
-        if (!createLinearBuffer(d, baseBlock.linear, sBlockMeta, dFence)) {
-            LOG(ERROR) << "Invalid C2BaseBlock::linear.";
-            return false;
-        }
-        break;
-    case C2BaseBlock::GRAPHIC:
-        if (!createGraphicBuffer(d, baseBlock.graphic, sBlockMeta, dFence)) {
-            LOG(ERROR) << "Invalid C2BaseBlock::graphic.";
-            return false;
-        }
-        break;
-    default:
-        LOG(ERROR) << "Invalid C2BaseBlock::type.";
-        return false;
-    }
-
-    // Parse info
-    std::vector<C2Param*> params;
-    if (!parseParamsBlob(&params, s.info)) {
-        LOG(ERROR) << "Invalid Buffer::info.";
-        return false;
-    }
-    for (C2Param* param : params) {
-        if (param == nullptr) {
-            LOG(ERROR) << "Null param in Buffer::info.";
-            return false;
-        }
-        std::shared_ptr<C2Param> c2param{
-                C2Param::Copy(*param).release()};
-        if (!c2param) {
-            LOG(ERROR) << "Invalid param in Buffer::info.";
-            return false;
-        }
-        c2_status_t status =
-                (*d)->setInfo(std::static_pointer_cast<C2Info>(c2param));
-        if (status != C2_OK) {
-            LOG(ERROR) << "C2Buffer::setInfo failed.";
-            return false;
-        }
-    }
-
-    return true;
-}
-
-// InfoBuffer -> C2InfoBuffer
-bool objcpy(std::vector<C2InfoBuffer> *d, const InfoBuffer& s,
-        const std::vector<C2BaseBlock>& baseBlocks) {
-
-    // Currently, a non-null C2InfoBufer must contain exactly 1 block.
-    if (s.buffer.blocks.size() == 0) {
-        return true;
-    } else if (s.buffer.blocks.size() != 1) {
-        LOG(ERROR) << "Invalid InfoBuffer::Buffer "
-                      "Currently, a C2InfoBuffer must contain exactly 1 block.";
-        return false;
-    }
-
-    const Block &sBlock = s.buffer.blocks[0];
-    if (sBlock.index >= baseBlocks.size()) {
-        LOG(ERROR) << "Invalid InfoBuffer::Buffer::blocks[0].index: "
-                      "Array index out of range.";
-        return false;
-    }
-    const C2BaseBlock &baseBlock = baseBlocks[sBlock.index];
-
-    // Parse meta.
-    std::vector<C2Param*> sBlockMeta;
-    if (!parseParamsBlob(&sBlockMeta, sBlock.meta)) {
-        LOG(ERROR) << "Invalid InfoBuffer::Buffer::blocks[0].meta.";
-        return false;
-    }
-
-    // Copy fence.
-    C2Fence dFence;
-    if (!objcpy(&dFence, sBlock.fence)) {
-        LOG(ERROR) << "Invalid InfoBuffer::Buffer::blocks[0].fence.";
-        return false;
-    }
-
-    // Construct a block.
-    switch (baseBlock.type) {
-    case C2BaseBlock::LINEAR:
-        if (sBlockMeta.size() == 1 && sBlockMeta[0] != nullptr &&
-            sBlockMeta[0]->size() == sizeof(C2Hidl_RangeInfo)) {
-            C2Hidl_RangeInfo *rangeInfo =
-                    reinterpret_cast<C2Hidl_RangeInfo*>(sBlockMeta[0]);
-            d->emplace_back(C2InfoBuffer::CreateLinearBuffer(
-                    s.index,
-                    baseBlock.linear->share(
-                            rangeInfo->offset, rangeInfo->length, dFence)));
-            return true;
-        }
-        LOG(ERROR) << "Invalid Meta for C2BaseBlock::Linear InfoBuffer.";
-        break;
-    case C2BaseBlock::GRAPHIC:
-        // It's not used now
-        LOG(ERROR) << "Non-Used C2BaseBlock::type for InfoBuffer.";
-        break;
-    default:
-        LOG(ERROR) << "Invalid C2BaseBlock::type for InfoBuffer.";
-        break;
-    }
-
-    return false;
-}
-
-// FrameData -> C2FrameData
-bool objcpy(C2FrameData* d, const FrameData& s,
-        const std::vector<C2BaseBlock>& baseBlocks) {
-    d->flags = static_cast<C2FrameData::flags_t>(s.flags);
-    if (!::android::objcpy(&d->ordinal, s.ordinal)) {
-        LOG(ERROR) << "Invalid FrameData::ordinal.";
-        return false;
-    }
-    d->buffers.clear();
-    d->buffers.reserve(s.buffers.size());
-    for (const Buffer& sBuffer : s.buffers) {
-        std::shared_ptr<C2Buffer> dBuffer;
-        if (!objcpy(&dBuffer, sBuffer, baseBlocks)) {
-            LOG(ERROR) << "Invalid FrameData::buffers.";
-            return false;
-        }
-        d->buffers.emplace_back(dBuffer);
-    }
-
-    std::vector<C2Param*> params;
-    if (!parseParamsBlob(&params, s.configUpdate)) {
-        LOG(ERROR) << "Invalid FrameData::configUpdate.";
-        return false;
-    }
-    d->configUpdate.clear();
-    for (C2Param* param : params) {
-        d->configUpdate.emplace_back(C2Param::Copy(*param));
-        if (!d->configUpdate.back()) {
-            LOG(ERROR) << "Unexpected error while parsing "
-                          "FrameData::configUpdate.";
-            return false;
-        }
-    }
-
-    d->infoBuffers.clear();
-    if (s.infoBuffers.size() == 0) {
-        // InfoBuffer is optional
-        return true;
-    }
-    d->infoBuffers.reserve(s.infoBuffers.size());
-    for (const InfoBuffer &sInfoBuffer: s.infoBuffers) {
-        if (!objcpy(&(d->infoBuffers), sInfoBuffer, baseBlocks)) {
-            LOG(ERROR) << "Invalid Framedata::infoBuffers.";
-            return false;
-        }
-    }
-    return true;
-}
-
-// BaseBlock -> C2BaseBlock
-bool objcpy(C2BaseBlock* d, const BaseBlock& s) {
-    switch (s.getDiscriminator()) {
-    case BaseBlock::hidl_discriminator::nativeBlock: {
-            if (s.nativeBlock() == nullptr) {
-                LOG(ERROR) << "Null BaseBlock::nativeBlock handle";
-                return false;
-            }
-            native_handle_t* sHandle =
-                    native_handle_clone(s.nativeBlock());
-            if (sHandle == nullptr) {
-                LOG(ERROR) << "Null BaseBlock::nativeBlock.";
-                return false;
-            }
-            const C2Handle *sC2Handle =
-                    reinterpret_cast<const C2Handle*>(sHandle);
-
-            d->linear = _C2BlockFactory::CreateLinearBlock(sC2Handle);
-            if (d->linear) {
-                d->type = C2BaseBlock::LINEAR;
-                return true;
-            }
-
-            d->graphic = _C2BlockFactory::CreateGraphicBlock(sC2Handle);
-            if (d->graphic) {
-                d->type = C2BaseBlock::GRAPHIC;
-                return true;
-            }
-
-            LOG(ERROR) << "Unknown handle type in BaseBlock::nativeBlock.";
-            if (sHandle) {
-                native_handle_close(sHandle);
-                native_handle_delete(sHandle);
-            }
-            return false;
-        }
-    case BaseBlock::hidl_discriminator::pooledBlock: {
-            const BufferStatusMessage &bpMessage =
-                    s.pooledBlock();
-            sp<ClientManager> bp = ClientManager::getInstance();
-            std::shared_ptr<BufferPoolData> bpData;
-            native_handle_t *cHandle;
-            ResultStatus bpStatus = bp->receive(
-                    bpMessage.connectionId,
-                    bpMessage.transactionId,
-                    bpMessage.bufferId,
-                    bpMessage.timestampUs,
-                    &cHandle,
-                    &bpData);
-            if (bpStatus != ResultStatus::OK) {
-                LOG(ERROR) << "Failed to receive buffer from bufferpool -- "
-                           << "resultStatus = " << underlying_value(bpStatus)
-                           << ".";
-                return false;
-            } else if (!bpData) {
-                LOG(ERROR) << "No data in bufferpool transaction.";
-                return false;
-            }
-
-            d->linear = _C2BlockFactory::CreateLinearBlock(cHandle, bpData);
-            if (d->linear) {
-                d->type = C2BaseBlock::LINEAR;
-                return true;
-            }
-
-            d->graphic = _C2BlockFactory::CreateGraphicBlock(cHandle, bpData);
-            if (d->graphic) {
-                d->type = C2BaseBlock::GRAPHIC;
-                return true;
-            }
-            if (cHandle) {
-                // Though we got cloned handle, creating block failed.
-                native_handle_close(cHandle);
-                native_handle_delete(cHandle);
-            }
-
-            LOG(ERROR) << "Unknown handle type in BaseBlock::pooledBlock.";
-            return false;
-        }
-    default:
-        LOG(ERROR) << "Unrecognized BaseBlock's discriminator with "
-                   << "underlying value "
-                   << underlying_value(s.getDiscriminator()) << ".";
-        return false;
-    }
-}
-
-} // unnamed namespace
-
 // WorkBundle -> std::list<std::unique_ptr<C2Work>>
 bool objcpy(std::list<std::unique_ptr<C2Work>>* d, const WorkBundle& s) {
-    // Convert BaseBlocks to C2BaseBlocks.
-    std::vector<C2BaseBlock> dBaseBlocks(s.baseBlocks.size());
-    for (size_t i = 0; i < s.baseBlocks.size(); ++i) {
-        if (!objcpy(&dBaseBlocks[i], s.baseBlocks[i])) {
-            LOG(ERROR) << "Invalid WorkBundle::baseBlocks["
-                       << i << "].";
-            return false;
-        }
-    }
-
-    d->clear();
-    for (const Work& sWork : s.works) {
-        d->emplace_back(std::make_unique<C2Work>());
-        C2Work& dWork = *d->back();
-
-        // chain info is not in use currently.
-
-        // input
-        if (!objcpy(&dWork.input, sWork.input, dBaseBlocks)) {
-            LOG(ERROR) << "Invalid Work::input.";
-            return false;
-        }
-
-        // worklet(s)
-        dWork.worklets.clear();
-        for (const Worklet& sWorklet : sWork.worklets) {
-            std::unique_ptr<C2Worklet> dWorklet = std::make_unique<C2Worklet>();
-
-            // component id
-            dWorklet->component = static_cast<c2_node_id_t>(
-                    sWorklet.componentId);
-
-            // tunings
-            if (!copyParamsFromBlob(&dWorklet->tunings, sWorklet.tunings)) {
-                LOG(ERROR) << "Invalid Worklet::tunings";
-                return false;
-            }
-
-            // failures
-            dWorklet->failures.clear();
-            dWorklet->failures.reserve(sWorklet.failures.size());
-            for (const SettingResult& sFailure : sWorklet.failures) {
-                std::unique_ptr<C2SettingResult> dFailure;
-                if (!objcpy(&dFailure, sFailure)) {
-                    LOG(ERROR) << "Invalid Worklet::failures.";
-                    return false;
-                }
-                dWorklet->failures.emplace_back(std::move(dFailure));
-            }
-
-            // output
-            if (!objcpy(&dWorklet->output, sWorklet.output, dBaseBlocks)) {
-                LOG(ERROR) << "Invalid Worklet::output.";
-                return false;
-            }
-
-            dWork.worklets.emplace_back(std::move(dWorklet));
-        }
-
-        // workletsProcessed
-        dWork.workletsProcessed = sWork.workletsProcessed;
-
-        // result
-        dWork.result = static_cast<c2_status_t>(sWork.result);
-    }
-
-    return true;
+    return ::android::objcpy(d, s);
 }
 
 // Params -> std::vector<C2Param*>
@@ -1247,92 +504,35 @@
     }
 }
 
-namespace /* unnamed */ {
-
-template <typename BlockProcessor>
-void forEachBlock(C2FrameData& frameData,
-                  BlockProcessor process) {
-    for (const std::shared_ptr<C2Buffer>& buffer : frameData.buffers) {
-        if (buffer) {
-            for (const C2ConstGraphicBlock& block :
-                    buffer->data().graphicBlocks()) {
-                process(block);
-            }
-        }
-    }
-}
-
-template <typename BlockProcessor>
-void forEachBlock(const std::list<std::unique_ptr<C2Work>>& workList,
-                  BlockProcessor process,
-                  bool processInput, bool processOutput) {
-    for (const std::unique_ptr<C2Work>& work : workList) {
-        if (!work) {
-            continue;
-        }
-        if (processInput) {
-            forEachBlock(work->input, process);
-        }
-        if (processOutput) {
-            for (const std::unique_ptr<C2Worklet>& worklet : work->worklets) {
-                if (worklet) {
-                    forEachBlock(worklet->output,
-                                 process);
-                }
-            }
-        }
-    }
-}
-
-} // unnamed namespace
-
+// BufferQueue-Based Block Operations
 bool beginTransferBufferQueueBlock(const C2ConstGraphicBlock& block) {
-    std::shared_ptr<_C2BlockPoolData> data =
-            _C2BlockFactory::GetGraphicBlockPoolData(block);
-    if (data && _C2BlockFactory::GetBufferQueueData(data)) {
-        _C2BlockFactory::BeginTransferBlockToClient(data);
-        return true;
-    }
-    return false;
+    return ::android::BeginTransferBufferQueueBlock(block);
 }
 
 void beginTransferBufferQueueBlocks(
         const std::list<std::unique_ptr<C2Work>>& workList,
-        bool processInput, bool processOutput) {
-    forEachBlock(workList, beginTransferBufferQueueBlock,
-                 processInput, processOutput);
+        bool processInput,
+        bool processOutput) {
+    return ::android::BeginTransferBufferQueueBlocks(
+            workList, processInput, processOutput);
 }
 
-bool endTransferBufferQueueBlock(
-        const C2ConstGraphicBlock& block,
-        bool transfer) {
-    std::shared_ptr<_C2BlockPoolData> data =
-            _C2BlockFactory::GetGraphicBlockPoolData(block);
-    if (data && _C2BlockFactory::GetBufferQueueData(data)) {
-        _C2BlockFactory::EndTransferBlockToClient(data, transfer);
-        return true;
-    }
-    return false;
+bool endTransferBufferQueueBlock(const C2ConstGraphicBlock& block,
+                                 bool transfer) {
+    return ::android::EndTransferBufferQueueBlock(block, transfer);
 }
 
 void endTransferBufferQueueBlocks(
         const std::list<std::unique_ptr<C2Work>>& workList,
         bool transfer,
-        bool processInput, bool processOutput) {
-    forEachBlock(workList,
-                 std::bind(endTransferBufferQueueBlock,
-                           std::placeholders::_1, transfer),
-                 processInput, processOutput);
+        bool processInput,
+        bool processOutput) {
+    return ::android::EndTransferBufferQueueBlocks(
+            workList, transfer, processInput, processOutput);
 }
 
 bool displayBufferQueueBlock(const C2ConstGraphicBlock& block) {
-    std::shared_ptr<_C2BlockPoolData> data =
-            _C2BlockFactory::GetGraphicBlockPoolData(block);
-    if (data && _C2BlockFactory::GetBufferQueueData(data)) {
-        _C2BlockFactory::DisplayBlockToBufferQueue(data);
-        return true;
-    }
-    return false;
+    return ::android::DisplayBufferQueueBlock(block);
 }
 
 }  // namespace utils
diff --git a/media/codec2/vndk/Android.bp b/media/codec2/vndk/Android.bp
index ba25226..a59bd47 100644
--- a/media/codec2/vndk/Android.bp
+++ b/media/codec2/vndk/Android.bp
@@ -173,6 +173,7 @@
         "libbase", // for C2_LOG
         "liblog", // for ALOG
         "libcodec2",
+        "libcodec2_hal_common",
         "libcodec2_vndk",
         "libutils",
     ],
diff --git a/media/libaudiohal/impl/CoreConversionHelperHidl.cpp b/media/libaudiohal/impl/CoreConversionHelperHidl.cpp
index bd18902..b801187 100644
--- a/media/libaudiohal/impl/CoreConversionHelperHidl.cpp
+++ b/media/libaudiohal/impl/CoreConversionHelperHidl.cpp
@@ -97,7 +97,7 @@
     for (size_t i = 0; i < parameters.size(); ++i) {
         params.add(String8(parameters[i].key.c_str()), String8(parameters[i].value.c_str()));
     }
-    values->setTo(params.toString());
+    *values = params.toString();
 }
 
 CoreConversionHelperHidl::CoreConversionHelperHidl(std::string_view className)
diff --git a/media/libaudiohal/tests/CoreAudioHalAidl_test.cpp b/media/libaudiohal/tests/CoreAudioHalAidl_test.cpp
index ea20794..adff110 100644
--- a/media/libaudiohal/tests/CoreAudioHalAidl_test.cpp
+++ b/media/libaudiohal/tests/CoreAudioHalAidl_test.cpp
@@ -452,7 +452,7 @@
     String8 values;
     EXPECT_EQ(OK, mDevice->getParameters(String8("random_name"), &values));
     EXPECT_EQ(0UL, mModule->getRetrievedParameterIds().size());
-    EXPECT_TRUE(values.empty());
+    EXPECT_EQ(0UL, values.length());
 }
 
 class DeviceHalAidlVendorParametersTest : public testing::Test {
diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp
index 583b7de..89348a4 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.cpp
+++ b/media/libmediaplayerservice/StagefrightRecorder.cpp
@@ -531,7 +531,7 @@
         --i;
     }
 
-    s->setTo(String8(&data[leading_space], i - leading_space));
+    *s = String8(&data[leading_space], i - leading_space);
 }
 
 status_t StagefrightRecorder::setParamAudioSamplingRate(int32_t sampleRate) {
@@ -825,7 +825,7 @@
 status_t StagefrightRecorder::setParamRtpLocalIp(const String8 &localIp) {
     ALOGV("setParamVideoLocalIp: %s", localIp.c_str());
 
-    mLocalIp.setTo(localIp.c_str());
+    mLocalIp = localIp.c_str();
     return OK;
 }
 
@@ -839,7 +839,7 @@
 status_t StagefrightRecorder::setParamRtpRemoteIp(const String8 &remoteIp) {
     ALOGV("setParamVideoRemoteIp: %s", remoteIp.c_str());
 
-    mRemoteIp.setTo(remoteIp.c_str());
+    mRemoteIp = remoteIp.c_str();
     return OK;
 }
 
@@ -932,7 +932,7 @@
     ALOGV("setLogSessionId: %s", log_session_id.c_str());
 
     // TODO: validity check that log_session_id is a 32-byte hex digit.
-    mLogSessionId.setTo(log_session_id.c_str());
+    mLogSessionId = log_session_id.c_str();
     return OK;
 }
 
@@ -1137,9 +1137,9 @@
         const char *semicolon_pos = strchr(value_start, ';');
         String8 value;
         if (semicolon_pos == NULL) {
-            value.setTo(value_start);
+            value = value_start;
         } else {
-            value.setTo(value_start, semicolon_pos - value_start);
+            value = String8(value_start, semicolon_pos - value_start);
         }
         if (setParameter(key, value) != OK) {
             return BAD_VALUE;
diff --git a/media/libmediaplayerservice/fuzzer/Android.bp b/media/libmediaplayerservice/fuzzer/Android.bp
index 017f403..41a322a 100644
--- a/media/libmediaplayerservice/fuzzer/Android.bp
+++ b/media/libmediaplayerservice/fuzzer/Android.bp
@@ -173,6 +173,7 @@
         "libnetd_client",
         "libpowermanager",
         "libstagefright_httplive",
+        "libaudiohal@7.0",
     ],
 }
 
diff --git a/media/libmediaplayerservice/nuplayer/RTPSource.cpp b/media/libmediaplayerservice/nuplayer/RTPSource.cpp
index efe1a80..9a33120 100644
--- a/media/libmediaplayerservice/nuplayer/RTPSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/RTPSource.cpp
@@ -751,9 +751,9 @@
         const char *semicolon_pos = strchr(value_start, ';');
         String8 value;
         if (semicolon_pos == NULL) {
-            value.setTo(value_start);
+            value = value_start;
         } else {
-            value.setTo(value_start, semicolon_pos - value_start);
+            value = String8(value_start, semicolon_pos - value_start);
         }
         if (setParameter(key, value) != OK) {
             return BAD_VALUE;
@@ -796,7 +796,7 @@
         --i;
     }
 
-    s->setTo(String8(&data[leading_space], i - leading_space));
+    *s = String8(&data[leading_space], i - leading_space);
 }
 
 }  // namespace android
diff --git a/media/libstagefright/omx/OmxGraphicBufferSource.cpp b/media/libstagefright/omx/OmxGraphicBufferSource.cpp
index 33481e3..5d653bc 100644
--- a/media/libstagefright/omx/OmxGraphicBufferSource.cpp
+++ b/media/libstagefright/omx/OmxGraphicBufferSource.cpp
@@ -85,6 +85,18 @@
         int32_t bufferCount,
         uint32_t frameWidth,
         uint32_t frameHeight,
+        uint32_t consumerUsage) {
+    uint64_t consumerUsage64 = static_cast<uint64_t>(consumerUsage);
+    return configure(omxNode, dataSpace, bufferCount,
+                     frameWidth, frameHeight, consumerUsage64);
+}
+
+status_t OmxGraphicBufferSource::configure(
+        const sp<IOmxNodeWrapper>& omxNode,
+        int32_t dataSpace,
+        int32_t bufferCount,
+        uint32_t frameWidth,
+        uint32_t frameHeight,
         uint64_t consumerUsage) {
     if (omxNode == NULL) {
         return BAD_VALUE;
diff --git a/media/libstagefright/omx/include/media/stagefright/omx/OmxGraphicBufferSource.h b/media/libstagefright/omx/include/media/stagefright/omx/OmxGraphicBufferSource.h
index a23efac..8b920c1 100644
--- a/media/libstagefright/omx/include/media/stagefright/omx/OmxGraphicBufferSource.h
+++ b/media/libstagefright/omx/include/media/stagefright/omx/OmxGraphicBufferSource.h
@@ -63,7 +63,19 @@
     // ------------------------------
 
     // Configure the buffer source to be used with an OMX node with the default
-    // data space.
+    // data space.(32-bit consumerUsage flag, for vendor partition
+    // compatibility)
+    [[deprecated("use configure() with a 64-bit consumerUsage flag instead")]]
+    status_t configure(
+        const sp<IOmxNodeWrapper> &omxNode,
+        int32_t dataSpace,
+        int32_t bufferCount,
+        uint32_t frameWidth,
+        uint32_t frameHeight,
+        uint32_t consumerUsage);
+
+    // Configure the buffer source to be used with an OMX node with the default
+    // data space. (64-bit consumerUsage flag)
     status_t configure(
         const sp<IOmxNodeWrapper> &omxNode,
         int32_t dataSpace,
diff --git a/media/module/bqhelper/GraphicBufferSource.cpp b/media/module/bqhelper/GraphicBufferSource.cpp
index 4bb2215..82ddbc0 100644
--- a/media/module/bqhelper/GraphicBufferSource.cpp
+++ b/media/module/bqhelper/GraphicBufferSource.cpp
@@ -1150,6 +1150,18 @@
         int32_t bufferCount,
         uint32_t frameWidth,
         uint32_t frameHeight,
+        uint32_t consumerUsage) {
+    uint64_t consumerUsage64 = static_cast<uint64_t>(consumerUsage);
+    return configure(component, dataSpace, bufferCount,
+                     frameWidth, frameHeight, consumerUsage64);
+}
+
+status_t GraphicBufferSource::configure(
+        const sp<ComponentWrapper>& component,
+        int32_t dataSpace,
+        int32_t bufferCount,
+        uint32_t frameWidth,
+        uint32_t frameHeight,
         uint64_t consumerUsage) {
     if (component == NULL) {
         return BAD_VALUE;
diff --git a/media/module/bqhelper/include/media/stagefright/bqhelper/GraphicBufferSource.h b/media/module/bqhelper/include/media/stagefright/bqhelper/GraphicBufferSource.h
index 4e4fbfd..5225a48 100644
--- a/media/module/bqhelper/include/media/stagefright/bqhelper/GraphicBufferSource.h
+++ b/media/module/bqhelper/include/media/stagefright/bqhelper/GraphicBufferSource.h
@@ -122,7 +122,19 @@
     // ------------------------------
 
     // Configure the buffer source to be used with a component with the default
-    // data space.
+    // data space. (32-bit consumerUsage flag, for vendor partition
+    // compatibility)
+    [[deprecated("use configure() with a 64-bit consumerUsage flag instead")]]
+    status_t configure(
+        const sp<ComponentWrapper> &component,
+        int32_t dataSpace,
+        int32_t bufferCount,
+        uint32_t frameWidth,
+        uint32_t frameHeight,
+        uint32_t consumerUsage);
+
+    // Configure the buffer source to be used with a component with the default
+    // data space. (64-bit consumerUsage flag)
     status_t configure(
         const sp<ComponentWrapper> &component,
         int32_t dataSpace,
diff --git a/media/module/extractors/mp4/ItemTable.cpp b/media/module/extractors/mp4/ItemTable.cpp
index 27d7878..cf3df62 100644
--- a/media/module/extractors/mp4/ItemTable.cpp
+++ b/media/module/extractors/mp4/ItemTable.cpp
@@ -1160,7 +1160,7 @@
         }
         buf.push_back(tmp);
         if (tmp == 0) {
-            out->setTo(buf.array());
+            *out = buf.array();
 
             *offset = newOffset;
             *size = stopOffset - newOffset;
diff --git a/media/module/extractors/mp4/MPEG4Extractor.cpp b/media/module/extractors/mp4/MPEG4Extractor.cpp
index 08c6fe6..9ab9f0f 100644
--- a/media/module/extractors/mp4/MPEG4Extractor.cpp
+++ b/media/module/extractors/mp4/MPEG4Extractor.cpp
@@ -847,7 +847,7 @@
     struct tm* tm = gmtime(&time_1970);
     if (tm != NULL &&
             strftime(tmp, sizeof(tmp), "%Y%m%dT%H%M%S.000Z", tm) > 0) {
-        s->setTo(tmp);
+        *s = tmp;
         return true;
     }
     return false;
@@ -4082,10 +4082,10 @@
             buffer[size] = '\0';
             switch (mPath[5]) {
                 case FOURCC("mean"):
-                    mLastCommentMean.setTo((const char *)buffer + 4);
+                    mLastCommentMean = ((const char *)buffer + 4);
                     break;
                 case FOURCC("name"):
-                    mLastCommentName.setTo((const char *)buffer + 4);
+                    mLastCommentName = ((const char *)buffer + 4);
                     break;
                 case FOURCC("data"):
                     if (size < 8) {
@@ -4094,7 +4094,7 @@
                         ALOGE("b/24346430");
                         return ERROR_MALFORMED;
                     }
-                    mLastCommentData.setTo((const char *)buffer + 8);
+                    mLastCommentData = ((const char *)buffer + 8);
                     break;
             }
 
diff --git a/media/module/foundation/MetaDataBase.cpp b/media/module/foundation/MetaDataBase.cpp
index da383fa..60478c9 100644
--- a/media/module/foundation/MetaDataBase.cpp
+++ b/media/module/foundation/MetaDataBase.cpp
@@ -23,6 +23,8 @@
 #include <stdlib.h>
 #include <string.h>
 
+#include <mutex>
+
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/AString.h>
 #include <media/stagefright/foundation/hexdump.h>
@@ -78,6 +80,7 @@
 
 
 struct MetaDataBase::MetaDataInternal {
+    std::mutex mLock;
     KeyedVector<uint32_t, MetaDataBase::typed_data> mItems;
 };
 
@@ -102,10 +105,12 @@
 }
 
 void MetaDataBase::clear() {
+    std::lock_guard<std::mutex> guard(mInternalData->mLock);
     mInternalData->mItems.clear();
 }
 
 bool MetaDataBase::remove(uint32_t key) {
+    std::lock_guard<std::mutex> guard(mInternalData->mLock);
     ssize_t i = mInternalData->mItems.indexOfKey(key);
 
     if (i < 0) {
@@ -252,6 +257,7 @@
         uint32_t key, uint32_t type, const void *data, size_t size) {
     bool overwrote_existing = true;
 
+    std::lock_guard<std::mutex> guard(mInternalData->mLock);
     ssize_t i = mInternalData->mItems.indexOfKey(key);
     if (i < 0) {
         typed_data item;
@@ -269,6 +275,7 @@
 
 bool MetaDataBase::findData(uint32_t key, uint32_t *type,
                         const void **data, size_t *size) const {
+    std::lock_guard<std::mutex> guard(mInternalData->mLock);
     ssize_t i = mInternalData->mItems.indexOfKey(key);
 
     if (i < 0) {
@@ -283,6 +290,7 @@
 }
 
 bool MetaDataBase::hasData(uint32_t key) const {
+    std::lock_guard<std::mutex> guard(mInternalData->mLock);
     ssize_t i = mInternalData->mItems.indexOfKey(key);
 
     if (i < 0) {
@@ -429,6 +437,7 @@
 
 String8 MetaDataBase::toString() const {
     String8 s;
+    std::lock_guard<std::mutex> guard(mInternalData->mLock);
     for (int i = mInternalData->mItems.size(); --i >= 0;) {
         int32_t key = mInternalData->mItems.keyAt(i);
         char cc[5];
@@ -443,6 +452,7 @@
 }
 
 void MetaDataBase::dumpToLog() const {
+    std::lock_guard<std::mutex> guard(mInternalData->mLock);
     for (int i = mInternalData->mItems.size(); --i >= 0;) {
         int32_t key = mInternalData->mItems.keyAt(i);
         char cc[5];
@@ -455,6 +465,7 @@
 #if defined(__ANDROID__) && !defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__)
 status_t MetaDataBase::writeToParcel(Parcel &parcel) {
     status_t ret;
+    std::lock_guard<std::mutex> guard(mInternalData->mLock);
     size_t numItems = mInternalData->mItems.size();
     ret = parcel.writeUint32(uint32_t(numItems));
     if (ret) {
diff --git a/media/module/id3/ID3.cpp b/media/module/id3/ID3.cpp
index 1f3cad9..aaaeeaf 100644
--- a/media/module/id3/ID3.cpp
+++ b/media/module/id3/ID3.cpp
@@ -535,40 +535,40 @@
 }
 
 void ID3::Iterator::getID(String8 *id) const {
-    id->setTo("");
+    *id = "";
 
     if (mFrameData == NULL) {
         return;
     }
 
     if (mParent.mVersion == ID3_V2_2) {
-        id->setTo((const char *)&mParent.mData[mOffset], 3);
+        *id = String8((const char *)&mParent.mData[mOffset], 3);
     } else if (mParent.mVersion == ID3_V2_3 || mParent.mVersion == ID3_V2_4) {
-        id->setTo((const char *)&mParent.mData[mOffset], 4);
+        *id = String8((const char *)&mParent.mData[mOffset], 4);
     } else {
         CHECK(mParent.mVersion == ID3_V1 || mParent.mVersion == ID3_V1_1);
 
         switch (mOffset) {
             case 3:
-                id->setTo("TT2");
+                *id = "TT2";
                 break;
             case 33:
-                id->setTo("TP1");
+                *id = "TP1";
                 break;
             case 63:
-                id->setTo("TAL");
+                *id = "TAL";
                 break;
             case 93:
-                id->setTo("TYE");
+                *id = "TYE";
                 break;
             case 97:
-                id->setTo("COM");
+                *id = "COM";
                 break;
             case 126:
-                id->setTo("TRK");
+                *id = "TRK";
                 break;
             case 127:
-                id->setTo("TCO");
+                *id = "TCO";
                 break;
             default:
                 CHECK(!"should not be here.");
@@ -590,7 +590,7 @@
 // followed by more data. The data following the \0 can be retrieved by setting
 // "otherdata" to true.
 void ID3::Iterator::getstring(String8 *id, bool otherdata) const {
-    id->setTo("");
+    *id = "";
 
     const uint8_t *frameData = mFrameData;
     if (frameData == NULL) {
@@ -605,13 +605,13 @@
             char tmp[16];
             snprintf(tmp, sizeof(tmp), "%d", (int)*frameData);
 
-            id->setTo(tmp);
+            *id = tmp;
             return;
         }
 
         // this is supposed to be ISO-8859-1, but pass it up as-is to the caller, who will figure
         // out the real encoding
-        id->setTo((const char*)frameData, mFrameSize);
+        *id = String8((const char*)frameData, mFrameSize);
         return;
     }
 
@@ -640,10 +640,10 @@
 
     if (encoding == 0x00) {
         // supposedly ISO 8859-1
-        id->setTo((const char*)frameData + 1, n);
+        *id = String8((const char*)frameData + 1, n);
     } else if (encoding == 0x03) {
         // supposedly UTF-8
-        id->setTo((const char *)(frameData + 1), n);
+        *id = String8((const char *)(frameData + 1), n);
     } else if (encoding == 0x02) {
         // supposedly UTF-16 BE, no byte order mark.
         // API wants number of characters, not number of bytes...
@@ -662,7 +662,7 @@
             framedata = framedatacopy;
         }
 #endif
-        id->setTo(framedata, len);
+        *id = String8(framedata, len);
         if (framedatacopy != NULL) {
             delete[] framedatacopy;
         }
@@ -715,13 +715,13 @@
                 for (int i = 0; i < len; i++) {
                     frame8[i] = framedata[i];
                 }
-                id->setTo(frame8, len);
+                *id = String8(frame8, len);
                 delete [] frame8;
             } else {
-                id->setTo(framedata, len);
+                *id = String8(framedata, len);
             }
         } else {
-            id->setTo(framedata, len);
+            *id = String8(framedata, len);
         }
 
         if (framedatacopy != NULL) {
@@ -948,7 +948,7 @@
 const void *
 ID3::getAlbumArt(size_t *length, String8 *mime) const {
     *length = 0;
-    mime->setTo("");
+    *mime = "";
 
     Iterator it(
             *this,
@@ -971,7 +971,7 @@
                 ALOGW("bogus album art size: mime");
                 return NULL;
             }
-            mime->setTo((const char *)&data[consumed]);
+            *mime = (const char *)&data[consumed];
             consumed += mimeLen;
 
 #if 0
@@ -1008,11 +1008,11 @@
             }
 
             if (!memcmp(&data[1], "PNG", 3)) {
-                mime->setTo("image/png");
+                *mime = "image/png";
             } else if (!memcmp(&data[1], "JPG", 3)) {
-                mime->setTo("image/jpeg");
+                *mime = "image/jpeg";
             } else if (!memcmp(&data[1], "-->", 3)) {
-                mime->setTo("text/plain");
+                *mime = "text/plain";
             } else {
                 return NULL;
             }
diff --git a/services/audioflinger/PlaybackTracks.h b/services/audioflinger/PlaybackTracks.h
index 5f54e11..3e5501f 100644
--- a/services/audioflinger/PlaybackTracks.h
+++ b/services/audioflinger/PlaybackTracks.h
@@ -62,8 +62,8 @@
 
     wp<IAfThreadBase> mThread;
     std::atomic_bool mHasOpPlayAudio;
-    const AttributionSourceState mAttributionSource;
-    const int32_t mUsage; // on purpose not audio_usage_t because always checked in appOps as int32_t
+    const int32_t mUsage;  // on purpose not audio_usage_t because always checked in appOps as
+                           // int32_t
     const int mId; // for logging purposes only
     const uid_t mUid;
     const String16 mPackageName;
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index ecea9eb..e93046e 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -568,9 +568,7 @@
     getPackagesForUid(uid, packages);
     if (isServiceUid(uid)) {
         if (packages.isEmpty()) {
-            ALOGD("OpPlayAudio: not muting track:%d usage:%d for service UID %d",
-                  id,
-                  attr.usage,
+            ALOGW("OpPlayAudio: not muting track:%d usage:%d for service UID %d", id, attr.usage,
                   uid);
             return nullptr;
         }
@@ -594,7 +592,6 @@
                                        audio_usage_t usage, int id, uid_t uid)
     : mThread(wp<IAfThreadBase>::fromExisting(thread)),
       mHasOpPlayAudio(true),
-      mAttributionSource(attributionSource),
       mUsage((int32_t)usage),
       mId(id),
       mUid(uid),
@@ -614,10 +611,11 @@
     // make sure not to broadcast the initial state since it is not needed and could
     // cause a deadlock since this method can be called with the mThread->mLock held
     checkPlayAudioForUsage(/*doBroadcast=*/false);
-    if (mAttributionSource.packageName.has_value()) {
+    if (mPackageName.size()) {
         mOpCallback = new PlayAudioOpCallback(this);
-        mAppOpsManager.startWatchingMode(AppOpsManager::OP_PLAY_AUDIO,
-                mPackageName, mOpCallback);
+        mAppOpsManager.startWatchingMode(AppOpsManager::OP_PLAY_AUDIO, mPackageName, mOpCallback);
+    } else {
+        ALOGW("Skipping OpPlayAudioMonitor due to null package name");
     }
 }
 
@@ -628,16 +626,16 @@
 // Note this method is never called (and never to be) for audio server / patch record track
 // - not called from constructor due to check on UID,
 // - not called from PlayAudioOpCallback because the callback is not installed in this case
-void OpPlayAudioMonitor::checkPlayAudioForUsage(bool doBroadcast)
-{
-    const bool hasAppOps = mAttributionSource.packageName.has_value()
-        && mAppOpsManager.checkAudioOpNoThrow(
-                AppOpsManager::OP_PLAY_AUDIO, mUsage, mUid, mPackageName) ==
-                        AppOpsManager::MODE_ALLOWED;
+void OpPlayAudioMonitor::checkPlayAudioForUsage(bool doBroadcast) {
+    const bool hasAppOps =
+            mPackageName.size() &&
+            mAppOpsManager.checkAudioOpNoThrow(AppOpsManager::OP_PLAY_AUDIO, mUsage, mUid,
+                                               mPackageName) == AppOpsManager::MODE_ALLOWED;
 
     bool shouldChange = !hasAppOps;  // check if we need to update.
     if (mHasOpPlayAudio.compare_exchange_strong(shouldChange, hasAppOps)) {
-        ALOGD("OpPlayAudio: track:%d usage:%d %smuted", mId, mUsage, hasAppOps ? "not " : "");
+        ALOGI("OpPlayAudio: track:%d package:%s usage:%d %smuted", mId,
+              String8(mPackageName).string(), mUsage, hasAppOps ? "not " : "");
         if (doBroadcast) {
             auto thread = mThread.promote();
             if (thread != nullptr && thread->type() == IAfThreadBase::OFFLOAD) {
@@ -655,11 +653,11 @@
 
 void OpPlayAudioMonitor::PlayAudioOpCallback::opChanged(int32_t op,
             const String16& packageName) {
-    // we only have uid, so we need to check all package names anyway
-    UNUSED(packageName);
     if (op != AppOpsManager::OP_PLAY_AUDIO) {
         return;
     }
+
+    ALOGI("%s OP_PLAY_AUDIO callback received for %s", __func__, String8(packageName).string());
     sp<OpPlayAudioMonitor> monitor = mMonitor.promote();
     if (monitor != NULL) {
         monitor->checkPlayAudioForUsage(/*doBroadcast=*/true);
@@ -1640,22 +1638,18 @@
         if (mMuteEventExtras == nullptr) {
             mMuteEventExtras = std::make_unique<os::PersistableBundle>();
         }
-        mMuteEventExtras->putInt(String16(kExtraPlayerEventMuteKey),
-                                 static_cast<int>(muteState));
+        mMuteEventExtras->putInt(String16(kExtraPlayerEventMuteKey), static_cast<int>(muteState));
 
-        result = audioManager->portEvent(mPortId,
-                                         PLAYER_UPDATE_MUTED,
-                                         mMuteEventExtras);
+        result = audioManager->portEvent(mPortId, PLAYER_UPDATE_MUTED, mMuteEventExtras);
     }
 
     if (result == OK) {
+        ALOGI("%s(%d): processed mute state for port ID %d from %d to %d", __func__, id(), mPortId,
+              int(muteState), int(mMuteState));
         mMuteState = muteState;
     } else {
-        ALOGW("%s(%d): cannot process mute state for port ID %d, status error %d",
-              __func__,
-              id(),
-              mPortId,
-              result);
+        ALOGW("%s(%d): cannot process mute state for port ID %d, status error %d", __func__, id(),
+              mPortId, result);
     }
 }
 
diff --git a/services/audiopolicy/config/Android.bp b/services/audiopolicy/config/Android.bp
index 671b30a..86600f4 100644
--- a/services/audiopolicy/config/Android.bp
+++ b/services/audiopolicy/config/Android.bp
@@ -112,3 +112,15 @@
     name: "r_submix_audio_policy_configuration",
     srcs: ["r_submix_audio_policy_configuration.xml"],
 }
+filegroup {
+    name: "bluetooth_audio_policy_configuration_7_0",
+    srcs: ["bluetooth_audio_policy_configuration_7_0.xml"],
+}
+filegroup {
+    name: "bluetooth_with_le_audio_policy_configuration_7_0",
+    srcs: ["bluetooth_with_le_audio_policy_configuration_7_0.xml"],
+}
+filegroup {
+    name: "hearing_aid_audio_policy_configuration_7_0",
+    srcs: ["hearing_aid_audio_policy_configuration_7_0.xml"],
+}
diff --git a/services/audiopolicy/fuzzer/audiopolicy_fuzzer.cpp b/services/audiopolicy/fuzzer/audiopolicy_fuzzer.cpp
index 8793085..58fcb5c 100644
--- a/services/audiopolicy/fuzzer/audiopolicy_fuzzer.cpp
+++ b/services/audiopolicy/fuzzer/audiopolicy_fuzzer.cpp
@@ -661,7 +661,9 @@
 }
 
 AudioPolicyManagerFuzzerDPPlaybackReRouting::~AudioPolicyManagerFuzzerDPPlaybackReRouting() {
-    mManager->stopInput(mPortId);
+    if (mManager) {
+        mManager->stopInput(mPortId);
+    }
 }
 
 bool AudioPolicyManagerFuzzerDPPlaybackReRouting::initialize() {
@@ -773,7 +775,9 @@
 }
 
 AudioPolicyManagerFuzzerDPMixRecordInjection::~AudioPolicyManagerFuzzerDPMixRecordInjection() {
-    mManager->stopOutput(mPortId);
+    if (mManager) {
+        mManager->stopOutput(mPortId);
+    }
 }
 
 bool AudioPolicyManagerFuzzerDPMixRecordInjection::initialize() {
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index ed321b6..c0194b9 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -1388,7 +1388,7 @@
             /*targetSdkVersion*/ __ANDROID_API_FUTURE__, /*overrideToPortrait*/ true,
             /*forceSlowJpegMode*/false, cameraIdStr, /*out*/ tmp)
             ).isOk()) {
-        ALOGE("%s: Error initializing shim metadata: %s", __FUNCTION__, ret.toString8().string());
+        ALOGE("%s: Error initializing shim metadata: %s", __FUNCTION__, ret.toString8().c_str());
     }
     return ret;
 }
diff --git a/services/camera/libcameraservice/api1/Camera2Client.cpp b/services/camera/libcameraservice/api1/Camera2Client.cpp
index 87a4420..b217476 100644
--- a/services/camera/libcameraservice/api1/Camera2Client.cpp
+++ b/services/camera/libcameraservice/api1/Camera2Client.cpp
@@ -188,7 +188,7 @@
         SharedParameters::Lock l(mParameters);
         ALOGD("%s: Default parameters converted from camera %d:", __FUNCTION__,
               mCameraId);
-        ALOGD("%s", l.mParameters.paramsFlattened.string());
+        ALOGD("%s", l.mParameters.paramsFlattened.c_str());
     }
 
     return OK;
@@ -247,7 +247,7 @@
         result << fmt::sprintf("    GPS timestamp: %" PRId64 "\n",
                 p.gpsTimestamp);
         result << fmt::sprintf("    GPS processing method: %s\n",
-                p.gpsProcessingMethod.string());
+                p.gpsProcessingMethod.c_str());
     }
 
     result << "    White balance mode: ";
diff --git a/services/camera/libcameraservice/api1/client2/Parameters.cpp b/services/camera/libcameraservice/api1/client2/Parameters.cpp
index 13dcbaa..aa3d1bb 100644
--- a/services/camera/libcameraservice/api1/client2/Parameters.cpp
+++ b/services/camera/libcameraservice/api1/client2/Parameters.cpp
@@ -164,7 +164,7 @@
                     availablePreviewSizes[i].width,
                     availablePreviewSizes[i].height);
         }
-        ALOGV("Supported preview sizes are: %s", supportedPreviewSizes.string());
+        ALOGV("Supported preview sizes are: %s", supportedPreviewSizes.c_str());
         params.set(CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES,
                 supportedPreviewSizes);
 
@@ -175,7 +175,7 @@
                     availableVideoSizes[i].width,
                     availableVideoSizes[i].height);
         }
-        ALOGV("Supported video sizes are: %s", supportedVideoSizes.string());
+        ALOGV("Supported video sizes are: %s", supportedVideoSizes.c_str());
         params.set(CameraParameters::KEY_SUPPORTED_VIDEO_SIZES,
                 supportedVideoSizes);
     }
@@ -315,7 +315,7 @@
                     fps);
 
             ALOGV("%s: Supported preview frame rates: %s",
-                    __FUNCTION__, supportedPreviewFrameRates.string());
+                    __FUNCTION__, supportedPreviewFrameRates.c_str());
         }
         params.set(CameraParameters::KEY_SUPPORTED_PREVIEW_FRAME_RATES,
                 supportedPreviewFrameRates);
@@ -2832,7 +2832,7 @@
     String8 areasStr(areasCStr);
     ssize_t areaStart = areasStr.find("(", 0) + 1;
     while (areaStart != 0) {
-        const char* area = areasStr.string() + areaStart;
+        const char* area = areasStr.c_str() + areaStart;
         char *numEnd;
         int vals[NUM_FIELDS];
         for (size_t i = 0; i < NUM_FIELDS; i++) {
diff --git a/services/camera/libcameraservice/gui/RingBufferConsumer.cpp b/services/camera/libcameraservice/gui/RingBufferConsumer.cpp
index cd4a92c..5dbfb36 100644
--- a/services/camera/libcameraservice/gui/RingBufferConsumer.cpp
+++ b/services/camera/libcameraservice/gui/RingBufferConsumer.cpp
@@ -25,11 +25,11 @@
 #include <gui/RingBufferConsumer.h>
 #include <camera/StringUtils.h>
 
-#define BI_LOGV(x, ...) ALOGV("[%s] " x, mName.string(), ##__VA_ARGS__)
-#define BI_LOGD(x, ...) ALOGD("[%s] " x, mName.string(), ##__VA_ARGS__)
-#define BI_LOGI(x, ...) ALOGI("[%s] " x, mName.string(), ##__VA_ARGS__)
-#define BI_LOGW(x, ...) ALOGW("[%s] " x, mName.string(), ##__VA_ARGS__)
-#define BI_LOGE(x, ...) ALOGE("[%s] " x, mName.string(), ##__VA_ARGS__)
+#define BI_LOGV(x, ...) ALOGV("[%s] " x, mName.c_str(), ##__VA_ARGS__)
+#define BI_LOGD(x, ...) ALOGD("[%s] " x, mName.c_str(), ##__VA_ARGS__)
+#define BI_LOGI(x, ...) ALOGI("[%s] " x, mName.c_str(), ##__VA_ARGS__)
+#define BI_LOGW(x, ...) ALOGW("[%s] " x, mName.c_str(), ##__VA_ARGS__)
+#define BI_LOGE(x, ...) ALOGE("[%s] " x, mName.c_str(), ##__VA_ARGS__)
 
 #undef assert
 #define assert(x) ALOG_ASSERT((x), #x)
diff --git a/services/camera/libcameraservice/hidl/HidlCameraService.cpp b/services/camera/libcameraservice/hidl/HidlCameraService.cpp
index 4f12933..94bf653 100644
--- a/services/camera/libcameraservice/hidl/HidlCameraService.cpp
+++ b/services/camera/libcameraservice/hidl/HidlCameraService.cpp
@@ -78,7 +78,7 @@
                 break;
             default:
                 ALOGE("Get camera characteristics from camera service failed: %s",
-                      serviceRet.toString8().string());
+                      serviceRet.toString8().c_str());
                 status = B2HStatus(serviceRet);
           }
         _hidl_cb(status, hidlMetadata);
@@ -307,7 +307,7 @@
         }
         hVendorTagSections.resize(numSections);
         for (size_t s = 0; s < numSections; s++) {
-            hVendorTagSections[s].sectionName = (*sectionNames)[s].string();
+            hVendorTagSections[s].sectionName = (*sectionNames)[s].c_str();
             hVendorTagSections[s].tags = tagsBySection[s];
         }
         HProviderIdAndVendorTagSections &hProviderIdAndVendorTagSections =
diff --git a/services/mediaresourcemanager/fuzzer/Android.bp b/services/mediaresourcemanager/fuzzer/Android.bp
index f38a085..bbbc737 100644
--- a/services/mediaresourcemanager/fuzzer/Android.bp
+++ b/services/mediaresourcemanager/fuzzer/Android.bp
@@ -49,6 +49,14 @@
             "android-media-fuzzing-reports@google.com",
         ],
         componentid: 155276,
+        hotlists: [
+            "4593311",
+        ],
+        description: "The fuzzer targets the APIs of libresourcemanagerservice",
+        vector: "remote",
+        service_privilege: "constrained",
+        users: "multi_user",
+        fuzzed_code_usage: "shipped",
     },
 }