Merge "CameraService: Increase watchdog timer" into main
diff --git a/camera/Android.bp b/camera/Android.bp
index a3fd7f9..e5ae954 100644
--- a/camera/Android.bp
+++ b/camera/Android.bp
@@ -43,6 +43,22 @@
     ],
 }
 
+aconfig_declarations {
+    name: "camera_platform_flags",
+    package: "com.android.internal.camera.flags",
+    srcs: ["camera_platform.aconfig"],
+}
+
+cc_aconfig_library {
+    name: "camera_platform_flags_c_lib",
+    aconfig_declarations: "camera_platform_flags",
+}
+
+java_aconfig_library {
+    name: "camera_platform_flags_java_lib",
+    aconfig_declarations: "camera_platform_flags",
+}
+
 cc_library_headers {
     name: "camera_headers",
     export_include_dirs: ["include"],
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..fb26f83 100644
--- a/camera/VendorTagDescriptor.cpp
+++ b/camera/VendorTagDescriptor.cpp
@@ -152,7 +152,7 @@
             break;
         }
         String8 tagName = parcel->readString8();
-        if (tagName.isEmpty()) {
+        if (tagName.empty()) {
             ALOGE("%s: parcel tag name was NULL for tag %d.", __FUNCTION__, tag);
             res = NOT_ENOUGH_DATA;
             break;
@@ -190,7 +190,7 @@
                 "Vector capacity must be positive");
         for (size_t i = 0; i < sectionCount; ++i) {
             String8 sectionName = parcel->readString8();
-            if (sectionName.isEmpty()) {
+            if (sectionName.empty()) {
                 ALOGE("%s: parcel section name was NULL for section %zu.",
                       __FUNCTION__, i);
                 return NOT_ENOUGH_DATA;
@@ -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/camera_platform.aconfig b/camera/camera_platform.aconfig
new file mode 100644
index 0000000..fc11518
--- /dev/null
+++ b/camera/camera_platform.aconfig
@@ -0,0 +1,8 @@
+package: "com.android.internal.camera.flags"
+
+flag {
+     namespace: "camera_platform"
+     name: "initial_test_flag"
+     description: "Flag infrastructure test flag"
+     bug: "292631208"
+}
diff --git a/camera/include/camera/StringUtils.h b/camera/include/camera/StringUtils.h
index b9dfbfc..80c419f 100644
--- a/camera/include/camera/StringUtils.h
+++ b/camera/include/camera/StringUtils.h
@@ -17,8 +17,6 @@
 #ifndef ANDROID_SERVERS_CAMERA_STRINGUTILS_H
 #define ANDROID_SERVERS_CAMERA_STRINGUTILS_H
 
-#include <codecvt>
-#include <locale>
 #include <memory>
 #include <optional>
 #include <string>
@@ -61,12 +59,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());
+        String8 str8(str);
+        return std::string(str8.c_str());
     }
 
     /**
@@ -74,8 +72,9 @@
      * len is the number of characters.
      */
     inline std::string toStdString(const char16_t *str, size_t len) {
-        std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> convert;
-        return convert.to_bytes(str, str + len);
+        String16 str16(str, len);
+        String8 str8(str16);
+        return std::string(str8.c_str());
     }
 } // namespace android
 
diff --git a/camera/ndk/impl/ACameraDevice.cpp b/camera/ndk/impl/ACameraDevice.cpp
index 8bdb6d4..97d65b0 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;
         }
     }
@@ -368,24 +368,24 @@
         // ndk as well.
         if (remoteRet.exceptionCode() != EX_SERVICE_SPECIFIC) {
             ALOGE("Camera device %s failed to prepare output window %p: %s", getId(), window,
-                    remoteRet.toString8().string());
+                    remoteRet.toString8().c_str());
             return ACAMERA_ERROR_UNKNOWN;
 
         }
         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_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 prepare output window %p: %s", getId(), window,
-                        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/camera/ndk/include/camera/NdkCameraMetadataTags.h b/camera/ndk/include/camera/NdkCameraMetadataTags.h
index af00e55..4a589bc 100644
--- a/camera/ndk/include/camera/NdkCameraMetadataTags.h
+++ b/camera/ndk/include/camera/NdkCameraMetadataTags.h
@@ -584,6 +584,13 @@
      * <p>Only constrains auto-exposure (AE) algorithm, not
      * manual control of ACAMERA_SENSOR_EXPOSURE_TIME and
      * ACAMERA_SENSOR_FRAME_DURATION.</p>
+     * <p>To start a CaptureSession with a target FPS range different from the
+     * capture request template's default value, the application
+     * is strongly recommended to call
+     * {@link ACameraDevice_createCaptureSessionWithSessionParameters }
+     * with the target fps range before creating the capture session. The aeTargetFpsRange is
+     * typically a session parameter. Specifying it at session creation time helps avoid
+     * session reconfiguration delays in cases like 60fps or high speed recording.</p>
      *
      * @see ACAMERA_SENSOR_EXPOSURE_TIME
      * @see ACAMERA_SENSOR_FRAME_DURATION
@@ -1128,6 +1135,12 @@
      * ACAMERA_CONTROL_VIDEO_STABILIZATION_MODE field will return
      * OFF if the recording output is not stabilized, or if there are no output
      * Surface types that can be stabilized.</p>
+     * <p>The application is strongly recommended to call
+     * {@link ACameraDevice_createCaptureSessionWithSessionParameters }
+     * with the desired video stabilization mode before creating the capture session.
+     * Video stabilization mode is a session parameter on many devices. Specifying
+     * it at session creation time helps avoid reconfiguration delay caused by difference
+     * between the default value and the first CaptureRequest.</p>
      * <p>If a camera device supports both this mode and OIS
      * (ACAMERA_LENS_OPTICAL_STABILIZATION_MODE), turning both modes on may
      * produce undesirable interaction, so it is recommended not to enable
diff --git a/cmds/screenrecord/TextRenderer.cpp b/cmds/screenrecord/TextRenderer.cpp
index 01f73e0..cd27bb5 100644
--- a/cmds/screenrecord/TextRenderer.cpp
+++ b/cmds/screenrecord/TextRenderer.cpp
@@ -153,7 +153,7 @@
     // just convert to char* -- but String8 doesn't document what it does
     // with values outside 0-255.  So just convert to char* and use strlen()
     // to see what we get.
-    const char* str = str8.string();
+    const char* str = str8.c_str();
     return computeScaledStringWidth(str, strlen(str));
 }
 
@@ -180,13 +180,13 @@
 
 void TextRenderer::drawString(const Program& program, const float* texMatrix,
         float x, float y, const String8& str8) const {
-    ALOGV("drawString %.3f,%.3f '%s' (scale=%.3f)", x, y, str8.string(),mScale);
+    ALOGV("drawString %.3f,%.3f '%s' (scale=%.3f)", x, y, str8.c_str(),mScale);
     initOnce();
 
     // We want to draw the entire string with a single GLES call.  We
     // generate two arrays, one with screen coordinates, one with texture
     // coordinates.  Need two triangles per character.
-    const char* str = str8.string();
+    const char* str = str8.c_str();
     size_t len = strlen(str);       // again, unsure about String8 handling
 
     const size_t quadCoords =
@@ -252,7 +252,7 @@
 
 float TextRenderer::drawWrappedString(const Program& texRender,
         float xpos, float ypos, const String8& str) {
-    ALOGV("drawWrappedString %.3f,%.3f '%s'", xpos, ypos, str.string());
+    ALOGV("drawWrappedString %.3f,%.3f '%s'", xpos, ypos, str.c_str());
     initOnce();
 
     if (mScreenWidth == 0 || mScreenHeight == 0) {
@@ -283,7 +283,7 @@
     } else {
         // We need to break the string into pieces, ideally at whitespace
         // boundaries.
-        char* mangle = strdup(str.string());
+        char* mangle = strdup(str.c_str());
         char* start = mangle;
         while (start != NULL) {
             float xposAdj = (start == mangle) ? xpos : xpos + indentWidth;
diff --git a/cmds/screenrecord/screenrecord.cpp b/cmds/screenrecord/screenrecord.cpp
index f53fc0a..55bfbd8 100644
--- a/cmds/screenrecord/screenrecord.cpp
+++ b/cmds/screenrecord/screenrecord.cpp
@@ -1096,7 +1096,7 @@
             "-a",
             "android.intent.action.MEDIA_SCANNER_SCAN_FILE",
             "-d",
-            fileUrl.string(),
+            fileUrl.c_str(),
             NULL
     };
     if (gVerbose) {
diff --git a/cmds/stagefright/stagefright.cpp b/cmds/stagefright/stagefright.cpp
index 379f244..f26e3a8 100644
--- a/cmds/stagefright/stagefright.cpp
+++ b/cmds/stagefright/stagefright.cpp
@@ -155,7 +155,7 @@
 }
 
 static void dumpSource(const sp<MediaSource> &source, const String8 &filename) {
-    FILE *out = fopen(filename.string(), "wb");
+    FILE *out = fopen(filename.c_str(), "wb");
 
     CHECK_EQ((status_t)OK, source->start());
 
@@ -212,8 +212,8 @@
         }
         rawSource = SimpleDecodingSource::Create(
                 source, flags, gSurface,
-                gComponentNameOverride.isEmpty() ? nullptr : gComponentNameOverride.c_str(),
-                !gComponentNameOverride.isEmpty());
+                gComponentNameOverride.empty() ? nullptr : gComponentNameOverride.c_str(),
+                !gComponentNameOverride.empty());
         if (rawSource == NULL) {
             return;
         }
@@ -538,9 +538,9 @@
         Vector<sp<MediaSource> > &sources, bool syncInfoPresent) {
 #if 0
     sp<MPEG4Writer> writer =
-        new MPEG4Writer(gWriteMP4Filename.string());
+        new MPEG4Writer(gWriteMP4Filename.c_str());
 #else
-    int fd = open(gWriteMP4Filename.string(), O_CREAT | O_LARGEFILE | O_TRUNC | O_RDWR, S_IRUSR | S_IWUSR);
+    int fd = open(gWriteMP4Filename.c_str(), O_CREAT | O_LARGEFILE | O_TRUNC | O_RDWR, S_IRUSR | S_IWUSR);
     if (fd < 0) {
         fprintf(stderr, "couldn't open file");
         return;
@@ -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/common/DrmSupportInfo.cpp b/drm/common/DrmSupportInfo.cpp
index 584c6a6..6294f50 100644
--- a/drm/common/DrmSupportInfo.cpp
+++ b/drm/common/DrmSupportInfo.cpp
@@ -50,7 +50,7 @@
     for (size_t i = 0; i < mMimeTypeVector.size(); i++) {
         const String8 item = mMimeTypeVector.itemAt(i);
 
-        if (!strcasecmp(item.string(), mimeType.string())) {
+        if (!strcasecmp(item.c_str(), mimeType.c_str())) {
             return true;
         }
     }
@@ -61,7 +61,7 @@
     for (size_t i = 0; i < mFileSuffixVector.size(); i++) {
         const String8 item = mFileSuffixVector.itemAt(i);
 
-        if (!strcasecmp(item.string(), fileType.string())) {
+        if (!strcasecmp(item.c_str(), fileType.c_str())) {
             return true;
         }
     }
diff --git a/drm/common/IDrmManagerService.cpp b/drm/common/IDrmManagerService.cpp
index a6d33b0..1b49be1 100644
--- a/drm/common/IDrmManagerService.cpp
+++ b/drm/common/IDrmManagerService.cpp
@@ -303,8 +303,8 @@
         const String8 value = drmInforequest->get(key);
         if (key == String8("FileDescriptorKey")) {
             int fd = -1;
-            if (sscanf(value.string(), "FileDescriptor[%d]", &fd) != 1) {
-                sscanf(value.string(), "%d", &fd);
+            if (sscanf(value.c_str(), "FileDescriptor[%d]", &fd) != 1) {
+                sscanf(value.c_str(), "%d", &fd);
             }
             data.writeFileDescriptor(fd);
         } else {
@@ -1330,7 +1330,7 @@
         const String8 mime = data.readString8();
 
         sp<DecryptHandle> handle
-            = openDecryptSession(uniqueId, fd, offset, length, mime.string());
+            = openDecryptSession(uniqueId, fd, offset, length, mime.c_str());
 
         if (NULL != handle.get()) {
             writeDecryptHandleToParcelData(handle.get(), reply);
@@ -1349,7 +1349,7 @@
         const String8 uri = data.readString8();
         const String8 mime = data.readString8();
 
-        sp<DecryptHandle> handle = openDecryptSession(uniqueId, uri.string(), mime.string());
+        sp<DecryptHandle> handle = openDecryptSession(uniqueId, uri.c_str(), mime.c_str());
 
         if (NULL != handle.get()) {
             writeDecryptHandleToParcelData(handle.get(), reply);
diff --git a/drm/common/ReadWriteUtils.cpp b/drm/common/ReadWriteUtils.cpp
index 16b5b34..97c3716 100644
--- a/drm/common/ReadWriteUtils.cpp
+++ b/drm/common/ReadWriteUtils.cpp
@@ -34,7 +34,7 @@
 
 String8 ReadWriteUtils::readBytes(const String8& filePath) {
     FILE* file = NULL;
-    file = fopen(filePath.string(), "r");
+    file = fopen(filePath.c_str(), "r");
 
     String8 string("");
     if (NULL != file) {
@@ -56,7 +56,7 @@
 
 int ReadWriteUtils::readBytes(const String8& filePath, char** buffer) {
     FILE* file = NULL;
-    file = fopen(filePath.string(), "r");
+    file = fopen(filePath.c_str(), "r");
     off64_t length = 0;
 
     if (NULL != file) {
@@ -77,15 +77,15 @@
 
 void ReadWriteUtils::writeToFile(const String8& filePath, const String8& data) {
     FILE* file = NULL;
-    file = fopen(filePath.string(), "w+");
+    file = fopen(filePath.c_str(), "w+");
 
     if (NULL != file) {
         int fd = fileno(file);
 
         int size = data.size();
         if (FAILURE != ftruncate(fd, size)) {
-            if (size != write(fd, data.string(), size)) {
-                ALOGE("Failed to write the data to: %s", filePath.string());
+            if (size != write(fd, data.c_str(), size)) {
+                ALOGE("Failed to write the data to: %s", filePath.c_str());
             }
         }
         fclose(file);
@@ -94,14 +94,14 @@
 
 void ReadWriteUtils::appendToFile(const String8& filePath, const String8& data) {
     FILE* file = NULL;
-    file = fopen(filePath.string(), "a+");
+    file = fopen(filePath.c_str(), "a+");
 
     if (NULL != file) {
         int fd = fileno(file);
 
         int size = data.size();
-        if (size != write(fd, data.string(), size)) {
-            ALOGE("Failed to write the data to: %s", filePath.string());
+        if (size != write(fd, data.c_str(), size)) {
+            ALOGE("Failed to write the data to: %s", filePath.c_str());
         }
         fclose(file);
     }
diff --git a/drm/drmserver/Android.bp b/drm/drmserver/Android.bp
index cee44b9..81c2003 100644
--- a/drm/drmserver/Android.bp
+++ b/drm/drmserver/Android.bp
@@ -78,6 +78,9 @@
         "libselinux",
         "libstagefright_foundation",
     ],
+    whole_static_libs: [
+        "libc++fs",
+    ],
 
     cflags: [
         "-Wall",
@@ -124,6 +127,7 @@
     ],
 
     static_libs: [
+        "libc++fs",
         "libmediautils",
         "liblog",
         "libdrmframeworkcommon",
diff --git a/drm/drmserver/DrmManager.cpp b/drm/drmserver/DrmManager.cpp
index f7989bd..d32228b 100644
--- a/drm/drmserver/DrmManager.cpp
+++ b/drm/drmserver/DrmManager.cpp
@@ -39,6 +39,7 @@
 #include "ReadWriteUtils.h"
 
 #include <algorithm>
+#include <filesystem>
 
 #define DECRYPT_FILE_ERROR (-1)
 
@@ -114,7 +115,7 @@
     std::unique_ptr<DrmSupportInfo> info(engine.getSupportInfo(0));
 
     uid_t callingUid = IPCThreadState::self()->getCallingUid();
-    std::string plugInId(plugInId8.getPathLeaf().getBasePath().c_str());
+    std::string plugInId = std::filesystem::path(plugInId8.c_str()).stem();
     ALOGV("%d calling %s %s", callingUid, plugInId.c_str(), func);
 
     Mutex::Autolock _l(mMetricsLock);
@@ -127,7 +128,7 @@
         }
     }
 
-    if (!mimeType.isEmpty()) {
+    if (!mimeType.empty()) {
         metrics.mMimeTypes.insert(mimeType.c_str());
     } else if (NULL != info) {
         DrmSupportInfo::MimeTypeIterator mimeIter = info->getMimeTypeIterator();
@@ -316,8 +317,8 @@
             IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
             result = rDrmEngine.canHandle(uniqueId, path);
         } else {
-            String8 extension = path.getPathExtension();
-            if (String8("") != extension) {
+            const auto extension = std::filesystem::path(path.c_str()).extension();
+            if (!extension.empty()) {
                 result = canHandle(uniqueId, path);
             }
         }
@@ -395,7 +396,7 @@
         IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
         mimeType = rDrmEngine.getOriginalMimeType(uniqueId, path, fd);
     }
-    if (!mimeType.isEmpty()) {
+    if (!mimeType.empty()) {
         recordEngineMetrics(__func__, plugInId, mimeType);
     }
     return mimeType;
@@ -745,7 +746,7 @@
 
 String8 DrmManager::getSupportedPlugInIdFromPath(int uniqueId, const String8& path) {
     String8 plugInId("");
-    const String8 fileSuffix = path.getPathExtension();
+    const String8 fileSuffix(std::filesystem::path(path.c_str()).extension().c_str());
 
     for (size_t index = 0; index < mSupportInfoToPlugInIdMap.size(); index++) {
         const DrmSupportInfo& drmSupportInfo = mSupportInfoToPlugInIdMap.keyAt(index);
diff --git a/drm/drmserver/DrmManagerService.cpp b/drm/drmserver/DrmManagerService.cpp
index c830c6e..98eba2a 100644
--- a/drm/drmserver/DrmManagerService.cpp
+++ b/drm/drmserver/DrmManagerService.cpp
@@ -373,7 +373,7 @@
         (void)args;
 #endif
     }
-    write(fd, result.string(), result.size());
+    write(fd, result.c_str(), result.size());
     return NO_ERROR;
 }
 
diff --git a/drm/drmserver/PlugInManager.h b/drm/drmserver/PlugInManager.h
index 466844d..8a60b78 100644
--- a/drm/drmserver/PlugInManager.h
+++ b/drm/drmserver/PlugInManager.h
@@ -25,6 +25,8 @@
 #include <utils/Vector.h>
 #include <utils/KeyedVector.h>
 
+#include <filesystem>
+
 namespace android {
 
 const char* const PLUGIN_MANAGER_CREATE = "create";
@@ -137,7 +139,7 @@
 
         PlugInContainer* pPlugInContainer = new PlugInContainer();
 
-        pPlugInContainer->hHandle = dlopen(rsPlugInPath.string(), RTLD_LAZY);
+        pPlugInContainer->hHandle = dlopen(rsPlugInPath.c_str(), RTLD_LAZY);
 
         if (NULL == pPlugInContainer->hHandle) {
             delete pPlugInContainer;
@@ -201,7 +203,7 @@
      */
     Vector<String8> getPlugInPathList(const String8& rsDirPath) {
         Vector<String8> fileList;
-        DIR* pDir = opendir(rsDirPath.string());
+        DIR* pDir = opendir(rsDirPath.c_str());
         struct dirent* pEntry;
 
         while (NULL != pDir && NULL != (pEntry = readdir(pDir))) {
@@ -227,10 +229,9 @@
      * True if the input name denotes plug-in
      */
     bool isPlugIn(const struct dirent* pEntry) const {
-        String8 sName(pEntry->d_name);
-        String8 extension(sName.getPathExtension());
+        const auto extension = std::filesystem::path(pEntry->d_name).extension();
         // Note that the plug-in extension must exactly match case
-        return extension == String8(PLUGIN_EXTENSION);
+        return extension.string() == PLUGIN_EXTENSION;
     }
 
     /**
diff --git a/drm/libdrmframework/plugins/common/util/src/MimeTypeUtil.cpp b/drm/libdrmframework/plugins/common/util/src/MimeTypeUtil.cpp
index 3b1566f..d47a9d9 100644
--- a/drm/libdrmframework/plugins/common/util/src/MimeTypeUtil.cpp
+++ b/drm/libdrmframework/plugins/common/util/src/MimeTypeUtil.cpp
@@ -128,7 +128,7 @@
     struct MimeGroup* pGroup;
     struct MimeTypeList* pMimeItem;
     int len;
-    pMimeType = mimeType.string();
+    pMimeType = mimeType.c_str();
     if (NULL != pMimeType) {
         if ((0 == strncmp(pMimeType, mime_group_audio, (sizeof mime_group_audio) - 1)) ||
             (0 == strncmp(pMimeType, mime_group_video, (sizeof mime_group_video) - 1))) {
@@ -159,7 +159,7 @@
             result = String8(mime_type_unsupported);
         }
         LOG_DEBUG("convertMimeType got mimetype %s, converted into mimetype %s",
-                pMimeType, result.string());
+                pMimeType, result.c_str());
     }
     return result;
 }
diff --git a/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/Android.bp b/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/Android.bp
index 6e55a16..16ea15e 100644
--- a/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/Android.bp
+++ b/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/Android.bp
@@ -64,6 +64,10 @@
         "libfwdlock-decoder",
     ],
 
+    whole_static_libs: [
+        "libc++fs",
+    ],
+
     local_include_dirs: ["include"],
 
     relative_install_path: "drm",
diff --git a/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/src/FwdLockEngine.cpp b/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/src/FwdLockEngine.cpp
index 769de0c..1ade2f7 100644
--- a/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/src/FwdLockEngine.cpp
+++ b/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/src/FwdLockEngine.cpp
@@ -37,6 +37,8 @@
 #include "FwdLockGlue.h"
 #include "MimeTypeUtil.h"
 
+#include <filesystem>
+
 #undef LOG_TAG
 #define LOG_TAG "FwdLockEngine"
 
@@ -227,7 +229,7 @@
 bool FwdLockEngine::onCanHandle(int /* uniqueId */, const String8& path) {
     bool result = false;
 
-    String8 extString = path.getPathExtension();
+    String8 extString(std::filesystem::path(path.c_str()).extension().c_str());
     return IsFileSuffixSupported(extString);
 }
 
@@ -544,7 +546,7 @@
         String8 uriTag = String8(uri);
         uriTag.toLower();
 
-        if (0 == strncmp(uriTag.string(), fileTag, sizeof(fileTag) - 1)) {
+        if (0 == strncmp(uriTag.c_str(), fileTag, sizeof(fileTag) - 1)) {
             const char *filePath = strchr(uri + sizeof(fileTag) - 1, '/');
             if (NULL != filePath && onCanHandle(uniqueId, String8(filePath))) {
                 int fd = open(filePath, O_RDONLY);
diff --git a/drm/libdrmframework/plugins/passthru/Android.bp b/drm/libdrmframework/plugins/passthru/Android.bp
index 6dffd49..0a6cd47 100644
--- a/drm/libdrmframework/plugins/passthru/Android.bp
+++ b/drm/libdrmframework/plugins/passthru/Android.bp
@@ -39,11 +39,15 @@
     srcs: ["src/DrmPassthruPlugIn.cpp"],
 
     shared_libs: [
+        "libbase",
         "libutils",
         "liblog",
         "libdl",
         "libdrmframeworkcommon",
     ],
+    whole_static_libs: [
+        "libc++fs",
+    ],
 
     local_include_dirs: ["include"],
 
diff --git a/drm/libdrmframework/plugins/passthru/src/DrmPassthruPlugIn.cpp b/drm/libdrmframework/plugins/passthru/src/DrmPassthruPlugIn.cpp
index 0fa3478..55b4b08 100644
--- a/drm/libdrmframework/plugins/passthru/src/DrmPassthruPlugIn.cpp
+++ b/drm/libdrmframework/plugins/passthru/src/DrmPassthruPlugIn.cpp
@@ -18,6 +18,7 @@
 #define LOG_TAG "DrmPassthruPlugIn"
 #include <utils/Log.h>
 
+#include <android-base/strings.h>
 #include <drm/DrmRights.h>
 #include <drm/DrmConstraints.h>
 #include <drm/DrmMetadata.h>
@@ -29,6 +30,8 @@
 #include <drm/DrmSupportInfo.h>
 #include <DrmPassthruPlugIn.h>
 
+#include <filesystem>
+
 using namespace android;
 
 
@@ -64,7 +67,7 @@
     String8 value("dummy_available_time");
     char* charValue = NULL;
     charValue = new char[value.length() + 1];
-    strncpy(charValue, value.string(), value.length());
+    strncpy(charValue, value.c_str(), value.length());
     charValue[value.length()] = '\0';
 
     //Just add dummy available time for verification
@@ -95,7 +98,7 @@
             const int bufferSize = licenseString.size();
             char* data = NULL;
             data = new char[bufferSize];
-            memcpy(data, licenseString.string(), bufferSize);
+            memcpy(data, licenseString.c_str(), bufferSize);
             const DrmBuffer* buffer = new DrmBuffer(data, bufferSize);
             drmInfoStatus = new DrmInfoStatus(DrmInfoStatus::STATUS_OK,
                     DrmInfoRequest::TYPE_RIGHTS_ACQUISITION_INFO, buffer, drmInfo->getMimeType());
@@ -150,7 +153,7 @@
         int length = dataString.length();
         char* data = NULL;
         data = new char[length];
-        memcpy(data, dataString.string(), length);
+        memcpy(data, dataString.c_str(), length);
         drmInfo = new DrmInfo(drmInfoRequest->getInfoType(),
             DrmBuffer(data, length), drmInfoRequest->getMimeType());
     }
@@ -158,10 +161,9 @@
 }
 
 bool DrmPassthruPlugIn::onCanHandle(int /*uniqueId*/, const String8& path) {
-    ALOGV("DrmPassthruPlugIn::canHandle: %s ", path.string());
-    String8 extension = path.getPathExtension();
-    extension.toLower();
-    return (String8(".passthru") == extension);
+    ALOGV("DrmPassthruPlugIn::canHandle: %s ", path.c_str());
+    const auto extension = std::filesystem::path(path.c_str()).extension();
+    return base::EqualsIgnoreCase(extension.string(), ".passthru");
 }
 
 String8 DrmPassthruPlugIn::onGetOriginalMimeType(int uniqueId,
diff --git a/drm/libmediadrm/DrmHalAidl.cpp b/drm/libmediadrm/DrmHalAidl.cpp
index 5ec7337..7106d66 100644
--- a/drm/libmediadrm/DrmHalAidl.cpp
+++ b/drm/libmediadrm/DrmHalAidl.cpp
@@ -117,7 +117,7 @@
 }
 
 static std::string toStdString(const String8& string8) {
-    return std::string(string8.string());
+    return std::string(string8.c_str());
 }
 
 static std::vector<KeyValue> toKeyValueVector(const KeyedVector<String8, String8>& keyedVector) {
@@ -375,7 +375,7 @@
     sp<DrmHalAidl> drm = mDrm.promote();
     if (drm == NULL) {
         name.append("<deleted>");
-    } else if (drm->getPropertyStringInternal(String8("vendor"), name) != OK || name.isEmpty()) {
+    } else if (drm->getPropertyStringInternal(String8("vendor"), name) != OK || name.empty()) {
         name.append("<Get vendor failed or is empty>");
     }
     name.append("[");
@@ -415,7 +415,7 @@
     *isSupported = false;
     Uuid uuidAidl = DrmUtils::toAidlUuid(uuid);
     SecurityLevel levelAidl = toAidlSecurityLevel(level);
-    std::string mimeTypeStr = mimeType.string();
+    std::string mimeTypeStr = mimeType.c_str();
 
     for (ssize_t i = mFactories.size() - 1; i >= 0; i--) {
         CryptoSchemes schemes{};
@@ -947,12 +947,12 @@
 
     String8 vendor;
     String8 description;
-    if (getPropertyStringInternal(String8("vendor"), vendor) != OK || vendor.isEmpty()) {
+    if (getPropertyStringInternal(String8("vendor"), vendor) != OK || vendor.empty()) {
         ALOGE("Get vendor failed or is empty");
         vendor = "NONE";
     }
     if (getPropertyStringInternal(String8("description"), description) != OK ||
-        description.isEmpty()) {
+        description.empty()) {
         ALOGE("Get description failed or is empty.");
         description = "NONE";
     }
diff --git a/drm/libmediadrm/DrmHalHidl.cpp b/drm/libmediadrm/DrmHalHidl.cpp
index 00ea004..c8c6e8e 100644
--- a/drm/libmediadrm/DrmHalHidl.cpp
+++ b/drm/libmediadrm/DrmHalHidl.cpp
@@ -121,7 +121,7 @@
 }
 
 static hidl_string toHidlString(const String8& string) {
-    return hidl_string(string.string());
+    return hidl_string(string.c_str());
 }
 
 static DrmPlugin::SecurityLevel toSecurityLevel(SecurityLevel level) {
@@ -273,7 +273,7 @@
     sp<DrmHalHidl> drm = mDrm.promote();
     if (drm == NULL) {
         name.append("<deleted>");
-    } else if (drm->getPropertyStringInternal(String8("vendor"), name) != OK || name.isEmpty()) {
+    } else if (drm->getPropertyStringInternal(String8("vendor"), name) != OK || name.empty()) {
         name.append("<Get vendor failed or is empty>");
     }
     name.append("[");
@@ -353,7 +353,7 @@
 
     sp<IDrmPlugin> plugin;
     Return<void> hResult = factory->createPlugin(
-            uuid, appPackageName.string(), [&](Status status, const sp<IDrmPlugin>& hPlugin) {
+            uuid, appPackageName.c_str(), [&](Status status, const sp<IDrmPlugin>& hPlugin) {
                 if (status != Status::OK) {
                     DrmUtils::LOG2BE(uuid, "Failed to make drm plugin: %d", status);
                     return;
@@ -517,7 +517,7 @@
             return DrmStatus(OK);
         }
         // isCryptoSchemeSupported(uuid, mimeType)
-        auto hResult = factory->isContentTypeSupported(mimeType.string());
+        auto hResult = factory->isContentTypeSupported(mimeType.c_str());
         if (!hResult.isOk()) {
             return DrmStatus(DEAD_OBJECT);
         }
@@ -531,7 +531,7 @@
     if (factoryV1_2 == NULL) {
         return DrmStatus(ERROR_UNSUPPORTED);
     } else {
-        auto hResult = factoryV1_2->isCryptoSchemeSupported_1_2(uuid, mimeType.string(),
+        auto hResult = factoryV1_2->isCryptoSchemeSupported_1_2(uuid, mimeType.c_str(),
                                                                 toHidlSecurityLevel(level));
         if (!hResult.isOk()) {
             return DrmStatus(DEAD_OBJECT);
@@ -1261,12 +1261,12 @@
     if (mPluginV1_1 != NULL) {
         String8 vendor;
         String8 description;
-        if (getPropertyStringInternal(String8("vendor"), vendor) != OK || vendor.isEmpty()) {
+        if (getPropertyStringInternal(String8("vendor"), vendor) != OK || vendor.empty()) {
             ALOGE("Get vendor failed or is empty");
             vendor = "NONE";
         }
         if (getPropertyStringInternal(String8("description"), description) != OK ||
-            description.isEmpty()) {
+            description.empty()) {
             ALOGE("Get description failed or is empty.");
             description = "NONE";
         }
diff --git a/drm/libmediadrm/DrmMetricsLogger.cpp b/drm/libmediadrm/DrmMetricsLogger.cpp
index ce4d730..7d600cb 100644
--- a/drm/libmediadrm/DrmMetricsLogger.cpp
+++ b/drm/libmediadrm/DrmMetricsLogger.cpp
@@ -151,7 +151,7 @@
     if (status == OK) {
         String8 version8;
         if (getPropertyString(String8("version"), version8) == OK) {
-            mVersion = version8.string();
+            mVersion = version8.c_str();
         }
         reportMediaDrmCreated();
     } else {
diff --git a/drm/libmediadrm/DrmSessionManager.cpp b/drm/libmediadrm/DrmSessionManager.cpp
index 6744e25..989a597 100644
--- a/drm/libmediadrm/DrmSessionManager.cpp
+++ b/drm/libmediadrm/DrmSessionManager.cpp
@@ -172,7 +172,7 @@
         const std::shared_ptr<IResourceManagerClient>& drm, const Vector<uint8_t> &sessionId) {
     uid_t uid = AIBinder_getCallingUid();
     ALOGV("addSession(pid %d, uid %d, drm %p, sessionId %s)", pid, uid, drm.get(),
-            GetSessionIdString(sessionId).string());
+            GetSessionIdString(sessionId).c_str());
 
     Mutex::Autolock lock(mLock);
     if (mService == NULL) {
@@ -188,7 +188,7 @@
 }
 
 void DrmSessionManager::useSession(const Vector<uint8_t> &sessionId) {
-    ALOGV("useSession(%s)", GetSessionIdString(sessionId).string());
+    ALOGV("useSession(%s)", GetSessionIdString(sessionId).c_str());
 
     Mutex::Autolock lock(mLock);
     auto it = mSessionMap.find(toStdVec(sessionId));
@@ -205,7 +205,7 @@
 }
 
 void DrmSessionManager::removeSession(const Vector<uint8_t> &sessionId) {
-    ALOGV("removeSession(%s)", GetSessionIdString(sessionId).string());
+    ALOGV("removeSession(%s)", GetSessionIdString(sessionId).c_str());
 
     Mutex::Autolock lock(mLock);
     auto it = mSessionMap.find(toStdVec(sessionId));
diff --git a/drm/libmediadrm/SharedLibrary.cpp b/drm/libmediadrm/SharedLibrary.cpp
index b2d635d..97d5653 100644
--- a/drm/libmediadrm/SharedLibrary.cpp
+++ b/drm/libmediadrm/SharedLibrary.cpp
@@ -25,7 +25,7 @@
 namespace android {
 
     SharedLibrary::SharedLibrary(const String8 &path) {
-        mLibHandle = dlopen(path.string(), RTLD_NOW);
+        mLibHandle = dlopen(path.c_str(), RTLD_NOW);
     }
 
     SharedLibrary::~SharedLibrary() {
diff --git a/drm/mediacas/plugins/clearkey/ClearKeyCasPlugin.cpp b/drm/mediacas/plugins/clearkey/ClearKeyCasPlugin.cpp
index af7c367..c364bbb 100644
--- a/drm/mediacas/plugins/clearkey/ClearKeyCasPlugin.cpp
+++ b/drm/mediacas/plugins/clearkey/ClearKeyCasPlugin.cpp
@@ -131,7 +131,7 @@
     for (size_t i = 0; i < array.size(); i++) {
         result.appendFormat("%02x ", array[i]);
     }
-    if (result.isEmpty()) {
+    if (result.empty()) {
         result.append("(null)");
     }
     return result;
@@ -157,7 +157,7 @@
 }
 
 status_t ClearKeyCasPlugin::closeSession(const CasSessionId &sessionId) {
-    ALOGV("closeSession: sessionId=%s", sessionIdToString(sessionId).string());
+    ALOGV("closeSession: sessionId=%s", sessionIdToString(sessionId).c_str());
     std::shared_ptr<ClearKeyCasSession> session =
             ClearKeySessionLibrary::get()->findSession(sessionId);
     if (session.get() == nullptr) {
@@ -171,7 +171,7 @@
 status_t ClearKeyCasPlugin::setSessionPrivateData(
         const CasSessionId &sessionId, const CasData & /*data*/) {
     ALOGV("setSessionPrivateData: sessionId=%s",
-            sessionIdToString(sessionId).string());
+            sessionIdToString(sessionId).c_str());
     std::shared_ptr<ClearKeyCasSession> session =
             ClearKeySessionLibrary::get()->findSession(sessionId);
     if (session.get() == nullptr) {
@@ -182,7 +182,7 @@
 
 status_t ClearKeyCasPlugin::processEcm(
         const CasSessionId &sessionId, const CasEcm& ecm) {
-    ALOGV("processEcm: sessionId=%s", sessionIdToString(sessionId).string());
+    ALOGV("processEcm: sessionId=%s", sessionIdToString(sessionId).c_str());
     std::shared_ptr<ClearKeyCasSession> session =
             ClearKeySessionLibrary::get()->findSession(sessionId);
     if (session.get() == nullptr) {
@@ -220,7 +220,7 @@
         const CasSessionId &sessionId, int32_t event,
         int arg, const CasData &eventData) {
     ALOGV("sendSessionEvent: sessionId=%s, event=%d, arg=%d",
-          sessionIdToString(sessionId).string(), event, arg);
+          sessionIdToString(sessionId).c_str(), event, arg);
     // Echo the received event to the callback.
     // Clear key plugin doesn't use any event, echo'ing for testing only.
     if (mCallbackExt != NULL) {
@@ -232,12 +232,12 @@
 }
 
 status_t ClearKeyCasPlugin::provision(const String8 &str) {
-    ALOGV("provision: provisionString=%s", str.string());
+    ALOGV("provision: provisionString=%s", str.c_str());
     Mutex::Autolock lock(mKeyFetcherLock);
 
     std::unique_ptr<ClearKeyLicenseFetcher> license_fetcher;
     license_fetcher.reset(new ClearKeyLicenseFetcher());
-    status_t err = license_fetcher->Init(str.string());
+    status_t err = license_fetcher->Init(str.c_str());
     if (err != OK) {
         ALOGE("provision: failed to init ClearKeyLicenseFetcher (err=%d)", err);
         return err;
@@ -475,7 +475,7 @@
 
 status_t ClearKeyDescramblerPlugin::setMediaCasSession(
         const CasSessionId &sessionId) {
-    ALOGV("setMediaCasSession: sessionId=%s", sessionIdToString(sessionId).string());
+    ALOGV("setMediaCasSession: sessionId=%s", sessionIdToString(sessionId).c_str());
 
     std::shared_ptr<ClearKeyCasSession> session =
             ClearKeySessionLibrary::get()->findSession(sessionId);
@@ -503,7 +503,7 @@
     ALOGV("descramble: secure=%d, sctrl=%d, subSamples=%s, "
             "srcPtr=%p, dstPtr=%p, srcOffset=%d, dstOffset=%d",
           (int)secure, (int)scramblingControl,
-          subSamplesToString(subSamples, numSubSamples).string(),
+          subSamplesToString(subSamples, numSubSamples).c_str(),
           srcPtr, dstPtr, srcOffset, dstOffset);
 
     std::shared_ptr<ClearKeyCasSession> session = std::atomic_load(&mCASSession);
diff --git a/drm/mediacas/plugins/clearkey/JsonAssetLoader.cpp b/drm/mediacas/plugins/clearkey/JsonAssetLoader.cpp
index ee8dba3..07de1d2 100644
--- a/drm/mediacas/plugins/clearkey/JsonAssetLoader.cpp
+++ b/drm/mediacas/plugins/clearkey/JsonAssetLoader.cpp
@@ -80,7 +80,7 @@
         }
     }
 
-    return decodeBase64(AString(paddedText.string()));
+    return decodeBase64(AString(paddedText.c_str()));
 }
 
 bool JsonAssetLoader::findKey(const String8& jsonObject, Asset *asset) {
@@ -91,30 +91,30 @@
         return false;
     }
     findValue(kIdTag, &value);
-    ALOGV("found %s=%s", kIdTag.string(), value.string());
-    asset->set_id(atoi(value.string()));
+    ALOGV("found %s=%s", kIdTag.c_str(), value.c_str());
+    asset->set_id(atoi(value.c_str()));
 
     if (jsonObject.find(kNameTag) < 0) {
         return false;
     }
     findValue(kNameTag, &value);
-    ALOGV("found %s=%s", kNameTag.string(), value.string());
-    asset->set_name(value.string());
+    ALOGV("found %s=%s", kNameTag.c_str(), value.c_str());
+    asset->set_name(value.c_str());
 
     if (jsonObject.find(kLowerCaseOgranizationNameTag) < 0) {
         return false;
     }
     findValue(kLowerCaseOgranizationNameTag, &value);
-    ALOGV("found %s=%s", kLowerCaseOgranizationNameTag.string(), value.string());
-    asset->set_lowercase_organization_name(value.string());
+    ALOGV("found %s=%s", kLowerCaseOgranizationNameTag.c_str(), value.c_str());
+    asset->set_lowercase_organization_name(value.c_str());
 
     if (jsonObject.find(kCasTypeTag) < 0) {
         return false;
     }
     findValue(kCasTypeTag, &value);
-    ALOGV("found %s=%s", kCasTypeTag.string(), value.string());
+    ALOGV("found %s=%s", kCasTypeTag.c_str(), value.c_str());
     // Asset_CasType_CLEARKEY_CAS = 1
-    asset->set_cas_type((Asset_CasType)atoi(value.string()));
+    asset->set_cas_type((Asset_CasType)atoi(value.c_str()));
 
     return true;
 }
@@ -127,8 +127,8 @@
         if (0 == (*nextToken).compare(key)) {
             if (nextToken + 1 == mTokens.end())
                 break;
-            valueToken = (*(nextToken + 1)).string();
-            value->setTo(valueToken);
+            valueToken = (*(nextToken + 1)).c_str();
+            *value = valueToken;
             nextToken++;
             break;
         }
@@ -146,7 +146,7 @@
 
     jsmn_init(&parser);
     int numTokens = jsmn_parse(&parser,
-        jsonObject.string(), jsonObject.size(), NULL, 0);
+        jsonObject.c_str(), jsonObject.size(), NULL, 0);
     if (numTokens < 0) {
         ALOGE("Parser returns error code=%d", numTokens);
         return false;
@@ -157,7 +157,7 @@
     mJsmnTokens.setCapacity(jsmnTokensSize);
 
     jsmn_init(&parser);
-    int status = jsmn_parse(&parser, jsonObject.string(),
+    int status = jsmn_parse(&parser, jsonObject.c_str(),
         jsonObject.size(), mJsmnTokens.editArray(), numTokens);
     if (status < 0) {
         ALOGE("Parser returns error code=%d", status);
@@ -169,12 +169,12 @@
     const char *pjs;
     ALOGV("numTokens: %d", numTokens);
     for (int j = 0; j < numTokens; ++j) {
-        pjs = jsonObject.string() + mJsmnTokens[j].start;
+        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.string());
+            ALOGV("add token: %s", token.c_str());
         }
     }
     return true;
@@ -187,7 +187,7 @@
  */
 bool JsonAssetLoader::parseJsonAssetString(const String8& jsonAsset,
         Vector<String8>* jsonObjects) {
-    if (jsonAsset.isEmpty()) {
+    if (jsonAsset.empty()) {
         ALOGE("Empty JSON Web Key");
         return false;
     }
@@ -199,7 +199,7 @@
     // the original string.
     jsmn_init(&parser);
     int numTokens = jsmn_parse(&parser,
-            jsonAsset.string(), jsonAsset.size(), NULL, 0);
+            jsonAsset.c_str(), jsonAsset.size(), NULL, 0);
     if (numTokens < 0) {
         ALOGE("Parser returns error code=%d", numTokens);
         return false;
@@ -209,7 +209,7 @@
     mJsmnTokens.setCapacity(jsmnTokensSize);
 
     jsmn_init(&parser);
-    int status = jsmn_parse(&parser, jsonAsset.string(),
+    int status = jsmn_parse(&parser, jsonAsset.c_str(),
             jsonAsset.size(), mJsmnTokens.editArray(), numTokens);
     if (status < 0) {
         ALOGE("Parser returns error code=%d", status);
@@ -219,9 +219,9 @@
     String8 token;
     const char *pjs;
     for (int i = 0; i < numTokens; ++i) {
-        pjs = jsonAsset.string() + mJsmnTokens[i].start;
+        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/mediacas/plugins/mock/MockCasPlugin.cpp b/drm/mediacas/plugins/mock/MockCasPlugin.cpp
index f8bab0a..cbff6cb 100644
--- a/drm/mediacas/plugins/mock/MockCasPlugin.cpp
+++ b/drm/mediacas/plugins/mock/MockCasPlugin.cpp
@@ -96,7 +96,7 @@
     for (size_t i = 0; i < array.size(); i++) {
         result.appendFormat("%02x ", array[i]);
     }
-    if (result.isEmpty()) {
+    if (result.empty()) {
         result.append("(null)");
     }
     return result;
@@ -135,7 +135,7 @@
 }
 
 status_t MockCasPlugin::closeSession(const CasSessionId &sessionId) {
-    ALOGV("closeSession: sessionId=%s", arrayToString(sessionId).string());
+    ALOGV("closeSession: sessionId=%s", arrayToString(sessionId).c_str());
     Mutex::Autolock lock(mLock);
 
     sp<MockCasSession> session =
@@ -151,7 +151,7 @@
 status_t MockCasPlugin::setSessionPrivateData(
         const CasSessionId &sessionId, const CasData& /*data*/) {
     ALOGV("setSessionPrivateData: sessionId=%s",
-            arrayToString(sessionId).string());
+            arrayToString(sessionId).c_str());
     Mutex::Autolock lock(mLock);
 
     sp<MockCasSession> session =
@@ -164,7 +164,7 @@
 
 status_t MockCasPlugin::processEcm(
         const CasSessionId &sessionId, const CasEcm& ecm) {
-    ALOGV("processEcm: sessionId=%s", arrayToString(sessionId).string());
+    ALOGV("processEcm: sessionId=%s", arrayToString(sessionId).c_str());
     Mutex::Autolock lock(mLock);
 
     sp<MockCasSession> session =
@@ -173,7 +173,7 @@
         return BAD_VALUE;
     }
     ALOGV("ECM: size=%zu", ecm.size());
-    ALOGV("ECM: data=%s", arrayToString(ecm).string());
+    ALOGV("ECM: data=%s", arrayToString(ecm).c_str());
 
     return OK;
 }
@@ -183,7 +183,7 @@
     Mutex::Autolock lock(mLock);
 
     ALOGV("EMM: size=%zu", emm.size());
-    ALOGV("EMM: data=%s", arrayToString(emm).string());
+    ALOGV("EMM: data=%s", arrayToString(emm).c_str());
 
     return OK;
 }
@@ -200,14 +200,14 @@
         const CasSessionId &sessionId, int32_t event,
         int /*arg*/, const CasData& /*eventData*/) {
     ALOGV("sendSessionEvent: sessionId=%s, event=%d",
-          arrayToString(sessionId).string(), event);
+          arrayToString(sessionId).c_str(), event);
     Mutex::Autolock lock(mLock);
 
     return OK;
 }
 
 status_t MockCasPlugin::provision(const String8 &str) {
-    ALOGV("provision: provisionString=%s", str.string());
+    ALOGV("provision: provisionString=%s", str.c_str());
     Mutex::Autolock lock(mLock);
 
     return OK;
@@ -215,7 +215,7 @@
 
 status_t MockCasPlugin::refreshEntitlements(
         int32_t /*refreshType*/, const CasData &refreshData) {
-    ALOGV("refreshEntitlements: refreshData=%s", arrayToString(refreshData).string());
+    ALOGV("refreshEntitlements: refreshData=%s", arrayToString(refreshData).c_str());
     Mutex::Autolock lock(mLock);
 
     return OK;
@@ -256,7 +256,7 @@
     ALOGV("MockDescramblerPlugin::descramble(secure=%d, sctrl=%d,"
           "subSamples=%s, srcPtr=%p, dstPtr=%p, srcOffset=%d, dstOffset=%d)",
           (int)secure, (int)scramblingControl,
-          subSamplesToString(subSamples, numSubSamples).string(),
+          subSamplesToString(subSamples, numSubSamples).c_str(),
           srcPtr, dstPtr, srcOffset, dstOffset);
 
     return 0;
diff --git a/drm/mediadrm/plugins/clearkey/default/DrmPlugin.cpp b/drm/mediadrm/plugins/clearkey/default/DrmPlugin.cpp
index 089eb1c..7ee8d3d 100644
--- a/drm/mediadrm/plugins/clearkey/default/DrmPlugin.cpp
+++ b/drm/mediadrm/plugins/clearkey/default/DrmPlugin.cpp
@@ -142,7 +142,7 @@
         const String8& name, Vector<uint8_t>& value) const {
     ssize_t index = mByteArrayProperties.indexOfKey(name);
     if (index < 0) {
-        ALOGE("App requested unknown property: %s", name.string());
+        ALOGE("App requested unknown property: %s", name.c_str());
         return android::ERROR_DRM_CANNOT_HANDLE;
     }
     value = mByteArrayProperties.valueAt(index);
@@ -154,12 +154,12 @@
 {
     UNUSED(value);
     if (0 == name.compare(kDeviceIdKey)) {
-        ALOGD("Cannot set immutable property: %s", name.string());
+        ALOGD("Cannot set immutable property: %s", name.c_str());
         return android::ERROR_DRM_CANNOT_HANDLE;
     }
 
     // Setting of undefined properties is not supported
-    ALOGE("Failed to set property byte array, key=%s", name.string());
+    ALOGE("Failed to set property byte array, key=%s", name.c_str());
     return android::ERROR_DRM_CANNOT_HANDLE;
 }
 
@@ -167,7 +167,7 @@
         const String8& name, String8& value) const {
     ssize_t index = mStringProperties.indexOfKey(name);
     if (index < 0) {
-        ALOGE("App requested unknown property: %s", name.string());
+        ALOGE("App requested unknown property: %s", name.c_str());
         return android::ERROR_DRM_CANNOT_HANDLE;
     }
     value = mStringProperties.valueAt(index);
@@ -178,21 +178,21 @@
         const String8& name, const String8& value) {
     String8 immutableKeys;
     immutableKeys.appendFormat("%s,%s,%s,%s",
-            kAlgorithmsKey.string(), kPluginDescriptionKey.string(),
-            kVendorKey.string(), kVersionKey.string());
-    if (immutableKeys.contains(name.string())) {
-        ALOGD("Cannot set immutable property: %s", name.string());
+            kAlgorithmsKey.c_str(), kPluginDescriptionKey.c_str(),
+            kVendorKey.c_str(), kVersionKey.c_str());
+    if (immutableKeys.contains(name.c_str())) {
+        ALOGD("Cannot set immutable property: %s", name.c_str());
         return android::ERROR_DRM_CANNOT_HANDLE;
     }
 
     ssize_t index = mStringProperties.indexOfKey(name);
     if (index < 0) {
-        ALOGE("Cannot set undefined property string, key=%s", name.string());
+        ALOGE("Cannot set undefined property string, key=%s", name.c_str());
         return android::ERROR_DRM_CANNOT_HANDLE;
     }
 
     if (mStringProperties.add(name, value) < 0) {
-        ALOGE("Failed to set property string, key=%s", name.string());
+        ALOGE("Failed to set property string, key=%s", name.c_str());
         return android::ERROR_DRM_UNKNOWN;
     }
     return android::OK;
diff --git a/drm/mediadrm/plugins/clearkey/default/InitDataParser.cpp b/drm/mediadrm/plugins/clearkey/default/InitDataParser.cpp
index 121a4e2..ca697a2 100644
--- a/drm/mediadrm/plugins/clearkey/default/InitDataParser.cpp
+++ b/drm/mediadrm/plugins/clearkey/default/InitDataParser.cpp
@@ -69,7 +69,7 @@
     String8 requestJson = generateRequest(keyIds);
     licenseRequest->clear();
     licenseRequest->appendArray(
-            reinterpret_cast<const uint8_t*>(requestJson.string()),
+            reinterpret_cast<const uint8_t*>(requestJson.c_str()),
             requestJson.size());
     return android::OK;
 }
diff --git a/drm/mediadrm/plugins/clearkey/default/JsonWebKey.cpp b/drm/mediadrm/plugins/clearkey/default/JsonWebKey.cpp
index a2d506d..6db70c1 100644
--- a/drm/mediadrm/plugins/clearkey/default/JsonWebKey.cpp
+++ b/drm/mediadrm/plugins/clearkey/default/JsonWebKey.cpp
@@ -77,18 +77,18 @@
             return false;
 
         if (findKey(mJsonObjects[i], &encodedKeyId, &encodedKey)) {
-            if (encodedKeyId.isEmpty() || encodedKey.isEmpty()) {
+            if (encodedKeyId.empty() || encodedKey.empty()) {
                 ALOGE("Must have both key id and key in the JsonWebKey set.");
                 continue;
             }
 
             if (!decodeBase64String(encodedKeyId, &decodedKeyId)) {
-                ALOGE("Failed to decode key id(%s)", encodedKeyId.string());
+                ALOGE("Failed to decode key id(%s)", encodedKeyId.c_str());
                 continue;
             }
 
             if (!decodeBase64String(encodedKey, &decodedKey)) {
-                ALOGE("Failed to decode key(%s)", encodedKey.string());
+                ALOGE("Failed to decode key(%s)", encodedKey.c_str());
                 continue;
             }
 
@@ -119,7 +119,7 @@
     }
 
     android::sp<ABuffer> buffer =
-            android::decodeBase64(AString(paddedText.string()));
+            android::decodeBase64(AString(paddedText.c_str()));
     if (buffer == NULL) {
         ALOGE("Malformed base64 encoded content found.");
         return false;
@@ -159,8 +159,8 @@
         if (0 == (*nextToken).compare(key)) {
             if (nextToken + 1 == mTokens.end())
                 break;
-            valueToken = (*(nextToken + 1)).string();
-            value->setTo(valueToken);
+            valueToken = (*(nextToken + 1)).c_str();
+            *value = valueToken;
             nextToken++;
             break;
         }
@@ -186,7 +186,7 @@
 
     jsmn_init(&parser);
     int numTokens = jsmn_parse(&parser,
-        jsonObject.string(), jsonObject.size(), NULL, 0);
+        jsonObject.c_str(), jsonObject.size(), NULL, 0);
     if (numTokens < 0) {
         ALOGE("Parser returns error code=%d", numTokens);
         return false;
@@ -197,7 +197,7 @@
     mJsmnTokens.setCapacity(jsmnTokensSize);
 
     jsmn_init(&parser);
-    int status = jsmn_parse(&parser, jsonObject.string(),
+    int status = jsmn_parse(&parser, jsonObject.c_str(),
         jsonObject.size(), mJsmnTokens.editArray(), numTokens);
     if (status < 0) {
         ALOGE("Parser returns error code=%d", status);
@@ -208,10 +208,10 @@
     String8 token;
     const char *pjs;
     for (int j = 0; j < numTokens; ++j) {
-        pjs = jsonObject.string() + mJsmnTokens[j].start;
+        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);
         }
     }
@@ -225,7 +225,7 @@
  */
 bool JsonWebKey::parseJsonWebKeySet(const String8& jsonWebKeySet,
         Vector<String8>* jsonObjects) {
-    if (jsonWebKeySet.isEmpty()) {
+    if (jsonWebKeySet.empty()) {
         ALOGE("Empty JSON Web Key");
         return false;
     }
@@ -237,7 +237,7 @@
     // the original string.
     jsmn_init(&parser);
     int numTokens = jsmn_parse(&parser,
-            jsonWebKeySet.string(), jsonWebKeySet.size(), NULL, 0);
+            jsonWebKeySet.c_str(), jsonWebKeySet.size(), NULL, 0);
     if (numTokens < 0) {
         ALOGE("Parser returns error code=%d", numTokens);
         return false;
@@ -247,7 +247,7 @@
     mJsmnTokens.setCapacity(jsmnTokensSize);
 
     jsmn_init(&parser);
-    int status = jsmn_parse(&parser, jsonWebKeySet.string(),
+    int status = jsmn_parse(&parser, jsonWebKeySet.c_str(),
             jsonWebKeySet.size(), mJsmnTokens.editArray(), numTokens);
     if (status < 0) {
         ALOGE("Parser returns error code=%d", status);
@@ -257,9 +257,9 @@
     String8 token;
     const char *pjs;
     for (int i = 0; i < numTokens; ++i) {
-        pjs = jsonWebKeySet.string() + mJsmnTokens[i].start;
+        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/drm/mediadrm/plugins/clearkey/default/SessionLibrary.cpp b/drm/mediadrm/plugins/clearkey/default/SessionLibrary.cpp
index 529230e..058f8ce 100644
--- a/drm/mediadrm/plugins/clearkey/default/SessionLibrary.cpp
+++ b/drm/mediadrm/plugins/clearkey/default/SessionLibrary.cpp
@@ -50,7 +50,7 @@
     mNextSessionId += 1;
     Vector<uint8_t> sessionId;
     sessionId.appendArray(
-            reinterpret_cast<const uint8_t*>(sessionIdString.string()),
+            reinterpret_cast<const uint8_t*>(sessionIdString.c_str()),
             sessionIdString.size());
 
     mSessions.add(sessionId, new Session(sessionId));
diff --git a/drm/mediadrm/plugins/mock/MockDrmCryptoPlugin.cpp b/drm/mediadrm/plugins/mock/MockDrmCryptoPlugin.cpp
index 3b4145f..db98a80 100644
--- a/drm/mediadrm/plugins/mock/MockDrmCryptoPlugin.cpp
+++ b/drm/mediadrm/plugins/mock/MockDrmCryptoPlugin.cpp
@@ -91,14 +91,14 @@
         }
         mSessions.add(sessionId);
 
-        ALOGD("MockDrmPlugin::openSession() -> %s", vectorToString(sessionId).string());
+        ALOGD("MockDrmPlugin::openSession() -> %s", vectorToString(sessionId).c_str());
         return OK;
     }
 
     status_t MockDrmPlugin::closeSession(Vector<uint8_t> const &sessionId)
     {
         Mutex::Autolock lock(mLock);
-        ALOGD("MockDrmPlugin::closeSession(%s)", vectorToString(sessionId).string());
+        ALOGD("MockDrmPlugin::closeSession(%s)", vectorToString(sessionId).c_str());
         ssize_t index = findSession(sessionId);
         if (index == kNotFound) {
             ALOGD("Invalid sessionId");
@@ -119,8 +119,8 @@
         Mutex::Autolock lock(mLock);
         ALOGD("MockDrmPlugin::getKeyRequest(sessionId=%s, initData=%s, mimeType=%s"
               ", keyType=%d, optionalParameters=%s))",
-              vectorToString(sessionId).string(), vectorToString(initData).string(), mimeType.string(),
-              keyType, stringMapToString(optionalParameters).string());
+              vectorToString(sessionId).c_str(), vectorToString(initData).c_str(), mimeType.c_str(),
+              keyType, stringMapToString(optionalParameters).c_str());
 
         ssize_t index = findSession(sessionId);
         if (index == kNotFound) {
@@ -144,8 +144,8 @@
         String8 params;
         for (size_t i = 0; i < optionalParameters.size(); i++) {
             params.appendFormat("%s{%s,%s}", i ? "," : "",
-                                optionalParameters.keyAt(i).string(),
-                                optionalParameters.valueAt(i).string());
+                                optionalParameters.keyAt(i).c_str(),
+                                optionalParameters.valueAt(i).c_str());
         }
         mStringProperties.add(String8("mock-optparams"), params);
 
@@ -176,7 +176,7 @@
             return BAD_VALUE;
         } else {
             *keyRequestType = static_cast<KeyRequestType>(
-                atoi(mStringProperties.valueAt(index).string()));
+                atoi(mStringProperties.valueAt(index).c_str()));
         }
 
         return OK;
@@ -188,7 +188,7 @@
     {
         Mutex::Autolock lock(mLock);
         ALOGD("MockDrmPlugin::provideKeyResponse(sessionId=%s, response=%s)",
-              vectorToString(sessionId).string(), vectorToString(response).string());
+              vectorToString(sessionId).c_str(), vectorToString(response).c_str());
         ssize_t index = findSession(sessionId);
         if (index == kNotFound) {
             ALOGD("Invalid sessionId");
@@ -217,7 +217,7 @@
     {
         Mutex::Autolock lock(mLock);
         ALOGD("MockDrmPlugin::removeKeys(keySetId=%s)",
-              vectorToString(keySetId).string());
+              vectorToString(keySetId).c_str());
 
         ssize_t index = findKeySet(keySetId);
         if (index == kNotFound) {
@@ -234,8 +234,8 @@
     {
         Mutex::Autolock lock(mLock);
         ALOGD("MockDrmPlugin::restoreKeys(sessionId=%s, keySetId=%s)",
-              vectorToString(sessionId).string(),
-              vectorToString(keySetId).string());
+              vectorToString(sessionId).c_str(),
+              vectorToString(keySetId).c_str());
         ssize_t index = findSession(sessionId);
         if (index == kNotFound) {
             ALOGD("Invalid sessionId");
@@ -255,7 +255,7 @@
                                                KeyedVector<String8, String8> &infoMap) const
     {
         ALOGD("MockDrmPlugin::queryKeyStatus(sessionId=%s)",
-              vectorToString(sessionId).string());
+              vectorToString(sessionId).c_str());
 
         ssize_t index = findSession(sessionId);
         if (index == kNotFound) {
@@ -304,7 +304,7 @@
     {
         Mutex::Autolock lock(mLock);
         ALOGD("MockDrmPlugin::provideProvisionResponse(%s)",
-              vectorToString(response).string());
+              vectorToString(response).c_str());
 
         // Properties used in mock test, set by mock plugin and verifed cts test app
         //   byte[] response            -> mock-response
@@ -367,7 +367,7 @@
     {
         Mutex::Autolock lock(mLock);
         ALOGD("MockDrmPlugin::releaseSecureStops(%s)",
-              vectorToString(ssRelease).string());
+              vectorToString(ssRelease).c_str());
 
         // Properties used in mock test, set by mock plugin and verifed cts test app
         //   byte[] secure-stop-release  -> mock-ssrelease
@@ -385,10 +385,10 @@
 
     status_t MockDrmPlugin::getPropertyString(String8 const &name, String8 &value) const
     {
-        ALOGD("MockDrmPlugin::getPropertyString(name=%s)", name.string());
+        ALOGD("MockDrmPlugin::getPropertyString(name=%s)", name.c_str());
         ssize_t index = mStringProperties.indexOfKey(name);
         if (index < 0) {
-            ALOGD("no property for '%s'", name.string());
+            ALOGD("no property for '%s'", name.c_str());
             return BAD_VALUE;
         }
         value = mStringProperties.valueAt(index);
@@ -398,10 +398,10 @@
     status_t MockDrmPlugin::getPropertyByteArray(String8 const &name,
                                                  Vector<uint8_t> &value) const
     {
-        ALOGD("MockDrmPlugin::getPropertyByteArray(name=%s)", name.string());
+        ALOGD("MockDrmPlugin::getPropertyByteArray(name=%s)", name.c_str());
         ssize_t index = mByteArrayProperties.indexOfKey(name);
         if (index < 0) {
-            ALOGD("no property for '%s'", name.string());
+            ALOGD("no property for '%s'", name.c_str());
             return BAD_VALUE;
         }
         value = mByteArrayProperties.valueAt(index);
@@ -413,11 +413,11 @@
     {
         Mutex::Autolock lock(mLock);
         ALOGD("MockDrmPlugin::setPropertyString(name=%s, value=%s)",
-              name.string(), value.string());
+              name.c_str(), value.c_str());
 
         if (name == "mock-send-event") {
             unsigned code, extra;
-            sscanf(value.string(), "%d %d", &code, &extra);
+            sscanf(value.c_str(), "%d %d", &code, &extra);
             DrmPlugin::EventType eventType = (DrmPlugin::EventType)code;
 
             Vector<uint8_t> const *pSessionId = NULL;
@@ -438,7 +438,7 @@
             sendEvent(eventType, extra, pSessionId, pData);
         } else if (name == "mock-send-expiration-update") {
             int64_t expiryTimeMS;
-            sscanf(value.string(), "%jd", &expiryTimeMS);
+            sscanf(value.c_str(), "%jd", &expiryTimeMS);
 
             Vector<uint8_t> const *pSessionId = NULL;
             ssize_t index = mByteArrayProperties.indexOfKey(String8("mock-event-session-id"));
@@ -504,7 +504,7 @@
     {
         Mutex::Autolock lock(mLock);
         ALOGD("MockDrmPlugin::setPropertyByteArray(name=%s, value=%s)",
-              name.string(), vectorToString(value).string());
+              name.c_str(), vectorToString(value).c_str());
         mByteArrayProperties.add(name, value);
         return OK;
     }
@@ -515,7 +515,7 @@
         Mutex::Autolock lock(mLock);
 
         ALOGD("MockDrmPlugin::setCipherAlgorithm(sessionId=%s, algorithm=%s)",
-              vectorToString(sessionId).string(), algorithm.string());
+              vectorToString(sessionId).c_str(), algorithm.c_str());
 
         ssize_t index = findSession(sessionId);
         if (index == kNotFound) {
@@ -535,7 +535,7 @@
         Mutex::Autolock lock(mLock);
 
         ALOGD("MockDrmPlugin::setMacAlgorithm(sessionId=%s, algorithm=%s)",
-              vectorToString(sessionId).string(), algorithm.string());
+              vectorToString(sessionId).c_str(), algorithm.c_str());
 
         ssize_t index = findSession(sessionId);
         if (index == kNotFound) {
@@ -557,10 +557,10 @@
     {
         Mutex::Autolock lock(mLock);
         ALOGD("MockDrmPlugin::encrypt(sessionId=%s, keyId=%s, input=%s, iv=%s)",
-              vectorToString(sessionId).string(),
-              vectorToString(keyId).string(),
-              vectorToString(input).string(),
-              vectorToString(iv).string());
+              vectorToString(sessionId).c_str(),
+              vectorToString(keyId).c_str(),
+              vectorToString(input).c_str(),
+              vectorToString(iv).c_str());
 
         ssize_t index = findSession(sessionId);
         if (index == kNotFound) {
@@ -596,10 +596,10 @@
     {
         Mutex::Autolock lock(mLock);
         ALOGD("MockDrmPlugin::decrypt(sessionId=%s, keyId=%s, input=%s, iv=%s)",
-              vectorToString(sessionId).string(),
-              vectorToString(keyId).string(),
-              vectorToString(input).string(),
-              vectorToString(iv).string());
+              vectorToString(sessionId).c_str(),
+              vectorToString(keyId).c_str(),
+              vectorToString(input).c_str(),
+              vectorToString(iv).c_str());
 
         ssize_t index = findSession(sessionId);
         if (index == kNotFound) {
@@ -634,9 +634,9 @@
     {
         Mutex::Autolock lock(mLock);
         ALOGD("MockDrmPlugin::sign(sessionId=%s, keyId=%s, message=%s)",
-              vectorToString(sessionId).string(),
-              vectorToString(keyId).string(),
-              vectorToString(message).string());
+              vectorToString(sessionId).c_str(),
+              vectorToString(keyId).c_str(),
+              vectorToString(message).c_str());
 
         ssize_t index = findSession(sessionId);
         if (index == kNotFound) {
@@ -670,10 +670,10 @@
     {
         Mutex::Autolock lock(mLock);
         ALOGD("MockDrmPlugin::verify(sessionId=%s, keyId=%s, message=%s, signature=%s)",
-              vectorToString(sessionId).string(),
-              vectorToString(keyId).string(),
-              vectorToString(message).string(),
-              vectorToString(signature).string());
+              vectorToString(sessionId).c_str(),
+              vectorToString(keyId).c_str(),
+              vectorToString(message).c_str(),
+              vectorToString(signature).c_str());
 
         ssize_t index = findSession(sessionId);
         if (index == kNotFound) {
@@ -696,7 +696,7 @@
             ALOGD("Missing 'mock-request' parameter for mock");
             return BAD_VALUE;
         } else {
-            match = atol(mStringProperties.valueAt(index).string());
+            match = atol(mStringProperties.valueAt(index).c_str());
         }
         return OK;
     }
@@ -710,11 +710,11 @@
         Mutex::Autolock lock(mLock);
         ALOGD("MockDrmPlugin::signRSA(sessionId=%s, algorithm=%s, keyId=%s, "
               "message=%s, signature=%s)",
-              vectorToString(sessionId).string(),
-              algorithm.string(),
-              vectorToString(message).string(),
-              vectorToString(wrappedKey).string(),
-              vectorToString(signature).string());
+              vectorToString(sessionId).c_str(),
+              algorithm.c_str(),
+              vectorToString(message).c_str(),
+              vectorToString(wrappedKey).c_str(),
+              vectorToString(signature).c_str());
 
         // Properties used in mock test, set by mock plugin and verifed cts test app
         //   byte[] wrappedKey         -> mock-wrappedkey
@@ -772,7 +772,7 @@
         String8 result("{ ");
         for (size_t i = 0; i < map.size(); i++) {
             result.appendFormat("%s{name=%s, value=%s}", i > 0 ? ", " : "",
-                                map.keyAt(i).string(), map.valueAt(i).string());
+                                map.keyAt(i).c_str(), map.valueAt(i).c_str());
         }
         return result + " }";
     }
@@ -802,10 +802,10 @@
               "pattern:{encryptBlocks=%d, skipBlocks=%d} src=%p, "
               "subSamples=%s, dst=%p)",
               (int)secure,
-              arrayToString(key, DECRYPT_KEY_SIZE).string(),
-              arrayToString(iv, DECRYPT_KEY_SIZE).string(),
+              arrayToString(key, DECRYPT_KEY_SIZE).c_str(),
+              arrayToString(iv, DECRYPT_KEY_SIZE).c_str(),
               (int)mode, pattern.mEncryptBlocks, pattern.mSkipBlocks, srcPtr,
-              subSamplesToString(subSamples, numSubSamples).string(),
+              subSamplesToString(subSamples, numSubSamples).c_str(),
               dstPtr);
         return OK;
     }
diff --git a/include/private/media/VideoFrame.h b/include/private/media/VideoFrame.h
index 11e1704..ec99fac 100644
--- a/include/private/media/VideoFrame.h
+++ b/include/private/media/VideoFrame.h
@@ -37,10 +37,12 @@
     // will calculate frame buffer size if |hasData| is set to true.
     VideoFrame(uint32_t width, uint32_t height,
             uint32_t displayWidth, uint32_t displayHeight,
+            uint32_t displayLeft, uint32_t displayTop,
             uint32_t tileWidth, uint32_t tileHeight,
             uint32_t angle, uint32_t bpp, uint32_t bitDepth, bool hasData, size_t iccSize):
         mWidth(width), mHeight(height),
         mDisplayWidth(displayWidth), mDisplayHeight(displayHeight),
+        mDisplayLeft(displayLeft), mDisplayTop(displayTop),
         mTileWidth(tileWidth), mTileHeight(tileHeight), mDurationUs(0),
         mRotationAngle(angle), mBytesPerPixel(bpp), mIccSize(iccSize),
         mBitDepth(bitDepth) {
@@ -82,6 +84,8 @@
     uint32_t mHeight;          // Decoded image height before rotation
     uint32_t mDisplayWidth;    // Display width before rotation
     uint32_t mDisplayHeight;   // Display height before rotation
+    uint32_t mDisplayLeft;     // Display left (column coordinate) before rotation
+    uint32_t mDisplayTop;      // Display top (row coordinate) before rotation
     uint32_t mTileWidth;       // Tile width (0 if image doesn't have grid)
     uint32_t mTileHeight;      // Tile height (0 if image doesn't have grid)
     int64_t  mDurationUs;      // Frame duration in microseconds
diff --git a/media/audioaidlconversion/AidlConversionCppNdk.cpp b/media/audioaidlconversion/AidlConversionCppNdk.cpp
index 4d3f9bd..7ea51ff 100644
--- a/media/audioaidlconversion/AidlConversionCppNdk.cpp
+++ b/media/audioaidlconversion/AidlConversionCppNdk.cpp
@@ -508,15 +508,6 @@
             {
                 AUDIO_DEVICE_IN_ECHO_REFERENCE, make_AudioDeviceDescription(
                         AudioDeviceType::IN_ECHO_REFERENCE)
-            },
-            {
-                AUDIO_DEVICE_IN_REMOTE_SUBMIX, make_AudioDeviceDescription(
-                         AudioDeviceType::IN_SUBMIX)
-            },
-            {
-                AUDIO_DEVICE_OUT_REMOTE_SUBMIX, make_AudioDeviceDescription(
-                        AudioDeviceType::OUT_SUBMIX,
-                        GET_DEVICE_DESC_CONNECTION(VIRTUAL))
             }
         }};
         append_AudioDeviceDescription(pairs,
@@ -592,6 +583,11 @@
                 AUDIO_DEVICE_IN_BLE_HEADSET, AUDIO_DEVICE_OUT_BLE_HEADSET,
                 AudioDeviceType::IN_HEADSET, AudioDeviceType::OUT_HEADSET,
                 GET_DEVICE_DESC_CONNECTION(BT_LE));
+        append_AudioDeviceDescription(pairs,
+                AUDIO_DEVICE_IN_REMOTE_SUBMIX, AUDIO_DEVICE_OUT_REMOTE_SUBMIX,
+                AudioDeviceType::IN_SUBMIX, AudioDeviceType::OUT_SUBMIX,
+                GET_DEVICE_DESC_CONNECTION(VIRTUAL));
+
         return pairs;
     }();
     return pairs;
diff --git a/media/audioaidlconversion/TEST_MAPPING b/media/audioaidlconversion/TEST_MAPPING
index 216bc12..203ed2f 100644
--- a/media/audioaidlconversion/TEST_MAPPING
+++ b/media/audioaidlconversion/TEST_MAPPING
@@ -1,8 +1,12 @@
 {
   "presubmit": [
     {
-      "name": "audio_aidl_conversion_tests",
-      "name": "audio_aidl_ndk_conversion_tests",
+      "name": "audio_aidl_conversion_tests"
+    },
+    {
+      "name": "audio_aidl_ndk_conversion_tests"
+    },
+    {
       "name": "audio_aidl_ndk_cpp_conversion_tests"
     }
   ]
diff --git a/media/codec2/hal/aidl/Android.bp b/media/codec2/hal/aidl/Android.bp
index 01cd354..b19f78c 100644
--- a/media/codec2/hal/aidl/Android.bp
+++ b/media/codec2/hal/aidl/Android.bp
@@ -8,28 +8,36 @@
     name: "libcodec2_aidl_client",
 
     srcs: [
+        "BufferTypes.cpp",
         "ParamTypes.cpp",
     ],
 
     header_libs: [
-        "libcodec2_hal_common",
         "libcodec2_internal", // private
         "libgui_headers",
     ],
 
     shared_libs: [
+        "android.hardware.common-V2-ndk",
         "android.hardware.media.bufferpool@2.0",
+        "android.hardware.media.bufferpool2-V1-ndk",
         "android.hardware.media.c2-V1-ndk",
         "libbinder_ndk",
         "libbase",
         "libcodec2",
+        "libcodec2_hal_common",
         "libcodec2_vndk",
         "libcutils",
         "liblog",
         "libnativewindow",
+        "libstagefright_aidl_bufferpool2",
         "libutils",
     ],
 
+    static_libs: [
+        "libaidlcommonsupport",
+    ],
+
     export_include_dirs: [
         "include",
     ],
@@ -37,6 +45,7 @@
     export_shared_lib_headers: [
         "android.hardware.media.c2-V1-ndk",
         "libcodec2",
+        "libcodec2_hal_common",
     ],
 }
 
diff --git a/media/codec2/hal/aidl/BufferTypes.cpp b/media/codec2/hal/aidl/BufferTypes.cpp
index 319ba62..1cd3555 100644
--- a/media/codec2/hal/aidl/BufferTypes.cpp
+++ b/media/codec2/hal/aidl/BufferTypes.cpp
@@ -15,10 +15,15 @@
  */
 
 //#define LOG_NDEBUG 0
-#define LOG_TAG "Codec2-types"
+#define LOG_TAG "Codec2-AIDL-BufferTypes"
 #include <android-base/logging.h>
 
-#include <codec2/hidl/1.0/types.h>
+#include <aidlcommonsupport/NativeHandle.h>
+#include <aidl/android/hardware/media/bufferpool2/BufferStatusMessage.h>
+#include <bufferpool2/BufferPoolTypes.h>
+#include <codec2/aidl/BufferTypes.h>
+#include <codec2/common/BufferTypes.h>
+#include <cutils/native_handle.h>
 #include <media/stagefright/foundation/AUtils.h>
 
 #include <C2AllocatorIon.h>
@@ -28,1431 +33,42 @@
 #include <C2Component.h>
 #include <C2FenceFactory.h>
 #include <C2Param.h>
-#include <C2ParamInternal.h>
 #include <C2PlatformSupport.h>
 #include <C2Work.h>
-#include <util/C2ParamUtils.h>
 
 #include <algorithm>
 #include <functional>
 #include <iomanip>
 #include <unordered_map>
 
+#include "ParamTypes-specialization.h"
+
 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;
+using ::aidl::android::hardware::media::bufferpool2::BufferPoolData;
+using ::aidl::android::hardware::media::bufferpool2::BufferStatusMessage;
+using ::aidl::android::hardware::media::bufferpool2::ResultStatus;
+using ::aidl::android::hardware::media::bufferpool2::implementation::BufferPoolStatus;
+using ::aidl::android::hardware::media::bufferpool2::implementation::ClientManager;
+using ::aidl::android::hardware::media::c2::BaseBlock;
+using ::aidl::android::hardware::media::c2::utils::BufferPoolTypes;
 
-const char* asString(Status status, const char* def) {
-    return asString(static_cast<c2_status_t>(status), def);
-}
+using AidlNativeHandle = ::aidl::android::hardware::common::NativeHandle;
 
-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)) {
-    }
-};
-
-// 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;
-}
-
-// 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;
-}
-
-// 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;
-}
-
-// 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;
-}
-
-// 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
-// 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 (!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(
-        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
-bool objcpy(
-        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;
-}
-
-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 (!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;
-}
+constexpr BaseBlock::Tag NATIVE_BLOCK = BaseBlock::nativeBlock;
+constexpr BaseBlock::Tag POOLED_BLOCK = BaseBlock::pooledBlock;
 
 // BaseBlock -> C2BaseBlock
+template<>
 bool objcpy(C2BaseBlock* d, const BaseBlock& s) {
-    switch (s.getDiscriminator()) {
-    case BaseBlock::hidl_discriminator::nativeBlock: {
-            if (s.nativeBlock() == nullptr) {
+    switch (s.getTag()) {
+    case NATIVE_BLOCK: {
+            if (isAidlNativeHandleEmpty(s.get<NATIVE_BLOCK>())) {
                 LOG(ERROR) << "Null BaseBlock::nativeBlock handle";
                 return false;
             }
             native_handle_t* sHandle =
-                    native_handle_clone(s.nativeBlock());
+                    ::android::dupFromAidl(s.get<NATIVE_BLOCK>());
             if (sHandle == nullptr) {
                 LOG(ERROR) << "Null BaseBlock::nativeBlock.";
                 return false;
@@ -1460,15 +76,17 @@
             const C2Handle *sC2Handle =
                     reinterpret_cast<const C2Handle*>(sHandle);
 
+            // If successful, the handle is deleted(!) and fds are owned by the block.
             d->linear = _C2BlockFactory::CreateLinearBlock(sC2Handle);
             if (d->linear) {
-                d->type = C2BaseBlock::LINEAR;
+                d->type = ::android::C2BaseBlock::LINEAR;
                 return true;
             }
 
+            // If successful, the handle is deleted(!) and fds are owned by the block.
             d->graphic = _C2BlockFactory::CreateGraphicBlock(sC2Handle);
             if (d->graphic) {
-                d->type = C2BaseBlock::GRAPHIC;
+                d->type = ::android::C2BaseBlock::GRAPHIC;
                 return true;
             }
 
@@ -1479,13 +97,12 @@
             }
             return false;
         }
-    case BaseBlock::hidl_discriminator::pooledBlock: {
-            const BufferStatusMessage &bpMessage =
-                    s.pooledBlock();
-            sp<ClientManager> bp = ClientManager::getInstance();
+    case POOLED_BLOCK: {
+            const BufferStatusMessage &bpMessage = s.get<POOLED_BLOCK>();
+            std::shared_ptr<ClientManager> bp = ClientManager::getInstance();
             std::shared_ptr<BufferPoolData> bpData;
             native_handle_t *cHandle;
-            ResultStatus bpStatus = bp->receive(
+            BufferPoolStatus bpStatus = bp->receive(
                     bpMessage.connectionId,
                     bpMessage.transactionId,
                     bpMessage.bufferId,
@@ -1494,23 +111,24 @@
                     &bpData);
             if (bpStatus != ResultStatus::OK) {
                 LOG(ERROR) << "Failed to receive buffer from bufferpool -- "
-                           << "resultStatus = " << underlying_value(bpStatus)
-                           << ".";
+                           << "resultStatus = " << bpStatus << ".";
                 return false;
             } else if (!bpData) {
                 LOG(ERROR) << "No data in bufferpool transaction.";
                 return false;
             }
 
+            // If successful, the handle is deleted(!) and fds are owned by the block.
             d->linear = _C2BlockFactory::CreateLinearBlock(cHandle, bpData);
             if (d->linear) {
-                d->type = C2BaseBlock::LINEAR;
+                d->type = ::android::C2BaseBlock::LINEAR;
                 return true;
             }
 
+            // If successful, the handle is deleted(!) and fds are owned by the block.
             d->graphic = _C2BlockFactory::CreateGraphicBlock(cHandle, bpData);
             if (d->graphic) {
-                d->type = C2BaseBlock::GRAPHIC;
+                d->type = ::android::C2BaseBlock::GRAPHIC;
                 return true;
             }
             if (cHandle) {
@@ -1525,404 +143,193 @@
     default:
         LOG(ERROR) << "Unrecognized BaseBlock's discriminator with "
                    << "underlying value "
-                   << underlying_value(s.getDiscriminator()) << ".";
+                   << ::android::underlying_value(s.getTag()) << ".";
         return false;
     }
 }
 
-} // unnamed namespace
+// C2Fence -> AidlNativeHandle
+template<>
+bool objcpy(AidlNativeHandle* d, const C2Fence& s) {
+    // fds are not duplicated here
+    native_handle_t* handle = _C2FenceFactory::CreateNativeHandle(s);
+    if (handle) {
+        // |d| copies the fds without duplicating
+        *d = makeToAidl(handle);
+        // no fds are duplicated, just delete the handle
+        // Note: C2Fence still owns the fds and should not be cleared
+        // before the transaction is complete.
+        native_handle_delete(handle);
+//  } 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;
+}
+
+// AidlNativeHandle -> C2Fence
+template<>
+bool objcpy(C2Fence* d, const AidlNativeHandle& s) {
+    // makeFromAidl does not duplicate the fds.
+    native_handle_t* handle = makeFromAidl(s);
+    // C2Fence duplicates and owns the fds
+    *d = _C2FenceFactory::CreateFromNativeHandle(handle);
+    if (handle) {
+        // |handle| should not be closed here, as the fds are owned by |s|
+        native_handle_delete(handle);
+    }
+    return true;
+}
+
+template<>
+void SetHandle(BaseBlock *block, const C2Handle *handle) {
+    block->set<BaseBlock::nativeBlock>(makeToAidl(handle));
+}
+
+template<>
+void SetPooledBlock<BufferPoolTypes>(
+        BaseBlock *baseBlock,
+        const typename BufferPoolTypes::BufferStatusMessage &pooledBlock) {
+    baseBlock->set<POOLED_BLOCK>(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 android
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace media {
+namespace c2 {
+namespace utils {
+
+namespace bufferpool2 = ::aidl::android::hardware::media::bufferpool2;
+namespace bufferpool2_impl = ::aidl::android::hardware::media::bufferpool2::implementation;
+
+// DefaultBufferPoolSender's implementation
+
+DefaultBufferPoolSender::DefaultBufferPoolSender(
+        const std::shared_ptr<IClientManager>& receiverManager,
+        std::chrono::steady_clock::duration refreshInterval)
+    : mReceiverManager(receiverManager),
+      mRefreshInterval(refreshInterval) {
+}
+
+void DefaultBufferPoolSender::setReceiver(
+        const std::shared_ptr<IClientManager>& receiverManager,
+        std::chrono::steady_clock::duration refreshInterval) {
+    std::lock_guard<std::mutex> lock(mMutex);
+    if (mReceiverManager != receiverManager) {
+        mReceiverManager = receiverManager;
+        mConnections.clear();
+    }
+    mRefreshInterval = refreshInterval;
+}
+
+BufferPoolTypes::BufferPoolStatus DefaultBufferPoolSender::send(
+        const std::shared_ptr<bufferpool2::BufferPoolData>& bpData,
+        bufferpool2::BufferStatusMessage* bpMessage) {
+    int64_t connectionId = bpData->mConnectionId;
+    if (connectionId == 0) {
+        LOG(WARNING) << "registerSender -- invalid sender connection id (0).";
+        return bufferpool2::ResultStatus::CRITICAL_ERROR;
+    }
+    std::lock_guard<std::mutex> lock(mMutex);
+    if (!mReceiverManager) {
+        LOG(ERROR) << "No access to receiver's BufferPool.";
+        return bufferpool2::ResultStatus::NOT_FOUND;
+    }
+    if (!mSenderManager) {
+        mSenderManager = ClientManager::getInstance();
+        if (!mSenderManager) {
+            LOG(ERROR) << "Failed to retrieve local BufferPool ClientManager.";
+            return bufferpool2::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.
+        bufferpool2_impl::BufferPoolStatus rs =
+                mSenderManager->registerSender(mReceiverManager,
+                                               connectionId,
+                                               &receiverConnectionId,
+                                               &isNewConnection);
+        if ((rs != bufferpool2::ResultStatus::OK)
+                && (rs != bufferpool2::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 bufferpool2::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;
+    bufferpool2_impl::BufferPoolStatus rs = mSenderManager->postSend(
+            receiverConnectionId, bpData, &transactionId, &timestampUs);
+    if (rs != bufferpool2::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 bufferpool2::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
+bool ToAidl(
+        WorkBundle* d,
+        const std::list<std::unique_ptr<C2Work>>& s,
+        ::android::BufferPoolSender<BufferPoolTypes>* bufferPoolSender) {
+    return ::android::objcpy(d, s, bufferPoolSender);
+}
 
 // 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;
-}
-
-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");
-
-// 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;
-
-    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(
-        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;
+bool FromAidl(std::list<std::unique_ptr<C2Work>>* d, const WorkBundle& s) {
+    return ::android::objcpy(d, s);
 }
 
 }  // namespace utils
-}  // namespace V1_0
 }  // namespace c2
 }  // namespace media
 }  // namespace hardware
 }  // namespace android
+}  // namespace aidl
 
diff --git a/media/codec2/hal/aidl/Component.cpp b/media/codec2/hal/aidl/Component.cpp
new file mode 100644
index 0000000..7994d32
--- /dev/null
+++ b/media/codec2/hal/aidl/Component.cpp
@@ -0,0 +1,566 @@
+/*
+ * Copyright 2021 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-Component@1.2"
+#include <android-base/logging.h>
+
+#include <codec2/hidl/1.2/Component.h>
+#include <codec2/hidl/1.2/ComponentStore.h>
+#include <codec2/hidl/1.2/InputBufferManager.h>
+
+#ifndef __ANDROID_APEX__
+#include <FilterWrapper.h>
+#endif
+
+#include <hidl/HidlBinderSupport.h>
+#include <utils/Timers.h>
+
+#include <C2BqBufferPriv.h>
+#include <C2Debug.h>
+#include <C2PlatformSupport.h>
+
+#include <chrono>
+#include <thread>
+
+namespace android {
+namespace hardware {
+namespace media {
+namespace c2 {
+namespace V1_2 {
+namespace utils {
+
+using namespace ::android;
+
+// ComponentListener wrapper
+struct Component::Listener : public C2Component::Listener {
+
+    Listener(const sp<Component>& component) :
+        mComponent(component),
+        mListener(component->mListener) {
+    }
+
+    virtual void onError_nb(
+            std::weak_ptr<C2Component> /* c2component */,
+            uint32_t errorCode) override {
+        sp<IComponentListener> listener = mListener.promote();
+        if (listener) {
+            Return<void> transStatus = listener->onError(Status::OK, errorCode);
+            if (!transStatus.isOk()) {
+                LOG(ERROR) << "Component::Listener::onError_nb -- "
+                           << "transaction failed.";
+            }
+        }
+    }
+
+    virtual void onTripped_nb(
+            std::weak_ptr<C2Component> /* c2component */,
+            std::vector<std::shared_ptr<C2SettingResult>> c2settingResult
+            ) override {
+        sp<IComponentListener> listener = mListener.promote();
+        if (listener) {
+            hidl_vec<SettingResult> settingResults(c2settingResult.size());
+            size_t ix = 0;
+            for (const std::shared_ptr<C2SettingResult> &c2result :
+                    c2settingResult) {
+                if (c2result) {
+                    if (!objcpy(&settingResults[ix++], *c2result)) {
+                        break;
+                    }
+                }
+            }
+            settingResults.resize(ix);
+            Return<void> transStatus = listener->onTripped(settingResults);
+            if (!transStatus.isOk()) {
+                LOG(ERROR) << "Component::Listener::onTripped_nb -- "
+                           << "transaction failed.";
+            }
+        }
+    }
+
+    virtual void onWorkDone_nb(
+            std::weak_ptr<C2Component> /* c2component */,
+            std::list<std::unique_ptr<C2Work>> c2workItems) override {
+        for (const std::unique_ptr<C2Work>& work : c2workItems) {
+            if (work) {
+                if (work->worklets.empty()
+                        || !work->worklets.back()
+                        || (work->worklets.back()->output.flags &
+                            C2FrameData::FLAG_INCOMPLETE) == 0) {
+                    InputBufferManager::
+                            unregisterFrameData(mListener, work->input);
+                }
+            }
+        }
+
+        sp<IComponentListener> listener = mListener.promote();
+        if (listener) {
+            WorkBundle workBundle;
+
+            sp<Component> strongComponent = mComponent.promote();
+            beginTransferBufferQueueBlocks(c2workItems, true);
+            if (!objcpy(&workBundle, c2workItems, strongComponent ?
+                    &strongComponent->mBufferPoolSender : nullptr)) {
+                LOG(ERROR) << "Component::Listener::onWorkDone_nb -- "
+                           << "received corrupted work items.";
+                endTransferBufferQueueBlocks(c2workItems, false, true);
+                return;
+            }
+            Return<void> transStatus = listener->onWorkDone(workBundle);
+            if (!transStatus.isOk()) {
+                LOG(ERROR) << "Component::Listener::onWorkDone_nb -- "
+                           << "transaction failed.";
+                endTransferBufferQueueBlocks(c2workItems, false, true);
+                return;
+            }
+            endTransferBufferQueueBlocks(c2workItems, true, true);
+        }
+    }
+
+protected:
+    wp<Component> mComponent;
+    wp<IComponentListener> mListener;
+};
+
+// Component::Sink
+struct Component::Sink : public IInputSink {
+    std::shared_ptr<Component> mComponent;
+    sp<IConfigurable> mConfigurable;
+
+    virtual Return<Status> queue(const WorkBundle& workBundle) override {
+        return mComponent->queue(workBundle);
+    }
+
+    virtual Return<sp<IConfigurable>> getConfigurable() override {
+        return mConfigurable;
+    }
+
+    Sink(const std::shared_ptr<Component>& component);
+    virtual ~Sink() override;
+
+    // Process-wide map: Component::Sink -> C2Component.
+    static std::mutex sSink2ComponentMutex;
+    static std::map<IInputSink*, std::weak_ptr<C2Component>> sSink2Component;
+
+    static std::shared_ptr<C2Component> findLocalComponent(
+            const sp<IInputSink>& sink);
+};
+
+std::mutex
+        Component::Sink::sSink2ComponentMutex{};
+std::map<IInputSink*, std::weak_ptr<C2Component>>
+        Component::Sink::sSink2Component{};
+
+Component::Sink::Sink(const std::shared_ptr<Component>& component)
+        : mComponent{component},
+          mConfigurable{[&component]() -> sp<IConfigurable> {
+              Return<sp<IComponentInterface>> ret1 = component->getInterface();
+              if (!ret1.isOk()) {
+                  LOG(ERROR) << "Sink::Sink -- component's transaction failed.";
+                  return nullptr;
+              }
+              Return<sp<IConfigurable>> ret2 =
+                      static_cast<sp<IComponentInterface>>(ret1)->
+                      getConfigurable();
+              if (!ret2.isOk()) {
+                  LOG(ERROR) << "Sink::Sink -- interface's transaction failed.";
+                  return nullptr;
+              }
+              return static_cast<sp<IConfigurable>>(ret2);
+          }()} {
+    std::lock_guard<std::mutex> lock(sSink2ComponentMutex);
+    sSink2Component.emplace(this, component->mComponent);
+}
+
+Component::Sink::~Sink() {
+    std::lock_guard<std::mutex> lock(sSink2ComponentMutex);
+    sSink2Component.erase(this);
+}
+
+std::shared_ptr<C2Component> Component::Sink::findLocalComponent(
+        const sp<IInputSink>& sink) {
+    std::lock_guard<std::mutex> lock(sSink2ComponentMutex);
+    auto i = sSink2Component.find(sink.get());
+    if (i == sSink2Component.end()) {
+        return nullptr;
+    }
+    return i->second.lock();
+}
+
+// Component
+Component::Component(
+        const std::shared_ptr<C2Component>& component,
+        const sp<IComponentListener>& listener,
+        const sp<ComponentStore>& store,
+        const sp<::android::hardware::media::bufferpool::V2_0::
+        IClientManager>& clientPoolManager)
+      : mComponent{component},
+        mInterface{new ComponentInterface(component->intf(),
+                                          store->getParameterCache())},
+        mListener{listener},
+        mStore{store},
+        mBufferPoolSender{clientPoolManager} {
+    // Retrieve supported parameters from store
+    // TODO: We could cache this per component/interface type
+    mInit = mInterface->status();
+}
+
+c2_status_t Component::status() const {
+    return mInit;
+}
+
+// Methods from ::android::hardware::media::c2::V1_1::IComponent
+Return<Status> Component::queue(const WorkBundle& workBundle) {
+    std::list<std::unique_ptr<C2Work>> c2works;
+
+    if (!objcpy(&c2works, workBundle)) {
+        return Status::CORRUPTED;
+    }
+
+    // Register input buffers.
+    for (const std::unique_ptr<C2Work>& work : c2works) {
+        if (work) {
+            InputBufferManager::
+                    registerFrameData(mListener, work->input);
+        }
+    }
+
+    return static_cast<Status>(mComponent->queue_nb(&c2works));
+}
+
+Return<void> Component::flush(flush_cb _hidl_cb) {
+    std::list<std::unique_ptr<C2Work>> c2flushedWorks;
+    c2_status_t c2res = mComponent->flush_sm(
+            C2Component::FLUSH_COMPONENT,
+            &c2flushedWorks);
+
+    // Unregister input buffers.
+    for (const std::unique_ptr<C2Work>& work : c2flushedWorks) {
+        if (work) {
+            if (work->worklets.empty()
+                    || !work->worklets.back()
+                    || (work->worklets.back()->output.flags &
+                        C2FrameData::FLAG_INCOMPLETE) == 0) {
+                InputBufferManager::
+                        unregisterFrameData(mListener, work->input);
+            }
+        }
+    }
+
+    WorkBundle flushedWorkBundle;
+    Status res = static_cast<Status>(c2res);
+    beginTransferBufferQueueBlocks(c2flushedWorks, true);
+    if (c2res == C2_OK) {
+        if (!objcpy(&flushedWorkBundle, c2flushedWorks, &mBufferPoolSender)) {
+            res = Status::CORRUPTED;
+        }
+    }
+    _hidl_cb(res, flushedWorkBundle);
+    endTransferBufferQueueBlocks(c2flushedWorks, true, true);
+    return Void();
+}
+
+Return<Status> Component::drain(bool withEos) {
+    return static_cast<Status>(mComponent->drain_nb(withEos ?
+            C2Component::DRAIN_COMPONENT_WITH_EOS :
+            C2Component::DRAIN_COMPONENT_NO_EOS));
+}
+
+Return<Status> Component::setOutputSurface(
+        uint64_t blockPoolId,
+        const sp<HGraphicBufferProducer2>& surface) {
+    std::shared_ptr<C2BlockPool> pool;
+    GetCodec2BlockPool(blockPoolId, mComponent, &pool);
+    if (pool && pool->getAllocatorId() == C2PlatformAllocatorStore::BUFFERQUEUE) {
+        std::shared_ptr<C2BufferQueueBlockPool> bqPool =
+                std::static_pointer_cast<C2BufferQueueBlockPool>(pool);
+        C2BufferQueueBlockPool::OnRenderCallback cb =
+            [this](uint64_t producer, int32_t slot, int64_t nsecs) {
+                // TODO: batch this
+                hidl_vec<IComponentListener::RenderedFrame> rendered;
+                rendered.resize(1);
+                rendered[0] = { producer, slot, nsecs };
+                (void)mListener->onFramesRendered(rendered).isOk();
+        };
+        if (bqPool) {
+            bqPool->setRenderCallback(cb);
+            bqPool->configureProducer(surface);
+        }
+    }
+    return Status::OK;
+}
+
+Return<void> Component::connectToInputSurface(
+        const sp<IInputSurface>& inputSurface,
+        connectToInputSurface_cb _hidl_cb) {
+    Status status;
+    sp<IInputSurfaceConnection> connection;
+    auto transStatus = inputSurface->connect(
+            asInputSink(),
+            [&status, &connection](
+                    Status s, const sp<IInputSurfaceConnection>& c) {
+                status = s;
+                connection = c;
+            }
+        );
+    _hidl_cb(status, connection);
+    return Void();
+}
+
+Return<void> Component::connectToOmxInputSurface(
+        const sp<HGraphicBufferProducer1>& producer,
+        const sp<::android::hardware::media::omx::V1_0::
+        IGraphicBufferSource>& source,
+        connectToOmxInputSurface_cb _hidl_cb) {
+    (void)producer;
+    (void)source;
+    (void)_hidl_cb;
+    return Void();
+}
+
+Return<Status> Component::disconnectFromInputSurface() {
+    // TODO implement
+    return Status::OK;
+}
+
+namespace /* unnamed */ {
+
+struct BlockPoolIntf : public ConfigurableC2Intf {
+    BlockPoolIntf(const std::shared_ptr<C2BlockPool>& pool)
+          : ConfigurableC2Intf{
+                "C2BlockPool:" +
+                    (pool ? std::to_string(pool->getLocalId()) : "null"),
+                0},
+            mPool{pool} {
+    }
+
+    virtual c2_status_t config(
+            const std::vector<C2Param*>& params,
+            c2_blocking_t mayBlock,
+            std::vector<std::unique_ptr<C2SettingResult>>* const failures
+            ) override {
+        (void)params;
+        (void)mayBlock;
+        (void)failures;
+        return C2_OK;
+    }
+
+    virtual c2_status_t query(
+            const std::vector<C2Param::Index>& indices,
+            c2_blocking_t mayBlock,
+            std::vector<std::unique_ptr<C2Param>>* const params
+            ) const override {
+        (void)indices;
+        (void)mayBlock;
+        (void)params;
+        return C2_OK;
+    }
+
+    virtual c2_status_t querySupportedParams(
+            std::vector<std::shared_ptr<C2ParamDescriptor>>* const params
+            ) const override {
+        (void)params;
+        return C2_OK;
+    }
+
+    virtual c2_status_t querySupportedValues(
+            std::vector<C2FieldSupportedValuesQuery>& fields,
+            c2_blocking_t mayBlock) const override {
+        (void)fields;
+        (void)mayBlock;
+        return C2_OK;
+    }
+
+protected:
+    std::shared_ptr<C2BlockPool> mPool;
+};
+
+} // unnamed namespace
+
+Return<void> Component::createBlockPool(
+        uint32_t allocatorId,
+        createBlockPool_cb _hidl_cb) {
+    std::shared_ptr<C2BlockPool> blockPool;
+#ifdef __ANDROID_APEX__
+    c2_status_t status = CreateCodec2BlockPool(
+            static_cast<C2PlatformAllocatorStore::id_t>(allocatorId),
+            mComponent,
+            &blockPool);
+#else
+    c2_status_t status = ComponentStore::GetFilterWrapper()->createBlockPool(
+            static_cast<C2PlatformAllocatorStore::id_t>(allocatorId),
+            mComponent,
+            &blockPool);
+#endif
+    if (status != C2_OK) {
+        blockPool = nullptr;
+    }
+    if (blockPool) {
+        mBlockPoolsMutex.lock();
+        mBlockPools.emplace(blockPool->getLocalId(), blockPool);
+        mBlockPoolsMutex.unlock();
+    } else if (status == C2_OK) {
+        status = C2_CORRUPTED;
+    }
+
+    _hidl_cb(static_cast<Status>(status),
+            blockPool ? blockPool->getLocalId() : 0,
+            new CachedConfigurable(
+            std::make_unique<BlockPoolIntf>(blockPool)));
+    return Void();
+}
+
+Return<Status> Component::destroyBlockPool(uint64_t blockPoolId) {
+    std::lock_guard<std::mutex> lock(mBlockPoolsMutex);
+    return mBlockPools.erase(blockPoolId) == 1 ?
+            Status::OK : Status::CORRUPTED;
+}
+
+Return<Status> Component::start() {
+    return static_cast<Status>(mComponent->start());
+}
+
+Return<Status> Component::stop() {
+    InputBufferManager::unregisterFrameData(mListener);
+    return static_cast<Status>(mComponent->stop());
+}
+
+Return<Status> Component::reset() {
+    Status status = static_cast<Status>(mComponent->reset());
+    {
+        std::lock_guard<std::mutex> lock(mBlockPoolsMutex);
+        mBlockPools.clear();
+    }
+    InputBufferManager::unregisterFrameData(mListener);
+    return status;
+}
+
+Return<Status> Component::release() {
+    Status status = static_cast<Status>(mComponent->release());
+    {
+        std::lock_guard<std::mutex> lock(mBlockPoolsMutex);
+        mBlockPools.clear();
+    }
+    InputBufferManager::unregisterFrameData(mListener);
+    return status;
+}
+
+Return<sp<IComponentInterface>> Component::getInterface() {
+    return sp<IComponentInterface>(mInterface);
+}
+
+Return<sp<IInputSink>> Component::asInputSink() {
+    std::lock_guard<std::mutex> lock(mSinkMutex);
+    if (!mSink) {
+        mSink = new Sink(shared_from_this());
+    }
+    return {mSink};
+}
+
+Return<void> Component::configureVideoTunnel(
+        uint32_t avSyncHwId, configureVideoTunnel_cb _hidl_cb) {
+    (void)avSyncHwId;
+    _hidl_cb(Status::OMITTED, hidl_handle{});
+    return Void();
+}
+
+Return<Status> Component::setOutputSurfaceWithSyncObj(
+        uint64_t blockPoolId, const sp<HGraphicBufferProducer2>& surface,
+        const SurfaceSyncObj& syncObject) {
+    std::shared_ptr<C2BlockPool> pool;
+    GetCodec2BlockPool(blockPoolId, mComponent, &pool);
+    if (pool && pool->getAllocatorId() == C2PlatformAllocatorStore::BUFFERQUEUE) {
+        std::shared_ptr<C2BufferQueueBlockPool> bqPool =
+                std::static_pointer_cast<C2BufferQueueBlockPool>(pool);
+        C2BufferQueueBlockPool::OnRenderCallback cb =
+            [this](uint64_t producer, int32_t slot, int64_t nsecs) {
+                // TODO: batch this
+                hidl_vec<IComponentListener::RenderedFrame> rendered;
+                rendered.resize(1);
+                rendered[0] = { producer, slot, nsecs };
+                (void)mListener->onFramesRendered(rendered).isOk();
+        };
+        if (bqPool) {
+            const native_handle_t *h = syncObject.syncMemory;
+            native_handle_t *syncMemory = h ? native_handle_clone(h) : nullptr;
+            uint64_t bqId = syncObject.bqId;
+            uint32_t generationId = syncObject.generationId;
+            uint64_t consumerUsage = syncObject.consumerUsage;
+
+            bqPool->setRenderCallback(cb);
+            bqPool->configureProducer(surface, syncMemory, bqId,
+                                      generationId, consumerUsage);
+        }
+    }
+    return Status::OK;
+}
+
+std::shared_ptr<C2Component> Component::findLocalComponent(
+        const sp<IInputSink>& sink) {
+    return Component::Sink::findLocalComponent(sink);
+}
+
+void Component::initListener(const sp<Component>& self) {
+    std::shared_ptr<C2Component::Listener> c2listener =
+            std::make_shared<Listener>(self);
+    c2_status_t res = mComponent->setListener_vb(c2listener, C2_DONT_BLOCK);
+    if (res != C2_OK) {
+        mInit = res;
+    }
+
+    struct ListenerDeathRecipient : public HwDeathRecipient {
+        ListenerDeathRecipient(const wp<Component>& comp)
+            : component{comp} {
+        }
+
+        virtual void serviceDied(
+                uint64_t /* cookie */,
+                const wp<::android::hidl::base::V1_0::IBase>& /* who */
+                ) override {
+            auto strongComponent = component.promote();
+            if (strongComponent) {
+                LOG(INFO) << "Client died ! release the component !!";
+                strongComponent->release();
+            } else {
+                LOG(ERROR) << "Client died ! no component to release !!";
+            }
+        }
+
+        wp<Component> component;
+    };
+
+    mDeathRecipient = new ListenerDeathRecipient(self);
+    Return<bool> transStatus = mListener->linkToDeath(
+            mDeathRecipient, 0);
+    if (!transStatus.isOk()) {
+        LOG(ERROR) << "Listener linkToDeath() transaction failed.";
+    }
+    if (!static_cast<bool>(transStatus)) {
+        LOG(DEBUG) << "Listener linkToDeath() call failed.";
+    }
+}
+
+Component::~Component() {
+    InputBufferManager::unregisterFrameData(mListener);
+    mStore->reportComponentDeath(this);
+}
+
+} // namespace utils
+} // namespace V1_2
+} // namespace c2
+} // namespace media
+} // namespace hardware
+} // namespace android
diff --git a/media/codec2/hal/aidl/ComponentInterface.cpp b/media/codec2/hal/aidl/ComponentInterface.cpp
new file mode 100644
index 0000000..12078e0
--- /dev/null
+++ b/media/codec2/hal/aidl/ComponentInterface.cpp
@@ -0,0 +1,110 @@
+/*
+ * 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-ComponentInterface"
+#include <android-base/logging.h>
+
+#include <codec2/hidl/1.0/Component.h>
+#include <codec2/hidl/1.0/ComponentInterface.h>
+#include <codec2/hidl/1.0/ComponentStore.h>
+
+#include <hidl/HidlBinderSupport.h>
+#include <utils/Timers.h>
+
+#include <C2BqBufferPriv.h>
+#include <C2Debug.h>
+#include <C2PlatformSupport.h>
+
+#include <chrono>
+#include <thread>
+
+namespace android {
+namespace hardware {
+namespace media {
+namespace c2 {
+namespace V1_0 {
+namespace utils {
+
+using namespace ::android;
+
+namespace /* unnamed */ {
+
+// Implementation of ConfigurableC2Intf based on C2ComponentInterface
+struct CompIntf : public ConfigurableC2Intf {
+    CompIntf(const std::shared_ptr<C2ComponentInterface>& intf) :
+        ConfigurableC2Intf{intf->getName(), intf->getId()},
+        mIntf{intf} {
+    }
+
+    virtual c2_status_t config(
+            const std::vector<C2Param*>& params,
+            c2_blocking_t mayBlock,
+            std::vector<std::unique_ptr<C2SettingResult>>* const failures
+            ) override {
+        return mIntf->config_vb(params, mayBlock, failures);
+    }
+
+    virtual c2_status_t query(
+            const std::vector<C2Param::Index>& indices,
+            c2_blocking_t mayBlock,
+            std::vector<std::unique_ptr<C2Param>>* const params
+            ) const override {
+        return mIntf->query_vb({}, indices, mayBlock, params);
+    }
+
+    virtual c2_status_t querySupportedParams(
+            std::vector<std::shared_ptr<C2ParamDescriptor>>* const params
+            ) const override {
+        return mIntf->querySupportedParams_nb(params);
+    }
+
+    virtual c2_status_t querySupportedValues(
+            std::vector<C2FieldSupportedValuesQuery>& fields,
+            c2_blocking_t mayBlock) const override {
+        return mIntf->querySupportedValues_vb(fields, mayBlock);
+    }
+
+protected:
+    std::shared_ptr<C2ComponentInterface> mIntf;
+};
+
+} // unnamed namespace
+
+// ComponentInterface
+ComponentInterface::ComponentInterface(
+        const std::shared_ptr<C2ComponentInterface>& intf,
+        const std::shared_ptr<ParameterCache>& cache)
+      : mInterface{intf},
+        mConfigurable{new CachedConfigurable(std::make_unique<CompIntf>(intf))} {
+    mInit = mConfigurable->init(cache);
+}
+
+c2_status_t ComponentInterface::status() const {
+    return mInit;
+}
+
+Return<sp<IConfigurable>> ComponentInterface::getConfigurable() {
+    return mConfigurable;
+}
+
+}  // namespace utils
+}  // namespace V1_0
+}  // namespace c2
+}  // namespace media
+}  // namespace hardware
+}  // namespace android
+
diff --git a/media/codec2/hal/aidl/ComponentStore.cpp b/media/codec2/hal/aidl/ComponentStore.cpp
new file mode 100644
index 0000000..9fac5d5
--- /dev/null
+++ b/media/codec2/hal/aidl/ComponentStore.cpp
@@ -0,0 +1,562 @@
+/*
+ * Copyright 2021 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-ComponentStore@1.2"
+#include <android-base/logging.h>
+
+#include <codec2/hidl/1.2/ComponentStore.h>
+#include <codec2/hidl/1.2/InputSurface.h>
+#include <codec2/hidl/1.2/types.h>
+
+#include <android-base/file.h>
+#include <media/stagefright/bqhelper/GraphicBufferSource.h>
+#include <utils/Errors.h>
+
+#include <C2PlatformSupport.h>
+#include <util/C2InterfaceHelper.h>
+
+#include <chrono>
+#include <ctime>
+#include <iomanip>
+#include <ostream>
+#include <sstream>
+
+#ifndef __ANDROID_APEX__
+#include <codec2/hidl/plugin/FilterPlugin.h>
+#include <dlfcn.h>
+#include <C2Config.h>
+#include <DefaultFilterPlugin.h>
+#include <FilterWrapper.h>
+#endif
+
+namespace android {
+namespace hardware {
+namespace media {
+namespace c2 {
+namespace V1_2 {
+namespace utils {
+
+using namespace ::android;
+using ::android::GraphicBufferSource;
+using namespace ::android::hardware::media::bufferpool::V2_0::implementation;
+
+namespace /* unnamed */ {
+
+struct StoreIntf : public ConfigurableC2Intf {
+    StoreIntf(const std::shared_ptr<C2ComponentStore>& store)
+          : ConfigurableC2Intf{store ? store->getName() : "", 0},
+            mStore{store} {
+    }
+
+    virtual c2_status_t config(
+            const std::vector<C2Param*> &params,
+            c2_blocking_t mayBlock,
+            std::vector<std::unique_ptr<C2SettingResult>> *const failures
+            ) override {
+        // Assume all params are blocking
+        // TODO: Filter for supported params
+        if (mayBlock == C2_DONT_BLOCK && params.size() != 0) {
+            return C2_BLOCKING;
+        }
+        return mStore->config_sm(params, failures);
+    }
+
+    virtual c2_status_t query(
+            const std::vector<C2Param::Index> &indices,
+            c2_blocking_t mayBlock,
+            std::vector<std::unique_ptr<C2Param>> *const params) const override {
+        // Assume all params are blocking
+        // TODO: Filter for supported params
+        if (mayBlock == C2_DONT_BLOCK && indices.size() != 0) {
+            return C2_BLOCKING;
+        }
+        return mStore->query_sm({}, indices, params);
+    }
+
+    virtual c2_status_t querySupportedParams(
+            std::vector<std::shared_ptr<C2ParamDescriptor>> *const params
+            ) const override {
+        return mStore->querySupportedParams_nb(params);
+    }
+
+    virtual c2_status_t querySupportedValues(
+            std::vector<C2FieldSupportedValuesQuery> &fields,
+            c2_blocking_t mayBlock) const override {
+        // Assume all params are blocking
+        // TODO: Filter for supported params
+        if (mayBlock == C2_DONT_BLOCK && fields.size() != 0) {
+            return C2_BLOCKING;
+        }
+        return mStore->querySupportedValues_sm(fields);
+    }
+
+protected:
+    std::shared_ptr<C2ComponentStore> mStore;
+};
+
+} // unnamed namespace
+
+struct ComponentStore::StoreParameterCache : public ParameterCache {
+    std::mutex mStoreMutex;
+    ComponentStore* mStore;
+
+    StoreParameterCache(ComponentStore* store): mStore{store} {
+    }
+
+    virtual c2_status_t validate(
+            const std::vector<std::shared_ptr<C2ParamDescriptor>>& params
+            ) override {
+        std::scoped_lock _lock(mStoreMutex);
+        return mStore ? mStore->validateSupportedParams(params) : C2_NO_INIT;
+    }
+
+    void onStoreDestroyed() {
+        std::scoped_lock _lock(mStoreMutex);
+        mStore = nullptr;
+    }
+};
+
+ComponentStore::ComponentStore(const std::shared_ptr<C2ComponentStore>& store)
+      : mConfigurable{new CachedConfigurable(std::make_unique<StoreIntf>(store))},
+        mParameterCache{std::make_shared<StoreParameterCache>(this)},
+        mStore{store} {
+
+    std::shared_ptr<C2ComponentStore> platformStore = android::GetCodec2PlatformComponentStore();
+    SetPreferredCodec2ComponentStore(store);
+
+    // Retrieve struct descriptors
+    mParamReflector = mStore->getParamReflector();
+
+    // Retrieve supported parameters from store
+    using namespace std::placeholders;
+    mInit = mConfigurable->init(mParameterCache);
+}
+
+ComponentStore::~ComponentStore() {
+    mParameterCache->onStoreDestroyed();
+}
+
+c2_status_t ComponentStore::status() const {
+    return mInit;
+}
+
+c2_status_t ComponentStore::validateSupportedParams(
+        const std::vector<std::shared_ptr<C2ParamDescriptor>>& params) {
+    c2_status_t res = C2_OK;
+
+    for (const std::shared_ptr<C2ParamDescriptor> &desc : params) {
+        if (!desc) {
+            // All descriptors should be valid
+            res = res ? res : C2_BAD_VALUE;
+            continue;
+        }
+        C2Param::CoreIndex coreIndex = desc->index().coreIndex();
+        std::lock_guard<std::mutex> lock(mStructDescriptorsMutex);
+        auto it = mStructDescriptors.find(coreIndex);
+        if (it == mStructDescriptors.end()) {
+            std::shared_ptr<C2StructDescriptor> structDesc =
+                    mParamReflector->describe(coreIndex);
+            if (!structDesc) {
+                // All supported params must be described
+                res = C2_BAD_INDEX;
+            }
+            mStructDescriptors.insert({ coreIndex, structDesc });
+        }
+    }
+    return res;
+}
+
+std::shared_ptr<ParameterCache> ComponentStore::getParameterCache() const {
+    return mParameterCache;
+}
+
+#ifndef __ANDROID_APEX__
+// static
+std::shared_ptr<FilterWrapper> ComponentStore::GetFilterWrapper() {
+    constexpr const char kPluginPath[] = "libc2filterplugin.so";
+    static std::shared_ptr<FilterWrapper> wrapper = FilterWrapper::Create(
+            std::make_unique<DefaultFilterPlugin>(kPluginPath));
+    return wrapper;
+}
+#endif
+
+// Methods from ::android::hardware::media::c2::V1_0::IComponentStore
+Return<void> ComponentStore::createComponent(
+        const hidl_string& name,
+        const sp<IComponentListener>& listener,
+        const sp<IClientManager>& pool,
+        createComponent_cb _hidl_cb) {
+
+    sp<Component> component;
+    std::shared_ptr<C2Component> c2component;
+    Status status = static_cast<Status>(
+            mStore->createComponent(name, &c2component));
+
+    if (status == Status::OK) {
+#ifndef __ANDROID_APEX__
+        c2component = GetFilterWrapper()->maybeWrapComponent(c2component);
+#endif
+        onInterfaceLoaded(c2component->intf());
+        component = new Component(c2component, listener, this, pool);
+        if (!component) {
+            status = Status::CORRUPTED;
+        } else {
+            reportComponentBirth(component.get());
+            if (component->status() != C2_OK) {
+                status = static_cast<Status>(component->status());
+            } else {
+                component->initListener(component);
+                if (component->status() != C2_OK) {
+                    status = static_cast<Status>(component->status());
+                }
+            }
+        }
+    }
+    _hidl_cb(status, component);
+    return Void();
+}
+
+Return<void> ComponentStore::createInterface(
+        const hidl_string& name,
+        createInterface_cb _hidl_cb) {
+    std::shared_ptr<C2ComponentInterface> c2interface;
+    c2_status_t res = mStore->createInterface(name, &c2interface);
+    sp<IComponentInterface> interface;
+    if (res == C2_OK) {
+#ifndef __ANDROID_APEX__
+        c2interface = GetFilterWrapper()->maybeWrapInterface(c2interface);
+#endif
+        onInterfaceLoaded(c2interface);
+        interface = new ComponentInterface(c2interface, mParameterCache);
+    }
+    _hidl_cb(static_cast<Status>(res), interface);
+    return Void();
+}
+
+Return<void> ComponentStore::listComponents(listComponents_cb _hidl_cb) {
+    std::vector<std::shared_ptr<const C2Component::Traits>> c2traits =
+            mStore->listComponents();
+    hidl_vec<IComponentStore::ComponentTraits> traits(c2traits.size());
+    size_t ix = 0;
+    for (const std::shared_ptr<const C2Component::Traits> &c2trait : c2traits) {
+        if (c2trait) {
+            if (objcpy(&traits[ix], *c2trait)) {
+                ++ix;
+            } else {
+                break;
+            }
+        }
+    }
+    traits.resize(ix);
+    _hidl_cb(Status::OK, traits);
+    return Void();
+}
+
+Return<void> ComponentStore::createInputSurface(createInputSurface_cb _hidl_cb) {
+    sp<GraphicBufferSource> source = new GraphicBufferSource();
+    if (source->initCheck() != OK) {
+        _hidl_cb(Status::CORRUPTED, nullptr);
+        return Void();
+    }
+    using namespace std::placeholders;
+    sp<InputSurface> inputSurface = new InputSurface(
+            mParameterCache,
+            std::make_shared<C2ReflectorHelper>(),
+            source->getHGraphicBufferProducer(),
+            source);
+    _hidl_cb(inputSurface ? Status::OK : Status::NO_MEMORY,
+             inputSurface);
+    return Void();
+}
+
+void ComponentStore::onInterfaceLoaded(const std::shared_ptr<C2ComponentInterface> &intf) {
+    // invalidate unsupported struct descriptors if a new interface is loaded as it may have
+    // exposed new descriptors
+    std::lock_guard<std::mutex> lock(mStructDescriptorsMutex);
+    if (!mLoadedInterfaces.count(intf->getName())) {
+        mUnsupportedStructDescriptors.clear();
+        mLoadedInterfaces.emplace(intf->getName());
+    }
+}
+
+Return<void> ComponentStore::getStructDescriptors(
+        const hidl_vec<uint32_t>& indices,
+        getStructDescriptors_cb _hidl_cb) {
+    hidl_vec<StructDescriptor> descriptors(indices.size());
+    size_t dstIx = 0;
+    Status res = Status::OK;
+    for (size_t srcIx = 0; srcIx < indices.size(); ++srcIx) {
+        std::lock_guard<std::mutex> lock(mStructDescriptorsMutex);
+        const C2Param::CoreIndex coreIndex = C2Param::CoreIndex(indices[srcIx]).coreIndex();
+        const auto item = mStructDescriptors.find(coreIndex);
+        if (item == mStructDescriptors.end()) {
+            // not in the cache, and not known to be unsupported, query local reflector
+            if (!mUnsupportedStructDescriptors.count(coreIndex)) {
+                std::shared_ptr<C2StructDescriptor> structDesc =
+                    mParamReflector->describe(coreIndex);
+                if (!structDesc) {
+                    mUnsupportedStructDescriptors.emplace(coreIndex);
+                } else {
+                    mStructDescriptors.insert({ coreIndex, structDesc });
+                    if (objcpy(&descriptors[dstIx], *structDesc)) {
+                        ++dstIx;
+                        continue;
+                    }
+                    res = Status::CORRUPTED;
+                    break;
+                }
+            }
+            res = Status::NOT_FOUND;
+        } else if (item->second) {
+            if (objcpy(&descriptors[dstIx], *item->second)) {
+                ++dstIx;
+                continue;
+            }
+            res = Status::CORRUPTED;
+            break;
+        } else {
+            res = Status::NO_MEMORY;
+            break;
+        }
+    }
+    descriptors.resize(dstIx);
+    _hidl_cb(res, descriptors);
+    return Void();
+}
+
+Return<sp<IClientManager>> ComponentStore::getPoolClientManager() {
+    return ClientManager::getInstance();
+}
+
+Return<Status> ComponentStore::copyBuffer(const Buffer& src, const Buffer& dst) {
+    // TODO implement
+    (void)src;
+    (void)dst;
+    return Status::OMITTED;
+}
+
+Return<sp<IConfigurable>> ComponentStore::getConfigurable() {
+    return mConfigurable;
+}
+
+// Methods from ::android::hardware::media::c2::V1_1::IComponentStore
+Return<void> ComponentStore::createComponent_1_1(
+        const hidl_string& name,
+        const sp<IComponentListener>& listener,
+        const sp<IClientManager>& pool,
+        createComponent_1_1_cb _hidl_cb) {
+
+    sp<Component> component;
+    std::shared_ptr<C2Component> c2component;
+    Status status = static_cast<Status>(
+            mStore->createComponent(name, &c2component));
+
+    if (status == Status::OK) {
+#ifndef __ANDROID_APEX__
+        c2component = GetFilterWrapper()->maybeWrapComponent(c2component);
+#endif
+        onInterfaceLoaded(c2component->intf());
+        component = new Component(c2component, listener, this, pool);
+        if (!component) {
+            status = Status::CORRUPTED;
+        } else {
+            reportComponentBirth(component.get());
+            if (component->status() != C2_OK) {
+                status = static_cast<Status>(component->status());
+            } else {
+                component->initListener(component);
+                if (component->status() != C2_OK) {
+                    status = static_cast<Status>(component->status());
+                }
+            }
+        }
+    }
+    _hidl_cb(status, component);
+    return Void();
+}
+
+// Methods from ::android::hardware::media::c2::V1_2::IComponentStore
+Return<void> ComponentStore::createComponent_1_2(
+        const hidl_string& name,
+        const sp<IComponentListener>& listener,
+        const sp<IClientManager>& pool,
+        createComponent_1_2_cb _hidl_cb) {
+
+    sp<Component> component;
+    std::shared_ptr<C2Component> c2component;
+    Status status = static_cast<Status>(
+            mStore->createComponent(name, &c2component));
+
+    if (status == Status::OK) {
+#ifndef __ANDROID_APEX__
+        c2component = GetFilterWrapper()->maybeWrapComponent(c2component);
+#endif
+        onInterfaceLoaded(c2component->intf());
+        component = new Component(c2component, listener, this, pool);
+        if (!component) {
+            status = Status::CORRUPTED;
+        } else {
+            reportComponentBirth(component.get());
+            if (component->status() != C2_OK) {
+                status = static_cast<Status>(component->status());
+            } else {
+                component->initListener(component);
+                if (component->status() != C2_OK) {
+                    status = static_cast<Status>(component->status());
+                }
+            }
+        }
+    }
+    _hidl_cb(status, component);
+    return Void();
+}
+
+// Called from createComponent() after a successful creation of `component`.
+void ComponentStore::reportComponentBirth(Component* component) {
+    ComponentStatus componentStatus;
+    componentStatus.c2Component = component->mComponent;
+    componentStatus.birthTime = std::chrono::system_clock::now();
+
+    std::lock_guard<std::mutex> lock(mComponentRosterMutex);
+    mComponentRoster.emplace(component, componentStatus);
+}
+
+// Called from within the destructor of `component`. No virtual function calls
+// are made on `component` here.
+void ComponentStore::reportComponentDeath(Component* component) {
+    std::lock_guard<std::mutex> lock(mComponentRosterMutex);
+    mComponentRoster.erase(component);
+}
+
+// Dumps component traits.
+std::ostream& ComponentStore::dump(
+        std::ostream& out,
+        const std::shared_ptr<const C2Component::Traits>& comp) {
+
+    constexpr const char indent[] = "    ";
+
+    out << indent << "name: " << comp->name << std::endl;
+    out << indent << "domain: " << comp->domain << std::endl;
+    out << indent << "kind: " << comp->kind << std::endl;
+    out << indent << "rank: " << comp->rank << std::endl;
+    out << indent << "mediaType: " << comp->mediaType << std::endl;
+    out << indent << "aliases:";
+    for (const auto& alias : comp->aliases) {
+        out << ' ' << alias;
+    }
+    out << std::endl;
+
+    return out;
+}
+
+// Dumps component status.
+std::ostream& ComponentStore::dump(
+        std::ostream& out,
+        ComponentStatus& compStatus) {
+
+    constexpr const char indent[] = "    ";
+
+    // Print birth time.
+    std::chrono::milliseconds ms =
+            std::chrono::duration_cast<std::chrono::milliseconds>(
+                compStatus.birthTime.time_since_epoch());
+    std::time_t birthTime = std::chrono::system_clock::to_time_t(
+            compStatus.birthTime);
+    std::tm tm = *std::localtime(&birthTime);
+    out << indent << "Creation time: "
+        << std::put_time(&tm, "%Y-%m-%d %H:%M:%S")
+        << '.' << std::setfill('0') << std::setw(3) << ms.count() % 1000
+        << std::endl;
+
+    // Print name and id.
+    std::shared_ptr<C2ComponentInterface> intf = compStatus.c2Component->intf();
+    if (!intf) {
+        out << indent << "Unknown component -- null interface" << std::endl;
+        return out;
+    }
+    out << indent << "Name: " << intf->getName() << std::endl;
+    out << indent << "Id: " << intf->getId() << std::endl;
+
+    return out;
+}
+
+// Dumps information when lshal is called.
+Return<void> ComponentStore::debug(
+        const hidl_handle& handle,
+        const hidl_vec<hidl_string>& /* args */) {
+    LOG(INFO) << "debug -- dumping...";
+    const native_handle_t *h = handle.getNativeHandle();
+    if (!h || h->numFds != 1) {
+       LOG(ERROR) << "debug -- dumping failed -- "
+               "invalid file descriptor to dump to";
+       return Void();
+    }
+    std::ostringstream out;
+
+    { // Populate "out".
+
+        constexpr const char indent[] = "  ";
+
+        // Show name.
+        out << "Beginning of dump -- C2ComponentStore: "
+                << mStore->getName() << std::endl << std::endl;
+
+        // Retrieve the list of supported components.
+        std::vector<std::shared_ptr<const C2Component::Traits>> traitsList =
+                mStore->listComponents();
+
+        // Dump the traits of supported components.
+        out << indent << "Supported components:" << std::endl << std::endl;
+        if (traitsList.size() == 0) {
+            out << indent << indent << "NONE" << std::endl << std::endl;
+        } else {
+            for (const auto& traits : traitsList) {
+                dump(out, traits) << std::endl;
+            }
+        }
+
+        // Dump active components.
+        {
+            out << indent << "Active components:" << std::endl << std::endl;
+            std::lock_guard<std::mutex> lock(mComponentRosterMutex);
+            if (mComponentRoster.size() == 0) {
+                out << indent << indent << "NONE" << std::endl << std::endl;
+            } else {
+                for (auto& pair : mComponentRoster) {
+                    dump(out, pair.second) << std::endl;
+                }
+            }
+        }
+
+        out << "End of dump -- C2ComponentStore: "
+                << mStore->getName() << std::endl;
+    }
+
+    if (!android::base::WriteStringToFd(out.str(), h->data[0])) {
+        PLOG(WARNING) << "debug -- dumping failed -- write()";
+    } else {
+        LOG(INFO) << "debug -- dumping succeeded";
+    }
+    return Void();
+}
+
+} // namespace utils
+} // namespace V1_2
+} // namespace c2
+} // namespace media
+} // namespace hardware
+} // namespace android
diff --git a/media/codec2/hal/aidl/Configurable.cpp b/media/codec2/hal/aidl/Configurable.cpp
new file mode 100644
index 0000000..530576d
--- /dev/null
+++ b/media/codec2/hal/aidl/Configurable.cpp
@@ -0,0 +1,196 @@
+/*
+ * 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-Configurable"
+#include <android-base/logging.h>
+
+#include <codec2/hidl/1.0/Configurable.h>
+#include <codec2/hidl/1.0/ComponentStore.h>
+#include <codec2/hidl/1.0/types.h>
+
+#include <C2ParamInternal.h>
+
+namespace android {
+namespace hardware {
+namespace media {
+namespace c2 {
+namespace V1_0 {
+namespace utils {
+
+using namespace ::android;
+
+CachedConfigurable::CachedConfigurable(
+        std::unique_ptr<ConfigurableC2Intf>&& intf)
+      : mIntf{std::move(intf)} {
+}
+
+c2_status_t CachedConfigurable::init(
+        const std::shared_ptr<ParameterCache>& cache) {
+    // Retrieve supported parameters from store
+    c2_status_t init = mIntf->querySupportedParams(&mSupportedParams);
+    c2_status_t validate = cache->validate(mSupportedParams);
+    return init == C2_OK ? C2_OK : validate;
+}
+
+// Methods from ::android::hardware::media::c2::V1_0::IConfigurable follow.
+Return<uint32_t> CachedConfigurable::getId() {
+    return mIntf->getId();
+}
+
+Return<void> CachedConfigurable::getName(getName_cb _hidl_cb) {
+    _hidl_cb(mIntf->getName());
+    return Void();
+}
+
+Return<void> CachedConfigurable::query(
+        const hidl_vec<uint32_t>& indices,
+        bool mayBlock,
+        query_cb _hidl_cb) {
+    typedef C2Param::Index Index;
+    std::vector<Index> c2heapParamIndices(
+            (Index*)indices.data(),
+            (Index*)indices.data() + indices.size());
+    std::vector<std::unique_ptr<C2Param>> c2heapParams;
+    c2_status_t c2res = mIntf->query(
+            c2heapParamIndices,
+            mayBlock ? C2_MAY_BLOCK : C2_DONT_BLOCK,
+            &c2heapParams);
+
+    hidl_vec<uint8_t> params;
+    if (!createParamsBlob(&params, c2heapParams)) {
+        LOG(WARNING) << "query -- invalid output params.";
+    }
+    _hidl_cb(static_cast<Status>(c2res), params);
+    return Void();
+}
+
+Return<void> CachedConfigurable::config(
+        const hidl_vec<uint8_t>& inParams,
+        bool mayBlock,
+        config_cb _hidl_cb) {
+    // inParams is not writable, so create a copy as config modifies the parameters
+    hidl_vec<uint8_t> inParamsCopy = inParams;
+    std::vector<C2Param*> c2params;
+    if (!parseParamsBlob(&c2params, inParamsCopy)) {
+        LOG(WARNING) << "config -- invalid input params.";
+        _hidl_cb(Status::CORRUPTED,
+                hidl_vec<SettingResult>(),
+                hidl_vec<uint8_t>());
+        return Void();
+    }
+    // TODO: check if blob was invalid
+    std::vector<std::unique_ptr<C2SettingResult>> c2failures;
+    c2_status_t c2res = mIntf->config(
+            c2params,
+            mayBlock ? C2_MAY_BLOCK : C2_DONT_BLOCK,
+            &c2failures);
+    hidl_vec<SettingResult> failures(c2failures.size());
+    {
+        size_t ix = 0;
+        for (const std::unique_ptr<C2SettingResult>& c2result : c2failures) {
+            if (c2result) {
+                if (objcpy(&failures[ix], *c2result)) {
+                    ++ix;
+                } else {
+                    LOG(DEBUG) << "config -- invalid setting results.";
+                    break;
+                }
+            }
+        }
+        failures.resize(ix);
+    }
+    hidl_vec<uint8_t> outParams;
+    if (!createParamsBlob(&outParams, c2params)) {
+        LOG(DEBUG) << "config -- invalid output params.";
+    }
+    _hidl_cb((Status)c2res, failures, outParams);
+    return Void();
+}
+
+Return<void> CachedConfigurable::querySupportedParams(
+        uint32_t start,
+        uint32_t count,
+        querySupportedParams_cb _hidl_cb) {
+    C2LinearRange request = C2LinearCapacity(mSupportedParams.size()).range(
+            start, count);
+    hidl_vec<ParamDescriptor> params(request.size());
+    Status res = Status::OK;
+    size_t dstIx = 0;
+    for (size_t srcIx = request.offset(); srcIx < request.endOffset(); ++srcIx) {
+        if (mSupportedParams[srcIx]) {
+            if (objcpy(&params[dstIx], *mSupportedParams[srcIx])) {
+                ++dstIx;
+            } else {
+                res = Status::CORRUPTED;
+                LOG(WARNING) << "querySupportedParams -- invalid output params.";
+                break;
+            }
+        } else {
+            res = Status::BAD_INDEX;
+        }
+    }
+    params.resize(dstIx);
+    _hidl_cb(res, params);
+    return Void();
+}
+
+Return<void> CachedConfigurable::querySupportedValues(
+        const hidl_vec<FieldSupportedValuesQuery>& inFields,
+        bool mayBlock,
+        querySupportedValues_cb _hidl_cb) {
+    std::vector<C2FieldSupportedValuesQuery> c2fields;
+    {
+        // C2FieldSupportedValuesQuery objects are restricted in that some
+        // members are const.
+        // C2ParamField - required for its constructor - has no constructors
+        // from fields. Use C2ParamInspector.
+        for (const FieldSupportedValuesQuery &query : inFields) {
+            c2fields.emplace_back(_C2ParamInspector::CreateParamField(
+                    query.field.index,
+                    query.field.fieldId.offset,
+                    query.field.fieldId.size),
+                    query.type == FieldSupportedValuesQuery::Type::POSSIBLE ?
+                    C2FieldSupportedValuesQuery::POSSIBLE :
+                    C2FieldSupportedValuesQuery::CURRENT);
+        }
+    }
+    c2_status_t c2res = mIntf->querySupportedValues(
+            c2fields,
+            mayBlock ? C2_MAY_BLOCK : C2_DONT_BLOCK);
+    hidl_vec<FieldSupportedValuesQueryResult> outFields(inFields.size());
+    size_t dstIx = 0;
+    for (const C2FieldSupportedValuesQuery &result : c2fields) {
+        if (objcpy(&outFields[dstIx], result)) {
+            ++dstIx;
+        } else {
+            outFields.resize(dstIx);
+            c2res = C2_CORRUPTED;
+            LOG(WARNING) << "querySupportedValues -- invalid output params.";
+            break;
+        }
+    }
+    _hidl_cb((Status)c2res, outFields);
+    return Void();
+}
+
+}  // namespace utils
+}  // namespace V1_0
+}  // namespace c2
+}  // namespace media
+}  // namespace hardware
+}  // namespace android
+
diff --git a/media/codec2/hal/aidl/InputBufferManager.cpp b/media/codec2/hal/aidl/InputBufferManager.cpp
new file mode 100644
index 0000000..8c0d0a4
--- /dev/null
+++ b/media/codec2/hal/aidl/InputBufferManager.cpp
@@ -0,0 +1,476 @@
+/*
+ * 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-InputBufferManager"
+#include <android-base/logging.h>
+
+#include <codec2/hidl/1.0/InputBufferManager.h>
+#include <codec2/hidl/1.0/types.h>
+
+#include <android/hardware/media/c2/1.0/IComponentListener.h>
+#include <android-base/logging.h>
+
+#include <C2Buffer.h>
+#include <C2Work.h>
+
+#include <chrono>
+
+namespace android {
+namespace hardware {
+namespace media {
+namespace c2 {
+namespace V1_0 {
+namespace utils {
+
+using namespace ::android;
+
+void InputBufferManager::registerFrameData(
+        const sp<IComponentListener>& listener,
+        const C2FrameData& input) {
+    getInstance()._registerFrameData(listener, input);
+}
+
+void InputBufferManager::unregisterFrameData(
+        const wp<IComponentListener>& listener,
+        const C2FrameData& input) {
+    getInstance()._unregisterFrameData(listener, input);
+}
+
+void InputBufferManager::unregisterFrameData(
+        const wp<IComponentListener>& listener) {
+    getInstance()._unregisterFrameData(listener);
+}
+
+void InputBufferManager::setNotificationInterval(
+        nsecs_t notificationIntervalNs) {
+    getInstance()._setNotificationInterval(notificationIntervalNs);
+}
+
+void InputBufferManager::_registerFrameData(
+        const sp<IComponentListener>& listener,
+        const C2FrameData& input) {
+    uint64_t frameIndex = input.ordinal.frameIndex.peeku();
+    LOG(VERBOSE) << "InputBufferManager::_registerFrameData -- called with "
+                 << "listener @ 0x" << std::hex << listener.get()
+                 << ", frameIndex = " << std::dec << frameIndex
+                 << ".";
+    std::lock_guard<std::mutex> lock(mMutex);
+
+    std::set<TrackedBuffer*> &bufferIds =
+            mTrackedBuffersMap[listener][frameIndex];
+
+    for (size_t i = 0; i < input.buffers.size(); ++i) {
+        if (!input.buffers[i]) {
+            LOG(VERBOSE) << "InputBufferManager::_registerFrameData -- "
+                         << "Input buffer at index " << i << " is null.";
+            continue;
+        }
+        TrackedBuffer *bufferId =
+            new TrackedBuffer(listener, frameIndex, i, input.buffers[i]);
+        mTrackedBufferCache.emplace(bufferId);
+        bufferIds.emplace(bufferId);
+
+        c2_status_t status = input.buffers[i]->registerOnDestroyNotify(
+                onBufferDestroyed,
+                reinterpret_cast<void*>(bufferId));
+        if (status != C2_OK) {
+            LOG(DEBUG) << "InputBufferManager::_registerFrameData -- "
+                       << "registerOnDestroyNotify() failed "
+                       << "(listener @ 0x" << std::hex << listener.get()
+                       << ", frameIndex = " << std::dec << frameIndex
+                       << ", bufferIndex = " << i
+                       << ") => status = " << status
+                       << ".";
+        }
+    }
+
+    mDeathNotifications.emplace(
+            listener,
+            DeathNotifications(
+                mNotificationIntervalNs.load(std::memory_order_relaxed)));
+}
+
+// Remove a pair (listener, frameIndex) from mTrackedBuffersMap and
+// mDeathNotifications. This implies all bufferIndices are removed.
+//
+// This is called from onWorkDone() and flush().
+void InputBufferManager::_unregisterFrameData(
+        const wp<IComponentListener>& listener,
+        const C2FrameData& input) {
+    uint64_t frameIndex = input.ordinal.frameIndex.peeku();
+    LOG(VERBOSE) << "InputBufferManager::_unregisterFrameData -- called with "
+                 << "listener @ 0x" << std::hex << listener.unsafe_get()
+                 << ", frameIndex = " << std::dec << frameIndex
+                 << ".";
+    std::lock_guard<std::mutex> lock(mMutex);
+
+    auto findListener = mTrackedBuffersMap.find(listener);
+    if (findListener != mTrackedBuffersMap.end()) {
+        std::map<uint64_t, std::set<TrackedBuffer*>> &frameIndex2BufferIds
+                = findListener->second;
+        auto findFrameIndex = frameIndex2BufferIds.find(frameIndex);
+        if (findFrameIndex != frameIndex2BufferIds.end()) {
+            std::set<TrackedBuffer*> &bufferIds = findFrameIndex->second;
+            for (TrackedBuffer* bufferId : bufferIds) {
+                std::shared_ptr<C2Buffer> buffer = bufferId->buffer.lock();
+                if (buffer) {
+                    c2_status_t status = buffer->unregisterOnDestroyNotify(
+                            onBufferDestroyed,
+                            reinterpret_cast<void*>(bufferId));
+                    if (status != C2_OK) {
+                        LOG(DEBUG) << "InputBufferManager::_unregisterFrameData "
+                                   << "-- unregisterOnDestroyNotify() failed "
+                                   << "(listener @ 0x"
+                                        << std::hex
+                                        << bufferId->listener.unsafe_get()
+                                   << ", frameIndex = "
+                                        << std::dec << bufferId->frameIndex
+                                   << ", bufferIndex = " << bufferId->bufferIndex
+                                   << ") => status = " << status
+                                   << ".";
+                    }
+                }
+                mTrackedBufferCache.erase(bufferId);
+                delete bufferId;
+            }
+
+            frameIndex2BufferIds.erase(findFrameIndex);
+            if (frameIndex2BufferIds.empty()) {
+                mTrackedBuffersMap.erase(findListener);
+            }
+        }
+    }
+
+    auto findListenerD = mDeathNotifications.find(listener);
+    if (findListenerD != mDeathNotifications.end()) {
+        DeathNotifications &deathNotifications = findListenerD->second;
+        auto findFrameIndex = deathNotifications.indices.find(frameIndex);
+        if (findFrameIndex != deathNotifications.indices.end()) {
+            std::vector<size_t> &bufferIndices = findFrameIndex->second;
+            deathNotifications.count -= bufferIndices.size();
+            deathNotifications.indices.erase(findFrameIndex);
+        }
+    }
+}
+
+// Remove listener from mTrackedBuffersMap and mDeathNotifications. This implies
+// all frameIndices and bufferIndices are removed.
+//
+// This is called when the component cleans up all input buffers, i.e., when
+// reset(), release(), stop() or ~Component() is called.
+void InputBufferManager::_unregisterFrameData(
+        const wp<IComponentListener>& listener) {
+    LOG(VERBOSE) << "InputBufferManager::_unregisterFrameData -- called with "
+                 << "listener @ 0x" << std::hex << listener.unsafe_get()
+                 << std::dec << ".";
+    std::lock_guard<std::mutex> lock(mMutex);
+
+    auto findListener = mTrackedBuffersMap.find(listener);
+    if (findListener != mTrackedBuffersMap.end()) {
+        std::map<uint64_t, std::set<TrackedBuffer*>> &frameIndex2BufferIds =
+                findListener->second;
+        for (auto findFrameIndex = frameIndex2BufferIds.begin();
+                findFrameIndex != frameIndex2BufferIds.end();
+                ++findFrameIndex) {
+            std::set<TrackedBuffer*> &bufferIds = findFrameIndex->second;
+            for (TrackedBuffer* bufferId : bufferIds) {
+                std::shared_ptr<C2Buffer> buffer = bufferId->buffer.lock();
+                if (buffer) {
+                    c2_status_t status = buffer->unregisterOnDestroyNotify(
+                            onBufferDestroyed,
+                            reinterpret_cast<void*>(bufferId));
+                    if (status != C2_OK) {
+                        LOG(DEBUG) << "InputBufferManager::_unregisterFrameData "
+                                   << "-- unregisterOnDestroyNotify() failed "
+                                   << "(listener @ 0x"
+                                        << std::hex
+                                        << bufferId->listener.unsafe_get()
+                                   << ", frameIndex = "
+                                        << std::dec << bufferId->frameIndex
+                                   << ", bufferIndex = " << bufferId->bufferIndex
+                                   << ") => status = " << status
+                                   << ".";
+                    }
+                    mTrackedBufferCache.erase(bufferId);
+                    delete bufferId;
+                }
+            }
+        }
+        mTrackedBuffersMap.erase(findListener);
+    }
+
+    mDeathNotifications.erase(listener);
+}
+
+// Set mNotificationIntervalNs.
+void InputBufferManager::_setNotificationInterval(
+        nsecs_t notificationIntervalNs) {
+    mNotificationIntervalNs.store(
+            notificationIntervalNs,
+            std::memory_order_relaxed);
+}
+
+// Move a buffer from mTrackedBuffersMap to mDeathNotifications.
+// This is called when a registered C2Buffer object is destroyed.
+void InputBufferManager::onBufferDestroyed(const C2Buffer* buf, void* arg) {
+    getInstance()._onBufferDestroyed(buf, arg);
+}
+
+void InputBufferManager::_onBufferDestroyed(const C2Buffer* buf, void* arg) {
+    if (!buf || !arg) {
+        LOG(WARNING) << "InputBufferManager::_onBufferDestroyed -- called with "
+                     << "null argument (s): "
+                     << "buf @ 0x" << std::hex << buf
+                     << ", arg @ 0x" << std::hex << arg
+                     << std::dec << ".";
+        return;
+    }
+
+    std::lock_guard<std::mutex> lock(mMutex);
+    TrackedBuffer *bufferId = reinterpret_cast<TrackedBuffer*>(arg);
+
+    if (mTrackedBufferCache.find(bufferId) == mTrackedBufferCache.end()) {
+        LOG(VERBOSE) << "InputBufferManager::_onBufferDestroyed -- called with "
+                     << "unregistered buffer: "
+                     << "buf @ 0x" << std::hex << buf
+                     << ", arg @ 0x" << std::hex << arg
+                     << std::dec << ".";
+        return;
+    }
+
+    LOG(VERBOSE) << "InputBufferManager::_onBufferDestroyed -- called with "
+                 << "buf @ 0x" << std::hex << buf
+                 << ", arg @ 0x" << std::hex << arg
+                 << std::dec << " -- "
+                 << "listener @ 0x" << std::hex << bufferId->listener.unsafe_get()
+                 << ", frameIndex = " << std::dec << bufferId->frameIndex
+                 << ", bufferIndex = " << bufferId->bufferIndex
+                 << ".";
+    auto findListener = mTrackedBuffersMap.find(bufferId->listener);
+    if (findListener == mTrackedBuffersMap.end()) {
+        LOG(VERBOSE) << "InputBufferManager::_onBufferDestroyed -- "
+                     << "received invalid listener: "
+                     << "listener @ 0x" << std::hex << bufferId->listener.unsafe_get()
+                     << " (frameIndex = " << std::dec << bufferId->frameIndex
+                     << ", bufferIndex = " << bufferId->bufferIndex
+                     << ").";
+        return;
+    }
+
+    std::map<uint64_t, std::set<TrackedBuffer*>> &frameIndex2BufferIds
+            = findListener->second;
+    auto findFrameIndex = frameIndex2BufferIds.find(bufferId->frameIndex);
+    if (findFrameIndex == frameIndex2BufferIds.end()) {
+        LOG(DEBUG) << "InputBufferManager::_onBufferDestroyed -- "
+                   << "received invalid frame index: "
+                   << "frameIndex = " << bufferId->frameIndex
+                   << " (listener @ 0x" << std::hex << bufferId->listener.unsafe_get()
+                   << ", bufferIndex = " << std::dec << bufferId->bufferIndex
+                   << ").";
+        return;
+    }
+
+    std::set<TrackedBuffer*> &bufferIds = findFrameIndex->second;
+    auto findBufferId = bufferIds.find(bufferId);
+    if (findBufferId == bufferIds.end()) {
+        LOG(DEBUG) << "InputBufferManager::_onBufferDestroyed -- "
+                   << "received invalid buffer index: "
+                   << "bufferIndex = " << bufferId->bufferIndex
+                   << " (frameIndex = " << bufferId->frameIndex
+                   << ", listener @ 0x" << std::hex << bufferId->listener.unsafe_get()
+                   << std::dec << ").";
+        return;
+    }
+
+    bufferIds.erase(findBufferId);
+    if (bufferIds.empty()) {
+        frameIndex2BufferIds.erase(findFrameIndex);
+        if (frameIndex2BufferIds.empty()) {
+            mTrackedBuffersMap.erase(findListener);
+        }
+    }
+
+    DeathNotifications &deathNotifications = mDeathNotifications[bufferId->listener];
+    deathNotifications.indices[bufferId->frameIndex].emplace_back(bufferId->bufferIndex);
+    ++deathNotifications.count;
+    mOnBufferDestroyed.notify_one();
+
+    mTrackedBufferCache.erase(bufferId);
+    delete bufferId;
+}
+
+// Notify the clients about buffer destructions.
+// Return false if all destructions have been notified.
+// Return true and set timeToRetry to the time point to wait for before
+// retrying if some destructions have not been notified.
+bool InputBufferManager::processNotifications(nsecs_t* timeToRetryNs) {
+
+    struct Notification {
+        sp<IComponentListener> listener;
+        hidl_vec<IComponentListener::InputBuffer> inputBuffers;
+        Notification(const sp<IComponentListener>& l, size_t s)
+              : listener(l), inputBuffers(s) {}
+    };
+    std::list<Notification> notifications;
+    nsecs_t notificationIntervalNs =
+            mNotificationIntervalNs.load(std::memory_order_relaxed);
+
+    bool retry = false;
+    {
+        std::lock_guard<std::mutex> lock(mMutex);
+        *timeToRetryNs = notificationIntervalNs;
+        nsecs_t timeNowNs = systemTime();
+        for (auto it = mDeathNotifications.begin();
+                it != mDeathNotifications.end(); ) {
+            sp<IComponentListener> listener = it->first.promote();
+            if (!listener) {
+                ++it;
+                continue;
+            }
+            DeathNotifications &deathNotifications = it->second;
+
+            nsecs_t timeSinceLastNotifiedNs =
+                    timeNowNs - deathNotifications.lastSentNs;
+            // If not enough time has passed since the last callback, leave the
+            // notifications for this listener untouched for now and retry
+            // later.
+            if (timeSinceLastNotifiedNs < notificationIntervalNs) {
+                retry = true;
+                *timeToRetryNs = std::min(*timeToRetryNs,
+                        notificationIntervalNs - timeSinceLastNotifiedNs);
+                LOG(VERBOSE) << "InputBufferManager::processNotifications -- "
+                             << "Notifications for listener @ "
+                                 << std::hex << listener.get()
+                             << " will be postponed.";
+                ++it;
+                continue;
+            }
+
+            // If enough time has passed since the last notification to this
+            // listener but there are currently no pending notifications, the
+            // listener can be removed from mDeathNotifications---there is no
+            // need to keep track of the last notification time anymore.
+            if (deathNotifications.count == 0) {
+                it = mDeathNotifications.erase(it);
+                continue;
+            }
+
+            // Create the argument for the callback.
+            notifications.emplace_back(listener, deathNotifications.count);
+            hidl_vec<IComponentListener::InputBuffer> &inputBuffers =
+                    notifications.back().inputBuffers;
+            size_t i = 0;
+            for (std::pair<const uint64_t, std::vector<size_t>>& p :
+                    deathNotifications.indices) {
+                uint64_t frameIndex = p.first;
+                const std::vector<size_t> &bufferIndices = p.second;
+                for (const size_t& bufferIndex : bufferIndices) {
+                    IComponentListener::InputBuffer &inputBuffer
+                            = inputBuffers[i++];
+                    inputBuffer.arrayIndex = bufferIndex;
+                    inputBuffer.frameIndex = frameIndex;
+                }
+            }
+
+            // Clear deathNotifications for this listener and set retry to true
+            // so processNotifications will be called again. This will
+            // guarantee that a listener with no pending notifications will
+            // eventually be removed from mDeathNotifications after
+            // mNotificationIntervalNs nanoseconds has passed.
+            retry = true;
+            deathNotifications.indices.clear();
+            deathNotifications.count = 0;
+            deathNotifications.lastSentNs = timeNowNs;
+            ++it;
+        }
+    }
+
+    // Call onInputBuffersReleased() outside the lock to avoid deadlock.
+    for (const Notification& notification : notifications) {
+        if (!notification.listener->onInputBuffersReleased(
+                notification.inputBuffers).isOk()) {
+            // This may trigger if the client has died.
+            LOG(DEBUG) << "InputBufferManager::processNotifications -- "
+                       << "failed to send death notifications to "
+                       << "listener @ 0x" << std::hex
+                                          << notification.listener.get()
+                       << std::dec << ".";
+        } else {
+#if LOG_NDEBUG == 0
+            std::stringstream inputBufferLog;
+            for (const IComponentListener::InputBuffer& inputBuffer :
+                    notification.inputBuffers) {
+                inputBufferLog << " (" << inputBuffer.frameIndex
+                               << ", " << inputBuffer.arrayIndex
+                               << ")";
+            }
+            LOG(VERBOSE) << "InputBufferManager::processNotifications -- "
+                         << "death notifications sent to "
+                         << "listener @ 0x" << std::hex
+                                            << notification.listener.get()
+                                            << std::dec
+                         << " with these (frameIndex, bufferIndex) pairs:"
+                         << inputBufferLog.str();
+#endif
+        }
+    }
+#if LOG_NDEBUG == 0
+    if (retry) {
+        LOG(VERBOSE) << "InputBufferManager::processNotifications -- "
+                     << "will retry again in " << *timeToRetryNs << "ns.";
+    } else {
+        LOG(VERBOSE) << "InputBufferManager::processNotifications -- "
+                     << "no pending death notifications.";
+    }
+#endif
+    return retry;
+}
+
+void InputBufferManager::main() {
+    LOG(VERBOSE) << "InputBufferManager main -- started.";
+    nsecs_t timeToRetryNs;
+    while (true) {
+        std::unique_lock<std::mutex> lock(mMutex);
+        while (mDeathNotifications.empty()) {
+            mOnBufferDestroyed.wait(lock);
+        }
+        lock.unlock();
+        while (processNotifications(&timeToRetryNs)) {
+            std::this_thread::sleep_for(
+                    std::chrono::nanoseconds(timeToRetryNs));
+        }
+    }
+}
+
+InputBufferManager::InputBufferManager()
+      : mMainThread{&InputBufferManager::main, this} {
+}
+
+InputBufferManager& InputBufferManager::getInstance() {
+    static InputBufferManager instance{};
+    return instance;
+}
+
+}  // namespace utils
+}  // namespace V1_0
+}  // namespace c2
+}  // namespace media
+}  // namespace hardware
+}  // namespace android
+
+
+
diff --git a/media/codec2/hal/aidl/InputSurface.cpp b/media/codec2/hal/aidl/InputSurface.cpp
new file mode 100644
index 0000000..c3c32e9
--- /dev/null
+++ b/media/codec2/hal/aidl/InputSurface.cpp
@@ -0,0 +1,177 @@
+/*
+ * 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-InputSurface"
+#include <android-base/logging.h>
+
+#include <codec2/hidl/1.0/InputSurface.h>
+#include <codec2/hidl/1.0/InputSurfaceConnection.h>
+
+#include <C2Component.h>
+#include <C2Config.h>
+
+#include <memory>
+
+namespace android {
+namespace hardware {
+namespace media {
+namespace c2 {
+namespace V1_0 {
+namespace utils {
+
+using namespace ::android;
+
+// Derived class of C2InterfaceHelper
+class InputSurface::Interface : public C2InterfaceHelper {
+public:
+    explicit Interface(
+            const std::shared_ptr<C2ReflectorHelper> &helper)
+        : C2InterfaceHelper(helper) {
+
+        setDerivedInstance(this);
+
+        addParameter(
+                DefineParam(mEos, C2_PARAMKEY_INPUT_SURFACE_EOS)
+                .withDefault(new C2InputSurfaceEosTuning(false))
+                .withFields({C2F(mEos, value).oneOf({true, false})})
+                .withSetter(EosSetter)
+                .build());
+    }
+
+    static C2R EosSetter(bool mayBlock, C2P<C2InputSurfaceEosTuning> &me) {
+        (void)mayBlock;
+        return me.F(me.v.value).validatePossible(me.v.value);
+    }
+
+    bool eos() const { return mEos->value; }
+
+private:
+    std::shared_ptr<C2InputSurfaceEosTuning> mEos;
+};
+
+// Derived class of ConfigurableC2Intf
+class InputSurface::ConfigurableIntf : public ConfigurableC2Intf {
+public:
+    ConfigurableIntf(
+            const std::shared_ptr<InputSurface::Interface> &intf,
+            const sp<GraphicBufferSource> &source)
+        : ConfigurableC2Intf("input-surface", 0),
+          mIntf(intf),
+          mSource(source) {
+    }
+
+    virtual ~ConfigurableIntf() override = default;
+
+    virtual c2_status_t query(
+            const std::vector<C2Param::Index> &indices,
+            c2_blocking_t mayBlock,
+            std::vector<std::unique_ptr<C2Param>>* const params
+            ) const override {
+        return mIntf->query({}, indices, mayBlock, params);
+    }
+
+    virtual c2_status_t config(
+            const std::vector<C2Param*> &params,
+            c2_blocking_t mayBlock,
+            std::vector<std::unique_ptr<C2SettingResult>>* const failures
+            ) override {
+        c2_status_t err = mIntf->config(params, mayBlock, failures);
+        if (mIntf->eos()) {
+            sp<GraphicBufferSource> source = mSource.promote();
+            if (source == nullptr || source->signalEndOfInputStream() != OK) {
+                // TODO: put something in |failures|
+                err = C2_BAD_VALUE;
+            }
+            // TODO: reset eos?
+        }
+        return err;
+    }
+
+    virtual c2_status_t querySupportedParams(
+            std::vector<std::shared_ptr<C2ParamDescriptor>>* const params
+            ) const override {
+        return mIntf->querySupportedParams(params);
+    }
+
+    virtual c2_status_t querySupportedValues(
+            std::vector<C2FieldSupportedValuesQuery>& fields,
+            c2_blocking_t mayBlock) const override {
+        return mIntf->querySupportedValues(fields, mayBlock);
+    }
+
+private:
+    const std::shared_ptr<InputSurface::Interface> mIntf;
+    wp<GraphicBufferSource> mSource;
+};
+
+Return<sp<InputSurface::HGraphicBufferProducer>> InputSurface::getGraphicBufferProducer() {
+    return mProducer;
+}
+
+Return<sp<IConfigurable>> InputSurface::getConfigurable() {
+    return mConfigurable;
+}
+
+Return<void> InputSurface::connect(
+        const sp<IInputSink>& sink,
+        connect_cb _hidl_cb) {
+    Status status;
+    sp<InputSurfaceConnection> connection;
+    if (!sink) {
+        _hidl_cb(Status::BAD_VALUE, nullptr);
+        return Void();
+    }
+    std::shared_ptr<C2Component> comp = Component::findLocalComponent(sink);
+    if (comp) {
+        connection = new InputSurfaceConnection(mSource, comp, mParameterCache);
+    } else {
+        connection = new InputSurfaceConnection(mSource, sink, mParameterCache);
+    }
+    if (!connection->init()) {
+        connection = nullptr;
+        status = Status::BAD_VALUE;
+    } else {
+        status = Status::OK;
+    }
+    _hidl_cb(status, connection);
+    return Void();
+}
+
+// Constructor is exclusive to ComponentStore.
+InputSurface::InputSurface(
+        const std::shared_ptr<ParameterCache>& cache,
+        const std::shared_ptr<C2ReflectorHelper>& reflector,
+        const sp<HGraphicBufferProducer>& producer,
+        const sp<GraphicBufferSource>& source)
+      : mParameterCache{cache},
+        mProducer{producer},
+        mSource{source},
+        mIntf{std::make_shared<Interface>(reflector)},
+        mConfigurable{new CachedConfigurable(
+                std::make_unique<ConfigurableIntf>(
+                    mIntf, source))} {
+
+    mConfigurable->init(mParameterCache);
+}
+
+}  // namespace utils
+}  // namespace V1_0
+}  // namespace c2
+}  // namespace media
+}  // namespace hardware
+}  // namespace android
+
diff --git a/media/codec2/hal/aidl/InputSurfaceConnection.cpp b/media/codec2/hal/aidl/InputSurfaceConnection.cpp
new file mode 100644
index 0000000..7c2e014
--- /dev/null
+++ b/media/codec2/hal/aidl/InputSurfaceConnection.cpp
@@ -0,0 +1,531 @@
+/*
+ * 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-InputSurfaceConnection"
+#include <android-base/logging.h>
+
+#include <codec2/hidl/1.0/InputSurfaceConnection.h>
+#include <codec2/hidl/1.0/InputSurfaceConnection.h>
+
+#include <memory>
+#include <list>
+#include <mutex>
+#include <atomic>
+
+#include <hidl/HidlSupport.h>
+#include <media/stagefright/bqhelper/ComponentWrapper.h>
+#include <system/graphics.h>
+#include <ui/GraphicBuffer.h>
+#include <utils/Errors.h>
+
+#include <C2.h>
+#include <C2AllocatorGralloc.h>
+#include <C2BlockInternal.h>
+#include <C2Buffer.h>
+#include <C2Component.h>
+#include <C2Config.h>
+#include <C2Debug.h>
+#include <C2PlatformSupport.h>
+#include <C2Work.h>
+
+namespace android {
+namespace hardware {
+namespace media {
+namespace c2 {
+namespace V1_0 {
+namespace utils {
+
+constexpr int32_t kBufferCount = 16;
+
+using namespace ::android;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+
+namespace /* unnamed */ {
+
+class Buffer2D : public C2Buffer {
+public:
+    explicit Buffer2D(C2ConstGraphicBlock block) : C2Buffer({ block }) {
+    }
+};
+
+} // unnamed namespace
+
+// Derived class of ComponentWrapper for use with
+// GraphicBufferSource::configure().
+//
+struct InputSurfaceConnection::Impl : public ComponentWrapper {
+
+    Impl(const sp<GraphicBufferSource>& source,
+         const std::shared_ptr<C2Component>& localComp)
+          : mSource{source}, mLocalComp{localComp}, mSink{}, mFrameIndex{0} {
+        std::shared_ptr<C2ComponentInterface> intf = localComp->intf();
+        mSinkName = intf ? intf->getName() : "";
+    }
+
+    Impl(const sp<GraphicBufferSource>& source,
+         const sp<IInputSink>& sink)
+          : mSource{source}, mLocalComp{}, mSink{sink}, mFrameIndex{0} {
+        Return<sp<IConfigurable>> transResult = sink->getConfigurable();
+        if (!transResult.isOk()) {
+            LOG(ERROR) << "Remote sink is dead.";
+            return;
+        }
+        mSinkConfigurable =
+                static_cast<sp<IConfigurable>>(transResult);
+        if (!mSinkConfigurable) {
+            LOG(ERROR) << "Remote sink is not configurable.";
+            mSinkName = "";
+            return;
+        }
+
+        hidl_string name;
+        Return<void> transStatus = mSinkConfigurable->getName(
+                [&name](const hidl_string& n) {
+                    name = n;
+                });
+        if (!transStatus.isOk()) {
+            LOG(ERROR) << "Remote sink's configurable is dead.";
+            mSinkName = "";
+            return;
+        }
+        mSinkName = name.c_str();
+    }
+
+    virtual ~Impl() {
+        mSource->stop();
+        mSource->release();
+    }
+
+    bool init() {
+        if (mSource == nullptr) {
+            return false;
+        }
+        status_t err = mSource->initCheck();
+        if (err != OK) {
+            LOG(WARNING) << "Impl::init -- GraphicBufferSource init failed: "
+                         << "status = " << err << ".";
+            return false;
+        }
+
+        // TODO: read settings properly from the interface
+        C2StreamPictureSizeInfo::input inputSize;
+        C2StreamUsageTuning::input usage;
+        c2_status_t c2Status = queryFromSink({ &inputSize, &usage },
+                                         {},
+                                         C2_MAY_BLOCK,
+                                         nullptr);
+        if (c2Status != C2_OK) {
+            LOG(WARNING) << "Impl::init -- cannot query information from "
+                            "the component interface: "
+                         << "status = " << asString(c2Status) << ".";
+            return false;
+        }
+
+        // TODO: proper color aspect & dataspace
+        android_dataspace dataSpace = HAL_DATASPACE_BT709;
+
+        // TODO: use the usage read from intf
+        // uint32_t grallocUsage =
+        //         C2AndroidMemoryUsage(C2MemoryUsage(usage.value)).
+        //         asGrallocUsage();
+
+        uint32_t grallocUsage =
+                mSinkName.compare(0, 11, "c2.android.") == 0 ?
+                GRALLOC_USAGE_SW_READ_OFTEN :
+                GRALLOC_USAGE_HW_VIDEO_ENCODER;
+
+        err = mSource->configure(
+                this, dataSpace, kBufferCount,
+                inputSize.width, inputSize.height,
+                grallocUsage);
+        if (err != OK) {
+            LOG(WARNING) << "Impl::init -- GBS configure failed: "
+                         << "status = " << err << ".";
+            return false;
+        }
+        for (int32_t i = 0; i < kBufferCount; ++i) {
+            if (mSource->onInputBufferAdded(i) != OK) {
+                LOG(WARNING) << "Impl::init: failed to populate GBS slots.";
+                return false;
+            }
+        }
+        if (mSource->start() != OK) {
+            LOG(WARNING) << "Impl::init -- GBS failed to start.";
+            return false;
+        }
+        mAllocatorMutex.lock();
+        c2_status_t c2err = GetCodec2PlatformAllocatorStore()->fetchAllocator(
+                C2AllocatorStore::PLATFORM_START + 1,  // GRALLOC
+                &mAllocator);
+        mAllocatorMutex.unlock();
+        if (c2err != OK) {
+            LOG(WARNING) << "Impl::init -- failed to fetch gralloc allocator: "
+                         << "status = " << asString(c2err) << ".";
+            return false;
+        }
+        return true;
+    }
+
+    // From ComponentWrapper
+    virtual status_t submitBuffer(
+            int32_t bufferId,
+            const sp<GraphicBuffer>& buffer,
+            int64_t timestamp,
+            int fenceFd) override {
+        LOG(VERBOSE) << "Impl::submitBuffer -- bufferId = " << bufferId << ".";
+        // TODO: Use fd to construct fence
+        (void)fenceFd;
+
+        std::shared_ptr<C2GraphicAllocation> alloc;
+        C2Handle* handle = WrapNativeCodec2GrallocHandle(
+                buffer->handle,
+                buffer->width, buffer->height,
+                buffer->format, buffer->usage, buffer->stride);
+        mAllocatorMutex.lock();
+        c2_status_t err = mAllocator->priorGraphicAllocation(handle, &alloc);
+        mAllocatorMutex.unlock();
+        if (err != OK) {
+            native_handle_close(handle);
+            native_handle_delete(handle);
+            return UNKNOWN_ERROR;
+        }
+        std::shared_ptr<C2GraphicBlock> block =
+                _C2BlockFactory::CreateGraphicBlock(alloc);
+
+        std::unique_ptr<C2Work> work(new C2Work);
+        work->input.flags = (C2FrameData::flags_t)0;
+        work->input.ordinal.timestamp = timestamp;
+        work->input.ordinal.frameIndex = mFrameIndex.fetch_add(
+                1, std::memory_order_relaxed);
+        work->input.buffers.clear();
+        std::shared_ptr<C2Buffer> c2Buffer(
+                // TODO: fence
+                new Buffer2D(block->share(
+                        C2Rect(block->width(), block->height()), ::C2Fence())),
+                [bufferId, source = mSource](C2Buffer* ptr) {
+                    delete ptr;
+                    if (source != nullptr) {
+                        // TODO: fence
+                        (void)source->onInputBufferEmptied(bufferId, -1);
+                    }
+                });
+        work->input.buffers.push_back(c2Buffer);
+        work->worklets.clear();
+        work->worklets.emplace_back(new C2Worklet);
+        std::list<std::unique_ptr<C2Work>> items;
+        items.push_back(std::move(work));
+
+        err = queueToSink(&items);
+        return (err == C2_OK) ? OK : UNKNOWN_ERROR;
+    }
+
+    virtual status_t submitEos(int32_t bufferId) override {
+        LOG(VERBOSE) << "Impl::submitEos -- bufferId = " << bufferId << ".";
+        (void)bufferId;
+
+        std::unique_ptr<C2Work> work(new C2Work);
+        work->input.flags = (C2FrameData::flags_t)0;
+        work->input.ordinal.frameIndex = mFrameIndex.fetch_add(
+                1, std::memory_order_relaxed);
+        work->input.buffers.clear();
+        work->worklets.clear();
+        work->worklets.emplace_back(new C2Worklet);
+        std::list<std::unique_ptr<C2Work>> items;
+        items.push_back(std::move(work));
+
+        c2_status_t err = queueToSink(&items);
+        return (err == C2_OK) ? OK : UNKNOWN_ERROR;
+    }
+
+    virtual void dispatchDataSpaceChanged(
+            int32_t dataSpace, int32_t aspects, int32_t pixelFormat) override {
+        // TODO
+        (void)dataSpace;
+        (void)aspects;
+        (void)pixelFormat;
+    }
+
+    // Configurable interface for InputSurfaceConnection::Impl.
+    //
+    // This class is declared as an inner class so that it will have access to
+    // all Impl's members.
+    struct ConfigurableIntf : public ConfigurableC2Intf {
+        sp<Impl> mConnection;
+        ConfigurableIntf(const sp<Impl>& connection)
+              : ConfigurableC2Intf{"input-surface-connection", 0},
+                mConnection{connection} {}
+        virtual c2_status_t config(
+                const std::vector<C2Param*> &params,
+                c2_blocking_t mayBlock,
+                std::vector<std::unique_ptr<C2SettingResult>> *const failures
+                ) override;
+        virtual c2_status_t query(
+                const std::vector<C2Param::Index> &indices,
+                c2_blocking_t mayBlock,
+                std::vector<std::unique_ptr<C2Param>> *const params) const override;
+        virtual c2_status_t querySupportedParams(
+                std::vector<std::shared_ptr<C2ParamDescriptor>> *const params
+                ) const override;
+        virtual c2_status_t querySupportedValues(
+                std::vector<C2FieldSupportedValuesQuery> &fields,
+                c2_blocking_t mayBlock) const override;
+    };
+
+private:
+    c2_status_t queryFromSink(
+            const std::vector<C2Param*> &stackParams,
+            const std::vector<C2Param::Index> &heapParamIndices,
+            c2_blocking_t mayBlock,
+            std::vector<std::unique_ptr<C2Param>>* const heapParams) {
+        if (mLocalComp) {
+            std::shared_ptr<C2ComponentInterface> intf = mLocalComp->intf();
+            if (intf) {
+                return intf->query_vb(stackParams,
+                                      heapParamIndices,
+                                      mayBlock,
+                                      heapParams);
+            } else {
+                LOG(ERROR) << "queryFromSink -- "
+                           << "component does not have an interface.";
+                return C2_BAD_STATE;
+            }
+        }
+
+        CHECK(mSink) << "-- queryFromSink "
+                     << "-- connection has no sink.";
+        CHECK(mSinkConfigurable) << "-- queryFromSink "
+                                 << "-- sink has no configurable.";
+
+        hidl_vec<ParamIndex> indices(
+                stackParams.size() + heapParamIndices.size());
+        size_t numIndices = 0;
+        for (C2Param* const& stackParam : stackParams) {
+            if (!stackParam) {
+                LOG(DEBUG) << "queryFromSink -- null stack param encountered.";
+                continue;
+            }
+            indices[numIndices++] = static_cast<ParamIndex>(stackParam->index());
+        }
+        size_t numStackIndices = numIndices;
+        for (const C2Param::Index& index : heapParamIndices) {
+            indices[numIndices++] =
+                    static_cast<ParamIndex>(static_cast<uint32_t>(index));
+        }
+        indices.resize(numIndices);
+        if (heapParams) {
+            heapParams->reserve(heapParams->size() + numIndices);
+        }
+        c2_status_t status;
+        Return<void> transStatus = mSinkConfigurable->query(
+                indices,
+                mayBlock == C2_MAY_BLOCK,
+                [&status, &numStackIndices, &stackParams, heapParams](
+                        Status s, const Params& p) {
+                    status = static_cast<c2_status_t>(s);
+                    if (status != C2_OK && status != C2_BAD_INDEX) {
+                        LOG(DEBUG) << "queryFromSink -- call failed: "
+                                   << "status = " << asString(status) << ".";
+                        return;
+                    }
+                    std::vector<C2Param*> paramPointers;
+                    if (!parseParamsBlob(&paramPointers, p)) {
+                        LOG(DEBUG) << "queryFromSink -- error while "
+                                   << "parsing params.";
+                        status = C2_CORRUPTED;
+                        return;
+                    }
+                    size_t i = 0;
+                    for (auto it = paramPointers.begin();
+                            it != paramPointers.end(); ) {
+                        C2Param* paramPointer = *it;
+                        if (numStackIndices > 0) {
+                            --numStackIndices;
+                            if (!paramPointer) {
+                                LOG(DEBUG) << "queryFromSink -- "
+                                              "null stack param.";
+                                ++it;
+                                continue;
+                            }
+                            for (; i < stackParams.size() &&
+                                    !stackParams[i]; ) {
+                                ++i;
+                            }
+                            CHECK(i < stackParams.size());
+                            if (stackParams[i]->index() !=
+                                    paramPointer->index()) {
+                                LOG(DEBUG) << "queryFromSink -- "
+                                              "param skipped (index = "
+                                           << stackParams[i]->index() << ").";
+                                stackParams[i++]->invalidate();
+                                continue;
+                            }
+                            if (!stackParams[i++]->updateFrom(*paramPointer)) {
+                                LOG(DEBUG) << "queryFromSink -- "
+                                              "param update failed (index = "
+                                           << paramPointer->index() << ").";
+                            }
+                        } else {
+                            if (!paramPointer) {
+                                LOG(DEBUG) << "queryFromSink -- "
+                                              "null heap param.";
+                                ++it;
+                                continue;
+                            }
+                            if (!heapParams) {
+                                LOG(WARNING) << "queryFromSink -- "
+                                                "too many stack params.";
+                                break;
+                            }
+                            heapParams->emplace_back(C2Param::Copy(*paramPointer));
+                        }
+                        ++it;
+                    }
+                });
+        if (!transStatus.isOk()) {
+            LOG(ERROR) << "queryFromSink -- transaction failed.";
+            return C2_CORRUPTED;
+        }
+        return status;
+    }
+
+    c2_status_t queueToSink(std::list<std::unique_ptr<C2Work>>* const items) {
+        if (mLocalComp) {
+            return mLocalComp->queue_nb(items);
+        }
+
+        CHECK(mSink) << "-- queueToSink "
+                     << "-- connection has no sink.";
+
+        WorkBundle workBundle;
+        if (!objcpy(&workBundle, *items, nullptr)) {
+            LOG(ERROR) << "queueToSink -- bad input.";
+            return C2_CORRUPTED;
+        }
+        Return<Status> transStatus = mSink->queue(workBundle);
+        if (!transStatus.isOk()) {
+            LOG(ERROR) << "queueToSink -- transaction failed.";
+            return C2_CORRUPTED;
+        }
+        c2_status_t status =
+                static_cast<c2_status_t>(static_cast<Status>(transStatus));
+        if (status != C2_OK) {
+            LOG(DEBUG) << "queueToSink -- call failed: "
+                         << asString(status);
+        }
+        return status;
+    }
+
+    sp<GraphicBufferSource> mSource;
+    std::shared_ptr<C2Component> mLocalComp;
+    sp<IInputSink> mSink;
+    sp<IConfigurable> mSinkConfigurable;
+    std::string mSinkName;
+
+    // Needed for ComponentWrapper implementation
+    std::mutex mAllocatorMutex;
+    std::shared_ptr<C2Allocator> mAllocator;
+    std::atomic_uint64_t mFrameIndex;
+
+};
+
+InputSurfaceConnection::InputSurfaceConnection(
+        const sp<GraphicBufferSource>& source,
+        const std::shared_ptr<C2Component>& comp,
+        const std::shared_ptr<ParameterCache>& cache)
+      : mImpl{new Impl(source, comp)},
+        mConfigurable{new CachedConfigurable(
+            std::make_unique<Impl::ConfigurableIntf>(mImpl))} {
+    mConfigurable->init(cache);
+}
+
+InputSurfaceConnection::InputSurfaceConnection(
+        const sp<GraphicBufferSource>& source,
+        const sp<IInputSink>& sink,
+        const std::shared_ptr<ParameterCache>& cache)
+      : mImpl{new Impl(source, sink)},
+        mConfigurable{new CachedConfigurable(
+            std::make_unique<Impl::ConfigurableIntf>(mImpl))} {
+    mConfigurable->init(cache);
+}
+
+Return<Status> InputSurfaceConnection::disconnect() {
+    std::lock_guard<std::mutex> lock(mImplMutex);
+    mImpl = nullptr;
+    return Status::OK;
+}
+
+InputSurfaceConnection::~InputSurfaceConnection() {
+    mImpl = nullptr;
+}
+
+bool InputSurfaceConnection::init() {
+    std::lock_guard<std::mutex> lock(mImplMutex);
+    return mImpl->init();
+}
+
+Return<sp<IConfigurable>> InputSurfaceConnection::getConfigurable() {
+    return mConfigurable;
+}
+
+// Configurable interface for InputSurfaceConnection::Impl
+c2_status_t InputSurfaceConnection::Impl::ConfigurableIntf::config(
+        const std::vector<C2Param*> &params,
+        c2_blocking_t mayBlock,
+        std::vector<std::unique_ptr<C2SettingResult>> *const failures) {
+    // TODO: implement
+    (void)params;
+    (void)mayBlock;
+    (void)failures;
+    return C2_OK;
+}
+
+c2_status_t InputSurfaceConnection::Impl::ConfigurableIntf::query(
+        const std::vector<C2Param::Index> &indices,
+        c2_blocking_t mayBlock,
+        std::vector<std::unique_ptr<C2Param>> *const params) const {
+    // TODO: implement
+    (void)indices;
+    (void)mayBlock;
+    (void)params;
+    return C2_OK;
+}
+
+c2_status_t InputSurfaceConnection::Impl::ConfigurableIntf::querySupportedParams(
+        std::vector<std::shared_ptr<C2ParamDescriptor>> *const params) const {
+    // TODO: implement
+    (void)params;
+    return C2_OK;
+}
+
+c2_status_t InputSurfaceConnection::Impl::ConfigurableIntf::querySupportedValues(
+        std::vector<C2FieldSupportedValuesQuery> &fields,
+        c2_blocking_t mayBlock) const {
+    // TODO: implement
+    (void)fields;
+    (void)mayBlock;
+    return C2_OK;
+}
+
+}  // namespace utils
+}  // namespace V1_0
+}  // namespace c2
+}  // namespace media
+}  // namespace hardware
+}  // namespace android
+
diff --git a/media/codec2/hal/aidl/ParamTypes.cpp b/media/codec2/hal/aidl/ParamTypes.cpp
index 0a430f9..7026f4c 100644
--- a/media/codec2/hal/aidl/ParamTypes.cpp
+++ b/media/codec2/hal/aidl/ParamTypes.cpp
@@ -157,14 +157,13 @@
 namespace c2 {
 namespace utils {
 
+// TODO: read it from aconfig flags
+bool IsEnabled() { return false; }
+
 const char* asString(Status status, const char* def) {
     return asString(static_cast<c2_status_t>(status.status), def);
 }
 
-namespace /* unnamed */ {
-
-} // unnamed namespace
-
 // C2FieldSupportedValuesQuery -> FieldSupportedValuesQuery
 bool ToAidl(
         FieldSupportedValuesQuery* d,
diff --git a/media/codec2/hal/aidl/include/codec2/aidl/BufferTypes.h b/media/codec2/hal/aidl/include/codec2/aidl/BufferTypes.h
index f111f81..470863c 100644
--- a/media/codec2/hal/aidl/include/codec2/aidl/BufferTypes.h
+++ b/media/codec2/hal/aidl/include/codec2/aidl/BufferTypes.h
@@ -14,156 +14,36 @@
  * limitations under the License.
  */
 
-#ifndef CODEC2_HIDL_V1_0_UTILS_TYPES_H
-#define CODEC2_HIDL_V1_0_UTILS_TYPES_H
+#ifndef CODEC2_AIDL_BUFFER_TYPES_H
+#define CODEC2_AIDL_BUFFER_TYPES_H
 
-#include <bufferpool/ClientManager.h>
-#include <android/hardware/media/bufferpool/2.0/IClientManager.h>
-#include <android/hardware/media/bufferpool/2.0/types.h>
-#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/BufferTypes.h>
 
-#include <C2Component.h>
-#include <C2Param.h>
-#include <C2ParamDef.h>
-#include <C2Work.h>
-#include <util/C2Debug-base.h>
+#include <aidl/android/hardware/media/bufferpool2/BufferStatusMessage.h>
+#include <aidl/android/hardware/media/bufferpool2/IClientManager.h>
+#include <aidl/android/hardware/media/bufferpool2/ResultStatus.h>
+#include <aidl/android/hardware/media/c2/WorkBundle.h>
 
-#include <chrono>
+#include <bufferpool2/BufferPoolTypes.h>
+#include <bufferpool2/ClientManager.h>
 
-using namespace std::chrono_literals;
 
+namespace aidl {
 namespace android {
 namespace hardware {
 namespace media {
 namespace c2 {
-namespace V1_0 {
 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;
-using ::android::hardware::media::bufferpool::V2_0::implementation::
-        ConnectionId;
+namespace bufferpool2 = ::aidl::android::hardware::media::bufferpool2;
 
-// Types of metadata for Blocks.
-struct C2Hidl_Range {
-    uint32_t offset;
-    uint32_t length; // Do not use "size" because the name collides with C2Info::size().
-};
-typedef C2GlobalParam<C2Info, C2Hidl_Range, 0> C2Hidl_RangeInfo;
+using namespace std::chrono_literals;
 
-struct C2Hidl_Rect {
-    uint32_t left;
-    uint32_t top;
-    uint32_t width;
-    uint32_t height;
-};
-typedef C2GlobalParam<C2Info, C2Hidl_Rect, 1> C2Hidl_RectInfo;
-
-// Make asString() and operator<< work with Status as well as c2_status_t.
-C2_DECLARE_AS_STRING_AND_DEFINE_STREAM_OUT(Status);
-
-/**
- * All objcpy() functions will return a boolean value indicating whether the
- * conversion succeeds or not.
- */
-
-// C2SettingResult -> SettingResult
-bool objcpy(
-        SettingResult* d,
-        const C2SettingResult& s);
-
-// SettingResult -> std::unique_ptr<C2SettingResult>
-bool objcpy(
-        std::unique_ptr<C2SettingResult>* d,
-        const SettingResult& s);
-
-// C2ParamDescriptor -> ParamDescriptor
-bool objcpy(
-        ParamDescriptor* d,
-        const C2ParamDescriptor& s);
-
-// ParamDescriptor -> std::shared_ptr<C2ParamDescriptor>
-bool objcpy(
-        std::shared_ptr<C2ParamDescriptor>* d,
-        const ParamDescriptor& s);
-
-// C2FieldSupportedValuesQuery -> FieldSupportedValuesQuery
-bool objcpy(
-        FieldSupportedValuesQuery* d,
-        const C2FieldSupportedValuesQuery& s);
-
-// FieldSupportedValuesQuery -> C2FieldSupportedValuesQuery
-bool objcpy(
-        C2FieldSupportedValuesQuery* d,
-        const FieldSupportedValuesQuery& s);
-
-// C2FieldSupportedValuesQuery -> FieldSupportedValuesQueryResult
-bool objcpy(
-        FieldSupportedValuesQueryResult* d,
-        const C2FieldSupportedValuesQuery& s);
-
-// FieldSupportedValuesQuery, FieldSupportedValuesQueryResult -> C2FieldSupportedValuesQuery
-bool objcpy(
-        C2FieldSupportedValuesQuery* d,
-        const FieldSupportedValuesQuery& sq,
-        const FieldSupportedValuesQueryResult& sr);
-
-// C2Component::Traits -> ComponentTraits
-bool objcpy(
-        IComponentStore::ComponentTraits* d,
-        const C2Component::Traits& s);
-
-// ComponentTraits -> C2Component::Traits
-bool objcpy(
-        C2Component::Traits* d,
-        const IComponentStore::ComponentTraits& s);
-
-// C2StructDescriptor -> StructDescriptor
-bool objcpy(
-        StructDescriptor* d,
-        const C2StructDescriptor& s);
-
-// StructDescriptor -> C2StructDescriptor
-bool objcpy(
-        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 bufferpool2::BufferPoolData BufferPoolData;
+    typedef bufferpool2::ResultStatus ResultStatus;
+    typedef bufferpool2::implementation::BufferPoolStatus BufferPoolStatus;
+    typedef bufferpool2::BufferStatusMessage BufferStatusMessage;
 };
 
 // Default implementation of BufferPoolSender.
@@ -173,18 +53,16 @@
 // hold a strong reference to the IClientManager instance and use it to call
 // IClientManager::registerSender() to establish the bufferpool connection when
 // send() is called.
-struct DefaultBufferPoolSender : BufferPoolSender {
-    typedef ::android::hardware::media::bufferpool::V2_0::implementation::
-            ClientManager ClientManager;
-    typedef ::android::hardware::media::bufferpool::V2_0::
-            IClientManager IClientManager;
+struct DefaultBufferPoolSender : ::android::BufferPoolSender<BufferPoolTypes> {
+    typedef bufferpool2::implementation::ClientManager ClientManager;
+    typedef bufferpool2::IClientManager IClientManager;
 
     // Set the IClientManager instance of the receiving process and the refresh
     // interval for the connection. The default interval is 4.5 seconds, which
     // is slightly shorter than the amount of time the bufferpool will keep an
     // inactive connection for.
     DefaultBufferPoolSender(
-            const sp<IClientManager>& receiverManager = nullptr,
+            const std::shared_ptr<IClientManager>& receiverManager = nullptr,
             std::chrono::steady_clock::duration refreshInterval = 4500ms);
 
     // Set the IClientManager instance of the receiving process and the refresh
@@ -192,20 +70,20 @@
     // is slightly shorter than the amount of time the bufferpool will keep an
     // inactive connection for.
     void setReceiver(
-            const sp<IClientManager>& receiverManager,
+            const std::shared_ptr<IClientManager>& receiverManager,
             std::chrono::steady_clock::duration refreshInterval = 4500ms);
 
     // 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(
+    BufferPoolStatus send(
             const std::shared_ptr<BufferPoolData>& bpData,
             BufferStatusMessage* bpMessage) override;
 
 private:
     std::mutex mMutex;
-    sp<ClientManager> mSenderManager;
-    sp<IClientManager> mReceiverManager;
+    std::shared_ptr<ClientManager> mSenderManager;
+    std::shared_ptr<IClientManager> mReceiverManager;
     std::chrono::steady_clock::duration mRefreshInterval;
 
     struct Connection {
@@ -227,137 +105,28 @@
 
 // std::list<std::unique_ptr<C2Work>> -> WorkBundle
 // Note: If bufferpool will be used, bpSender must not be null.
-bool objcpy(
+bool ToAidl(
         WorkBundle* d,
         const std::list<std::unique_ptr<C2Work>>& s,
-        BufferPoolSender* bpSender = nullptr);
+        ::android::BufferPoolSender<BufferPoolTypes>* bpSender = nullptr);
 
 // WorkBundle -> std::list<std::unique_ptr<C2Work>>
-bool objcpy(
+bool FromAidl(
         std::list<std::unique_ptr<C2Work>>* d,
         const WorkBundle& s);
 
 /**
- * Parses a params blob and returns C2Param pointers to its params. The pointers
- * point to locations inside the underlying buffer of \p blob. If \p blob is
- * destroyed, the pointers become invalid.
- *
- * \param[out] params target vector of C2Param pointers
- * \param[in] blob parameter blob to parse
- * \retval true if the full blob was parsed
- * \retval false otherwise
- */
-bool parseParamsBlob(
-        std::vector<C2Param*> *params,
-        const hidl_vec<uint8_t> &blob);
-
-/**
- * Concatenates a list of C2Params into a params blob.
- *
- * \param[out] blob target blob
- * \param[in] params parameters to concatenate
- * \retval true if the blob was successfully created
- * \retval false if the blob was not successful (this only happens if the
- *         parameters were not const)
- */
-bool createParamsBlob(
-        hidl_vec<uint8_t> *blob,
-        const std::vector<C2Param*> &params);
-bool createParamsBlob(
-        hidl_vec<uint8_t> *blob,
-        const std::vector<std::unique_ptr<C2Param>> &params);
-bool createParamsBlob(
-        hidl_vec<uint8_t> *blob,
-        const std::vector<std::shared_ptr<const C2Info>> &params);
-bool createParamsBlob(
-        hidl_vec<uint8_t> *blob,
-        const std::vector<std::unique_ptr<C2Tuning>> &params);
-
-/**
- * Parses a params blob and create a vector of C2Params whose members are copies
- * of the params in the blob.
- *
- * \param[out] params the resulting vector
- * \param[in] blob parameter blob to parse
- * \retval true if the full blob was parsed and params was constructed
- * \retval false otherwise
- */
-bool copyParamsFromBlob(
-        std::vector<std::unique_ptr<C2Param>>* params,
-        Params blob);
-bool copyParamsFromBlob(
-        std::vector<std::unique_ptr<C2Tuning>>* params,
-        Params blob);
-
-/**
- * Parses a params blob and applies updates to params.
- *
- * \param[in,out] params params to be updated
- * \param[in] blob parameter blob containing updates
- * \retval true if the full blob was parsed and params was updated
- * \retval false otherwise
- */
-bool updateParamsFromBlob(
-        const std::vector<C2Param*>& params,
-        const Params& blob);
-
-/**
  * Converts a BufferPool status value to c2_status_t.
  * \param BufferPool status
  * \return Corresponding c2_status_t
  */
-c2_status_t toC2Status(::android::hardware::media::bufferpool::V2_0::
-        ResultStatus rs);
-
-// BufferQueue-Based Block Operations
-// ==================================
-
-// 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);
-
-// 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 = false,
-        bool processOutput = true);
-
-// 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);
-
-// 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 = false,
-        bool processOutput = true);
-
-// 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);
+c2_status_t toC2Status(BufferPoolTypes::BufferPoolStatus rs);
 
 }  // namespace utils
-}  // namespace V1_0
 }  // namespace c2
 }  // namespace media
 }  // namespace hardware
 }  // namespace android
+}  // namespace aidl
 
-#endif  // CODEC2_HIDL_V1_0_UTILS_TYPES_H
+#endif  // CODEC2_AIDL_BUFFER_TYPES_H
diff --git a/media/codec2/hal/aidl/include/codec2/aidl/Component.h b/media/codec2/hal/aidl/include/codec2/aidl/Component.h
new file mode 100644
index 0000000..e343655
--- /dev/null
+++ b/media/codec2/hal/aidl/include/codec2/aidl/Component.h
@@ -0,0 +1,147 @@
+/*
+ * 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_HIDL_V1_0_UTILS_COMPONENT_H
+#define CODEC2_HIDL_V1_0_UTILS_COMPONENT_H
+
+#include <codec2/hidl/1.0/ComponentInterface.h>
+#include <codec2/hidl/1.0/Configurable.h>
+#include <codec2/hidl/1.0/types.h>
+
+#include <android/hardware/media/bufferpool/2.0/IClientManager.h>
+#include <android/hardware/media/c2/1.0/IComponent.h>
+#include <android/hardware/media/c2/1.0/IComponentInterface.h>
+#include <android/hardware/media/c2/1.0/IComponentListener.h>
+#include <android/hardware/media/c2/1.0/IComponentStore.h>
+#include <android/hardware/media/c2/1.0/IInputSink.h>
+#include <hidl/Status.h>
+#include <hwbinder/IBinder.h>
+
+#include <C2Component.h>
+#include <C2Buffer.h>
+#include <C2.h>
+
+#include <map>
+#include <memory>
+#include <mutex>
+
+namespace android {
+namespace hardware {
+namespace media {
+namespace c2 {
+namespace V1_0 {
+namespace utils {
+
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_memory;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::IBinder;
+using ::android::sp;
+using ::android::wp;
+
+struct ComponentStore;
+
+struct Component : public IComponent,
+                   public std::enable_shared_from_this<Component> {
+    Component(
+            const std::shared_ptr<C2Component>&,
+            const sp<IComponentListener>& listener,
+            const sp<ComponentStore>& store,
+            const sp<::android::hardware::media::bufferpool::V2_0::
+                IClientManager>& clientPoolManager);
+    c2_status_t status() const;
+
+    typedef ::android::hardware::graphics::bufferqueue::V1_0::
+            IGraphicBufferProducer HGraphicBufferProducer1;
+    typedef ::android::hardware::graphics::bufferqueue::V2_0::
+            IGraphicBufferProducer HGraphicBufferProducer2;
+
+    // Methods from IComponent follow.
+    virtual Return<Status> queue(const WorkBundle& workBundle) override;
+    virtual Return<void> flush(flush_cb _hidl_cb) override;
+    virtual Return<Status> drain(bool withEos) override;
+    virtual Return<Status> setOutputSurface(
+            uint64_t blockPoolId,
+            const sp<HGraphicBufferProducer2>& surface) override;
+    virtual Return<void> connectToInputSurface(
+            const sp<IInputSurface>& inputSurface,
+            connectToInputSurface_cb _hidl_cb) override;
+    virtual Return<void> connectToOmxInputSurface(
+            const sp<HGraphicBufferProducer1>& producer,
+            const sp<::android::hardware::media::omx::V1_0::
+            IGraphicBufferSource>& source,
+            connectToOmxInputSurface_cb _hidl_cb) override;
+    virtual Return<Status> disconnectFromInputSurface() override;
+    virtual Return<void> createBlockPool(
+            uint32_t allocatorId,
+            createBlockPool_cb _hidl_cb) override;
+    virtual Return<Status> destroyBlockPool(uint64_t blockPoolId) override;
+    virtual Return<Status> start() override;
+    virtual Return<Status> stop() override;
+    virtual Return<Status> reset() override;
+    virtual Return<Status> release() override;
+    virtual Return<sp<IComponentInterface>> getInterface() override;
+    virtual Return<sp<IInputSink>> asInputSink() override;
+
+    // Returns a C2Component associated to the given sink if the sink is indeed
+    // a local component. Returns nullptr otherwise.
+    //
+    // This function is used by InputSurface::connect().
+    static std::shared_ptr<C2Component> findLocalComponent(
+            const sp<IInputSink>& sink);
+
+protected:
+    c2_status_t mInit;
+    std::shared_ptr<C2Component> mComponent;
+    sp<ComponentInterface> mInterface;
+    sp<IComponentListener> mListener;
+    sp<ComponentStore> mStore;
+    ::android::hardware::media::c2::V1_0::utils::DefaultBufferPoolSender
+            mBufferPoolSender;
+
+    struct Sink;
+    std::mutex mSinkMutex;
+    sp<Sink> mSink;
+
+    std::mutex mBlockPoolsMutex;
+    // This map keeps C2BlockPool objects that are created by createBlockPool()
+    // alive. These C2BlockPool objects can be deleted by calling
+    // destroyBlockPool(), reset() or release(), or by destroying the component.
+    std::map<uint64_t, std::shared_ptr<C2BlockPool>> mBlockPools;
+
+    void initListener(const sp<Component>& self);
+
+    virtual ~Component() override;
+
+    friend struct ComponentStore;
+
+    struct Listener;
+
+    using HwDeathRecipient = ::android::hardware::hidl_death_recipient;
+    sp<HwDeathRecipient> mDeathRecipient;
+};
+
+}  // namespace utils
+}  // namespace V1_0
+}  // namespace c2
+}  // namespace media
+}  // namespace hardware
+}  // namespace android
+
+#endif  // CODEC2_HIDL_V1_0_UTILS_COMPONENT_H
diff --git a/media/codec2/hal/aidl/include/codec2/aidl/ComponentInterface.h b/media/codec2/hal/aidl/include/codec2/aidl/ComponentInterface.h
new file mode 100644
index 0000000..9102f92
--- /dev/null
+++ b/media/codec2/hal/aidl/include/codec2/aidl/ComponentInterface.h
@@ -0,0 +1,66 @@
+/*
+ * 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_HIDL_V1_0_UTILS_COMPONENT_INTERFACE_H
+#define CODEC2_HIDL_V1_0_UTILS_COMPONENT_INTERFACE_H
+
+#include <codec2/hidl/1.0/Configurable.h>
+#include <codec2/hidl/1.0/types.h>
+
+#include <android/hardware/media/c2/1.0/IComponentInterface.h>
+#include <hidl/Status.h>
+
+#include <C2Component.h>
+#include <C2Buffer.h>
+#include <C2.h>
+
+#include <memory>
+
+namespace android {
+namespace hardware {
+namespace media {
+namespace c2 {
+namespace V1_0 {
+namespace utils {
+
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+
+struct ComponentStore;
+
+struct ComponentInterface : public IComponentInterface {
+    ComponentInterface(
+            const std::shared_ptr<C2ComponentInterface>& interface,
+            const std::shared_ptr<ParameterCache>& cache);
+    c2_status_t status() const;
+    virtual Return<sp<IConfigurable>> getConfigurable() override;
+
+protected:
+    std::shared_ptr<C2ComponentInterface> mInterface;
+    sp<CachedConfigurable> mConfigurable;
+    c2_status_t mInit;
+};
+
+
+}  // namespace utils
+}  // namespace V1_0
+}  // namespace c2
+}  // namespace media
+}  // namespace hardware
+}  // namespace android
+
+#endif  // CODEC2_HIDL_V1_0_UTILS_COMPONENT_INTERFACE_H
diff --git a/media/codec2/hal/aidl/include/codec2/aidl/ComponentStore.h b/media/codec2/hal/aidl/include/codec2/aidl/ComponentStore.h
new file mode 100644
index 0000000..27e2a05
--- /dev/null
+++ b/media/codec2/hal/aidl/include/codec2/aidl/ComponentStore.h
@@ -0,0 +1,162 @@
+/*
+ * 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_HIDL_V1_0_UTILS_COMPONENTSTORE_H
+#define CODEC2_HIDL_V1_0_UTILS_COMPONENTSTORE_H
+
+#include <codec2/hidl/1.0/Component.h>
+#include <codec2/hidl/1.0/ComponentInterface.h>
+#include <codec2/hidl/1.0/Configurable.h>
+
+#include <android/hardware/media/bufferpool/2.0/IClientManager.h>
+#include <android/hardware/media/c2/1.0/IComponentStore.h>
+#include <hidl/Status.h>
+
+#include <C2Component.h>
+#include <C2Param.h>
+#include <C2.h>
+
+#include <chrono>
+#include <map>
+#include <memory>
+#include <mutex>
+#include <set>
+#include <vector>
+
+namespace android {
+class FilterWrapper;
+
+namespace hardware {
+namespace media {
+namespace c2 {
+namespace V1_0 {
+namespace utils {
+
+using ::android::hardware::media::bufferpool::V2_0::IClientManager;
+
+using ::android::hardware::hidl_handle;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+
+struct ComponentStore : public IComponentStore {
+    ComponentStore(const std::shared_ptr<C2ComponentStore>& store);
+    virtual ~ComponentStore();
+
+    /**
+     * Returns the status of the construction of this object.
+     */
+    c2_status_t status() const;
+
+    /**
+     * This function is called by CachedConfigurable::init() to validate
+     * supported parameters.
+     */
+    c2_status_t validateSupportedParams(
+            const std::vector<std::shared_ptr<C2ParamDescriptor>>& params);
+
+    /**
+     * Returns the store's ParameterCache. This is used for validation by
+     * Configurable::init().
+     */
+    std::shared_ptr<ParameterCache> getParameterCache() const;
+
+    static std::shared_ptr<FilterWrapper> GetFilterWrapper();
+
+    // Methods from ::android::hardware::media::c2::V1_0::IComponentStore.
+    virtual Return<void> createComponent(
+            const hidl_string& name,
+            const sp<IComponentListener>& listener,
+            const sp<IClientManager>& pool,
+            createComponent_cb _hidl_cb) override;
+    virtual Return<void> createInterface(
+            const hidl_string& name,
+            createInterface_cb _hidl_cb) override;
+    virtual Return<void> listComponents(listComponents_cb _hidl_cb) override;
+    virtual Return<void> createInputSurface(
+            createInputSurface_cb _hidl_cb) override;
+    virtual Return<void> getStructDescriptors(
+            const hidl_vec<uint32_t>& indices,
+            getStructDescriptors_cb _hidl_cb) override;
+    virtual Return<sp<IClientManager>> getPoolClientManager() override;
+    virtual Return<Status> copyBuffer(
+            const Buffer& src,
+            const Buffer& dst) override;
+    virtual Return<sp<IConfigurable>> getConfigurable() override;
+
+    /**
+     * Dumps information when lshal is called.
+     */
+    virtual Return<void> debug(
+            const hidl_handle& handle,
+            const hidl_vec<hidl_string>& args) override;
+
+protected:
+    sp<CachedConfigurable> mConfigurable;
+    struct StoreParameterCache;
+    std::shared_ptr<StoreParameterCache> mParameterCache;
+
+    // Does bookkeeping for an interface that has been loaded.
+    void onInterfaceLoaded(const std::shared_ptr<C2ComponentInterface> &intf);
+
+    c2_status_t mInit;
+    std::shared_ptr<C2ComponentStore> mStore;
+    std::shared_ptr<C2ParamReflector> mParamReflector;
+
+    std::map<C2Param::CoreIndex, std::shared_ptr<C2StructDescriptor>> mStructDescriptors;
+    std::set<C2Param::CoreIndex> mUnsupportedStructDescriptors;
+    std::set<C2String> mLoadedInterfaces;
+    mutable std::mutex mStructDescriptorsMutex;
+
+    // ComponentStore keeps track of live Components.
+
+    struct ComponentStatus {
+        std::shared_ptr<C2Component> c2Component;
+        std::chrono::system_clock::time_point birthTime;
+    };
+
+    mutable std::mutex mComponentRosterMutex;
+    std::map<Component*, ComponentStatus> mComponentRoster;
+
+    // Called whenever Component is created.
+    void reportComponentBirth(Component* component);
+    // Called only from the destructor of Component.
+    void reportComponentDeath(Component* component);
+
+    friend Component;
+
+    // Helper functions for dumping.
+
+    std::ostream& dump(
+            std::ostream& out,
+            const std::shared_ptr<const C2Component::Traits>& comp);
+
+    std::ostream& dump(
+            std::ostream& out,
+            ComponentStatus& compStatus);
+
+};
+
+}  // namespace utils
+}  // namespace V1_0
+}  // namespace c2
+}  // namespace media
+}  // namespace hardware
+}  // namespace android
+
+#endif  // CODEC2_HIDL_V1_0_UTILS_COMPONENTSTORE_H
diff --git a/media/codec2/hal/aidl/include/codec2/aidl/Configurable.h b/media/codec2/hal/aidl/include/codec2/aidl/Configurable.h
new file mode 100644
index 0000000..8f49a97
--- /dev/null
+++ b/media/codec2/hal/aidl/include/codec2/aidl/Configurable.h
@@ -0,0 +1,153 @@
+/*
+ * 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_HIDL_V1_0_UTILS_CONFIGURABLE_H
+#define CODEC2_HIDL_V1_0_UTILS_CONFIGURABLE_H
+
+#include <android/hardware/media/c2/1.0/IConfigurable.h>
+#include <hidl/Status.h>
+
+#include <C2Component.h>
+#include <C2Param.h>
+#include <C2.h>
+
+#include <memory>
+
+namespace android {
+namespace hardware {
+namespace media {
+namespace c2 {
+namespace V1_0 {
+namespace utils {
+
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+
+struct ComponentStore;
+
+/**
+ * Codec2 objects of different types may have different querying and configuring
+ * functions, but across the Treble boundary, they share the same HIDL
+ * interface, IConfigurable.
+ *
+ * ConfigurableC2Intf is an abstract class that a Codec2 object can implement to
+ * easily expose an IConfigurable instance. See CachedConfigurable below.
+ */
+struct ConfigurableC2Intf {
+    C2String getName() const { return mName; }
+    uint32_t getId() const { return mId; }
+    /** C2ComponentInterface::query_vb sans stack params */
+    virtual c2_status_t query(
+            const std::vector<C2Param::Index> &indices,
+            c2_blocking_t mayBlock,
+            std::vector<std::unique_ptr<C2Param>>* const params) const = 0;
+    /** C2ComponentInterface::config_vb */
+    virtual c2_status_t config(
+            const std::vector<C2Param*> &params,
+            c2_blocking_t mayBlock,
+            std::vector<std::unique_ptr<C2SettingResult>>* const failures) = 0;
+    /** C2ComponentInterface::querySupportedParams_nb */
+    virtual c2_status_t querySupportedParams(
+            std::vector<std::shared_ptr<C2ParamDescriptor>>* const params) const = 0;
+    /** C2ComponentInterface::querySupportedParams_nb */
+    virtual c2_status_t querySupportedValues(
+            std::vector<C2FieldSupportedValuesQuery>& fields, c2_blocking_t mayBlock) const = 0;
+
+    virtual ~ConfigurableC2Intf() = default;
+
+    ConfigurableC2Intf(const C2String& name, uint32_t id)
+          : mName{name}, mId{id} {}
+
+protected:
+    C2String mName; /* cached component name */
+    uint32_t mId;
+};
+
+/**
+ * Type for validating and caching parameters when CachedConfigurable is
+ * initialized.
+ *
+ * This is meant to be created by the ComponentStore. The purpose of abstracting
+ * this is to allow different versions of ComponentStore to work with this
+ * CachedConfigurable.
+ */
+struct ParameterCache {
+    virtual c2_status_t validate(
+            const std::vector<std::shared_ptr<C2ParamDescriptor>>&) = 0;
+    virtual ~ParameterCache() = default;
+};
+
+/**
+ * Implementation of the IConfigurable interface that supports caching of
+ * supported parameters from a supplied ComponentStore.
+ *
+ * CachedConfigurable essentially converts a ConfigurableC2Intf into HIDL's
+ * IConfigurable. A Codec2 object generally implements ConfigurableC2Intf and
+ * passes the implementation to the constructor of CachedConfigurable.
+ *
+ * Note that caching happens
+ */
+struct CachedConfigurable : public IConfigurable {
+    CachedConfigurable(std::unique_ptr<ConfigurableC2Intf>&& intf);
+
+    // Populates mSupportedParams.
+    c2_status_t init(const std::shared_ptr<ParameterCache> &cache);
+
+    // Methods from ::android::hardware::media::c2::V1_0::IConfigurable
+
+    virtual Return<uint32_t> getId() override;
+
+    virtual Return<void> getName(getName_cb _hidl_cb) override;
+
+    virtual Return<void> query(
+            const hidl_vec<uint32_t>& indices,
+            bool mayBlock,
+            query_cb _hidl_cb) override;
+
+    virtual Return<void> config(
+            const hidl_vec<uint8_t>& inParams,
+            bool mayBlock,
+            config_cb _hidl_cb) override;
+
+    virtual Return<void> querySupportedParams(
+            uint32_t start,
+            uint32_t count,
+            querySupportedParams_cb _hidl_cb) override;
+
+    virtual Return<void> querySupportedValues(
+            const hidl_vec<FieldSupportedValuesQuery>& inFields,
+            bool mayBlock,
+            querySupportedValues_cb _hidl_cb) override;
+
+protected:
+    // Common Codec2.0 interface wrapper
+    std::unique_ptr<ConfigurableC2Intf> mIntf;
+
+    // Cached supported params
+    std::vector<std::shared_ptr<C2ParamDescriptor>> mSupportedParams;
+};
+
+}  // namespace utils
+}  // namespace V1_0
+}  // namespace c2
+}  // namespace media
+}  // namespace hardware
+}  // namespace android
+
+#endif  // CODEC2_HIDL_V1_0_UTILS_CONFIGURABLE_H
+
diff --git a/media/codec2/hal/aidl/include/codec2/aidl/InputBufferManager.h b/media/codec2/hal/aidl/include/codec2/aidl/InputBufferManager.h
new file mode 100644
index 0000000..42fa557
--- /dev/null
+++ b/media/codec2/hal/aidl/include/codec2/aidl/InputBufferManager.h
@@ -0,0 +1,300 @@
+/*
+ * 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_HIDL_V1_0_UTILS_INPUT_BUFFER_MANAGER_H
+#define CODEC2_HIDL_V1_0_UTILS_INPUT_BUFFER_MANAGER_H
+
+#include <android/hardware/media/c2/1.0/IComponentListener.h>
+#include <utils/Timers.h>
+
+#include <C2Buffer.h>
+#include <C2Work.h>
+
+#include <set>
+#include <map>
+#include <thread>
+
+namespace android {
+namespace hardware {
+namespace media {
+namespace c2 {
+namespace V1_0 {
+namespace utils {
+
+using namespace ::android;
+
+/**
+ * InputBufferManager
+ * ==================
+ *
+ * InputBufferManager presents a way to track and untrack input buffers in this
+ * (codec) process and send a notification to a listener, possibly in a
+ * different process, when a tracked buffer no longer has any references in this
+ * process.
+ *
+ * InputBufferManager holds a collection of records representing tracked buffers
+ * and their callback listeners. Conceptually, one record is a triple (listener,
+ * frameIndex, bufferIndex) where
+ *
+ * - (frameIndex, bufferIndex) is a pair of indices used to identify the buffer.
+ * - listener is of type IComponentListener. Its onInputBuffersReleased()
+ *   function will be called after the associated buffer dies. The argument of
+ *   onInputBuffersReleased() is a list of InputBuffer objects, each of which
+ *   has the following members:
+ *
+ *     uint64_t frameIndex
+ *     uint32_t arrayIndex
+ *
+ * When a tracked buffer associated to the triple (listener, frameIndex,
+ * bufferIndex) goes out of scope, listener->onInputBuffersReleased() will be
+ * called with an InputBuffer object whose members are set as follows:
+ *
+ *     inputBuffer.frameIndex = frameIndex
+ *     inputBuffer.arrayIndex = bufferIndex
+ *
+ * IPC Optimization
+ * ----------------
+ *
+ * Since onInputBuffersReleased() is an IPC call, InputBufferManager tries not
+ * to call it too often. Any two calls to the same listener are at least
+ * mNotificationIntervalNs nanoseconds apart, where mNotificationIntervalNs is
+ * configurable via calling setNotificationInterval(). The default value of
+ * mNotificationIntervalNs is kDefaultNotificationInternalNs.
+ *
+ * Public Member Functions
+ * -----------------------
+ *
+ * InputBufferManager is a singleton class. Its only instance is accessible via
+ * the following public functions:
+ *
+ * - registerFrameData(const sp<IComponentListener>& listener,
+ *                     const C2FrameData& input)
+ *
+ * - unregisterFrameData(const sp<IComponentListener>& listener,
+ *                       const C2FrameData& input)
+ *
+ * - unregisterFrameData(const sp<IComponentListener>& listener)
+ *
+ * - setNotificationInterval(nsecs_t notificationIntervalNs)
+ *
+ */
+
+struct InputBufferManager {
+
+    /**
+     * The default value for the time interval between 2 subsequent IPCs.
+     */
+    static constexpr nsecs_t kDefaultNotificationIntervalNs = 1000000; /* 1ms */
+
+    /**
+     * Track all buffers in a C2FrameData object.
+     *
+     * input (C2FrameData) has the following two members that are of interest:
+     *
+     *   C2WorkOrdinal                ordinal
+     *   vector<shared_ptr<C2Buffer>> buffers
+     *
+     * Calling registerFrameData(listener, input) will register multiple
+     * triples (listener, frameIndex, bufferIndex) where frameIndex is equal to
+     * input.ordinal.frameIndex and bufferIndex runs through the indices of
+     * input.buffers such that input.buffers[bufferIndex] is not null.
+     *
+     * This should be called from queue().
+     *
+     * \param listener Listener of death notifications.
+     * \param input Input frame data whose input buffers are to be tracked.
+     */
+    static void registerFrameData(
+            const sp<IComponentListener>& listener,
+            const C2FrameData& input);
+
+    /**
+     * Untrack all buffers in a C2FrameData object.
+     *
+     * Calling unregisterFrameData(listener, input) will unregister and remove
+     * pending notifications for all triples (l, fi, bufferIndex) such that
+     * l = listener and fi = input.ordinal.frameIndex.
+     *
+     * This should be called from onWorkDone() and flush().
+     *
+     * \param listener Previously registered listener.
+     * \param input Previously registered frame data.
+     */
+    static void unregisterFrameData(
+            const wp<IComponentListener>& listener,
+            const C2FrameData& input);
+
+    /**
+     * Untrack all buffers associated to a given listener.
+     *
+     * Calling unregisterFrameData(listener) will unregister and remove
+     * pending notifications for all triples (l, frameIndex, bufferIndex) such
+     * that l = listener.
+     *
+     * This should be called when the component cleans up all input buffers,
+     * i.e., when reset(), release(), stop() or ~Component() is called.
+     *
+     * \param listener Previously registered listener.
+     */
+    static void unregisterFrameData(
+            const wp<IComponentListener>& listener);
+
+    /**
+     * Set the notification interval.
+     *
+     * \param notificationIntervalNs New notification interval, in nanoseconds.
+     */
+    static void setNotificationInterval(nsecs_t notificationIntervalNs);
+
+private:
+    void _registerFrameData(
+            const sp<IComponentListener>& listener,
+            const C2FrameData& input);
+    void _unregisterFrameData(
+            const wp<IComponentListener>& listener,
+            const C2FrameData& input);
+    void _unregisterFrameData(
+            const wp<IComponentListener>& listener);
+    void _setNotificationInterval(nsecs_t notificationIntervalNs);
+
+    // The callback function tied to C2Buffer objects.
+    //
+    // Note: This function assumes that sInstance is the only instance of this
+    //       class.
+    static void onBufferDestroyed(const C2Buffer* buf, void* arg);
+    void _onBufferDestroyed(const C2Buffer* buf, void* arg);
+
+    // Persistent data to be passed as "arg" in onBufferDestroyed().
+    // This is essentially the triple (listener, frameIndex, bufferIndex) plus a
+    // weak pointer to the C2Buffer object.
+    //
+    // Note that the "key" is bufferIndex according to operator<(). This is
+    // designed to work with TrackedBuffersMap defined below.
+    struct TrackedBuffer {
+        wp<IComponentListener> listener;
+        uint64_t frameIndex;
+        size_t bufferIndex;
+        std::weak_ptr<C2Buffer> buffer;
+        TrackedBuffer(const wp<IComponentListener>& listener,
+                      uint64_t frameIndex,
+                      size_t bufferIndex,
+                      const std::shared_ptr<C2Buffer>& buffer)
+              : listener(listener),
+                frameIndex(frameIndex),
+                bufferIndex(bufferIndex),
+                buffer(buffer) {}
+    };
+
+    // Map: listener -> frameIndex -> set<TrackedBuffer*>.
+    // Essentially, this is used to store triples (listener, frameIndex,
+    // bufferIndex) that's searchable by listener and (listener, frameIndex).
+    // However, the value of the innermost map is TrackedBuffer, which also
+    // contains an extra copy of listener and frameIndex. This is needed
+    // because onBufferDestroyed() needs to know listener and frameIndex too.
+    typedef std::map<wp<IComponentListener>,
+                     std::map<uint64_t,
+                              std::set<TrackedBuffer*>>> TrackedBuffersMap;
+
+    // Storage for pending (unsent) death notifications for one listener.
+    // Each pair in member named "indices" are (frameIndex, bufferIndex) from
+    // the (listener, frameIndex, bufferIndex) triple.
+    struct DeathNotifications {
+
+        // The number of pending notifications for this listener.
+        // count may be 0, in which case the DeathNotifications object will
+        // remain valid for only a small period (specified
+        // nanoseconds).
+        size_t count;
+
+        // The timestamp of the most recent callback on this listener. This is
+        // used to guarantee that callbacks do not occur too frequently, and
+        // also to trigger expiration of a DeathNotifications object that has
+        // count = 0.
+        nsecs_t lastSentNs;
+
+        // Map: frameIndex -> vector of bufferIndices
+        // This is essentially a collection of (framdeIndex, bufferIndex).
+        std::map<uint64_t, std::vector<size_t>> indices;
+
+        DeathNotifications(
+                nsecs_t notificationIntervalNs = kDefaultNotificationIntervalNs)
+              : count(0),
+                lastSentNs(systemTime() - notificationIntervalNs),
+                indices() {}
+    };
+
+    // The minimum time period between IPC calls to notify the client about the
+    // destruction of input buffers.
+    std::atomic<nsecs_t> mNotificationIntervalNs{kDefaultNotificationIntervalNs};
+
+    // Mutex for the management of all input buffers.
+    std::mutex mMutex;
+
+    // Cache for all TrackedBuffers.
+    //
+    // Whenever registerOnDestroyNotify() is called, an argument of type
+    // TrackedBuffer is created and stored into this cache.
+    // Whenever unregisterOnDestroyNotify() or onBufferDestroyed() is called,
+    // the TrackedBuffer is removed from this cache.
+    //
+    // mTrackedBuffersMap stores references to TrackedBuffers inside this cache.
+    std::set<TrackedBuffer*> mTrackedBufferCache;
+
+    // Tracked input buffers.
+    TrackedBuffersMap mTrackedBuffersMap;
+
+    // Death notifications to be sent.
+    //
+    // A DeathNotifications object is associated to each listener. An entry in
+    // this map will be removed if its associated DeathNotifications has count =
+    // 0 and lastSentNs < systemTime() - mNotificationIntervalNs.
+    std::map<wp<IComponentListener>, DeathNotifications> mDeathNotifications;
+
+    // Condition variable signaled when an entry is added to mDeathNotifications.
+    std::condition_variable mOnBufferDestroyed;
+
+    // Notify the clients about buffer destructions.
+    // Return false if all destructions have been notified.
+    // Return true and set timeToRetry to the duration to wait for before
+    // retrying if some destructions have not been notified.
+    bool processNotifications(nsecs_t* timeToRetryNs);
+
+    // Main function for the input buffer manager thread.
+    void main();
+
+    // The thread that manages notifications.
+    //
+    // Note: This variable is declared last so its initialization will happen
+    // after all other member variables have been initialized.
+    std::thread mMainThread;
+
+    // Private constructor.
+    InputBufferManager();
+
+    // The only instance of this class.
+    static InputBufferManager& getInstance();
+
+};
+
+}  // namespace utils
+}  // namespace V1_0
+}  // namespace c2
+}  // namespace media
+}  // namespace hardware
+}  // namespace android
+
+#endif  // CODEC2_HIDL_V1_0_UTILS_INPUT_BUFFER_MANAGER_H
+
diff --git a/media/codec2/hal/aidl/include/codec2/aidl/InputSurface.h b/media/codec2/hal/aidl/include/codec2/aidl/InputSurface.h
new file mode 100644
index 0000000..062dcd9
--- /dev/null
+++ b/media/codec2/hal/aidl/include/codec2/aidl/InputSurface.h
@@ -0,0 +1,87 @@
+/*
+ * 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_HIDL_V1_0_UTILS_INPUTSURFACE_H
+#define CODEC2_HIDL_V1_0_UTILS_INPUTSURFACE_H
+
+#include <codec2/hidl/1.0/ComponentStore.h>
+
+#include <android/hardware/graphics/bufferqueue/2.0/IGraphicBufferProducer.h>
+#include <android/hardware/media/c2/1.0/IInputSink.h>
+#include <android/hardware/media/c2/1.0/IInputSurface.h>
+#include <hidl/Status.h>
+#include <media/stagefright/bqhelper/GraphicBufferSource.h>
+
+#include <util/C2InterfaceHelper.h>
+
+namespace android {
+namespace hardware {
+namespace media {
+namespace c2 {
+namespace V1_0 {
+namespace utils {
+
+using ::android::hardware::hidl_handle;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+
+struct InputSurface : public IInputSurface {
+
+    typedef ::android::hardware::graphics::bufferqueue::V2_0::
+            IGraphicBufferProducer HGraphicBufferProducer;
+
+    typedef ::android::
+            GraphicBufferSource GraphicBufferSource;
+
+    virtual Return<sp<HGraphicBufferProducer>> getGraphicBufferProducer() override;
+
+    virtual Return<sp<IConfigurable>> getConfigurable() override;
+
+    virtual Return<void> connect(
+            const sp<IInputSink>& sink,
+            connect_cb _hidl_cb) override;
+
+    InputSurface(
+            const std::shared_ptr<ParameterCache>& cache,
+            const std::shared_ptr<C2ReflectorHelper>& reflector,
+            const sp<HGraphicBufferProducer>& base,
+            const sp<GraphicBufferSource>& source);
+
+protected:
+
+    class Interface;
+    class ConfigurableIntf;
+
+    std::shared_ptr<ParameterCache> mParameterCache;
+    sp<HGraphicBufferProducer> mProducer;
+    sp<GraphicBufferSource> mSource;
+    std::shared_ptr<Interface> mIntf;
+    sp<CachedConfigurable> mConfigurable;
+
+    virtual ~InputSurface() override = default;
+};
+
+}  // namespace utils
+}  // namespace V1_0
+}  // namespace c2
+}  // namespace media
+}  // namespace hardware
+}  // namespace android
+
+#endif  // CODEC2_HIDL_V1_0_UTILS_INPUTSURFACE_H
diff --git a/media/codec2/hal/aidl/include/codec2/aidl/InputSurfaceConnection.h b/media/codec2/hal/aidl/include/codec2/aidl/InputSurfaceConnection.h
new file mode 100644
index 0000000..475ce8b
--- /dev/null
+++ b/media/codec2/hal/aidl/include/codec2/aidl/InputSurfaceConnection.h
@@ -0,0 +1,96 @@
+/*
+ * 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_HIDL_V1_0_UTILS_INPUTSURFACECONNECTION_H
+#define CODEC2_HIDL_V1_0_UTILS_INPUTSURFACECONNECTION_H
+
+#include <codec2/hidl/1.0/Component.h>
+#include <codec2/hidl/1.0/Configurable.h>
+
+#include <android/hardware/media/c2/1.0/IComponent.h>
+#include <android/hardware/media/c2/1.0/IConfigurable.h>
+#include <android/hardware/media/c2/1.0/IInputSurfaceConnection.h>
+
+#include <media/stagefright/bqhelper/GraphicBufferSource.h>
+
+#include <hidl/HidlSupport.h>
+#include <hidl/Status.h>
+
+#include <C2Component.h>
+
+#include <memory>
+#include <mutex>
+
+namespace android {
+namespace hardware {
+namespace media {
+namespace c2 {
+namespace V1_0 {
+namespace utils {
+
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+using ::android::GraphicBufferSource;
+
+// An InputSurfaceConnection connects an InputSurface to a sink, which may be an
+// IInputSink or a local C2Component. This can be specified by choosing the
+// corresponding constructor. The reason for distinguishing these two cases is
+// that when an InputSurfaceConnection lives in the same process as the
+// component that processes the buffers, data parceling is not needed.
+struct InputSurfaceConnection : public IInputSurfaceConnection {
+
+    virtual Return<Status> disconnect() override;
+
+    virtual Return<sp<IConfigurable>> getConfigurable() override;
+
+protected:
+
+    InputSurfaceConnection(
+            const sp<GraphicBufferSource>& source,
+            const std::shared_ptr<C2Component>& comp,
+            const std::shared_ptr<ParameterCache>& cache);
+
+    InputSurfaceConnection(
+            const sp<GraphicBufferSource>& source,
+            const sp<IInputSink>& sink,
+            const std::shared_ptr<ParameterCache>& cache);
+
+    bool init();
+
+    friend struct InputSurface;
+
+    InputSurfaceConnection() = delete;
+    InputSurfaceConnection(const InputSurfaceConnection&) = delete;
+    void operator=(const InputSurfaceConnection&) = delete;
+
+    struct Impl;
+
+    std::mutex mImplMutex;
+    sp<Impl> mImpl;
+    sp<CachedConfigurable> mConfigurable;
+
+    virtual ~InputSurfaceConnection() override;
+};
+
+}  // namespace utils
+}  // namespace V1_0
+}  // namespace c2
+}  // namespace media
+}  // namespace hardware
+}  // namespace android
+
+#endif  // CODEC2_HIDL_V1_0_UTILS_INPUTSURFACECONNECTION_H
diff --git a/media/codec2/hal/aidl/include/codec2/aidl/ParamTypes.h b/media/codec2/hal/aidl/include/codec2/aidl/ParamTypes.h
index ff69039..3f82ee3 100644
--- a/media/codec2/hal/aidl/include/codec2/aidl/ParamTypes.h
+++ b/media/codec2/hal/aidl/include/codec2/aidl/ParamTypes.h
@@ -37,11 +37,14 @@
 namespace c2 {
 namespace utils {
 
+// Returns true iff AIDL c2 HAL is enabled
+bool IsEnabled();
+
 // Make asString() and operator<< work with Status as well as c2_status_t.
 C2_DECLARE_AS_STRING_AND_DEFINE_STREAM_OUT(Status);
 
 /**
- * All objcpy() functions will return a boolean value indicating whether the
+ * All To/FromAidl() functions will return a boolean value indicating whether the
  * conversion succeeds or not.
  */
 
diff --git a/media/codec2/hal/client/Android.bp b/media/codec2/hal/client/Android.bp
index 7a0525b..22aa35e 100644
--- a/media/codec2/hal/client/Android.bp
+++ b/media/codec2/hal/client/Android.bp
@@ -28,6 +28,10 @@
         "output.cpp",
     ],
 
+    defaults: [
+        "libcodec2-aidl-client-defaults",
+    ],
+
     header_libs: [
         "libcodec2_internal", // private
     ],
@@ -38,6 +42,7 @@
         "android.hardware.media.c2@1.0",
         "android.hardware.media.c2@1.1",
         "android.hardware.media.c2@1.2",
+        "android.hardware.media.bufferpool2-V1-ndk",
         "android.hardware.media.c2-V1-ndk",
         "libbase",
         "libbinder",
@@ -52,11 +57,16 @@
         "libhidlbase",
         "liblog",
         "libnativewindow",
+        "libstagefright_aidl_bufferpool2",
         "libstagefright_bufferpool@2.0.1",
         "libui",
         "libutils",
     ],
 
+    static_libs: [
+        "libaidlcommonsupport",
+    ],
+
     export_include_dirs: [
         "include",
     ],
diff --git a/media/codec2/hal/client/client.cpp b/media/codec2/hal/client/client.cpp
index 9a4b385..b680931 100644
--- a/media/codec2/hal/client/client.cpp
+++ b/media/codec2/hal/client/client.cpp
@@ -25,7 +25,6 @@
 #include <C2Config.h> // for C2StreamUsageTuning
 #include <C2PlatformSupport.h>
 
-#include <android/binder_auto_utils.h>
 #include <android/hardware/media/bufferpool/2.0/IClientManager.h>
 #include <android/hardware/media/c2/1.0/IComponent.h>
 #include <android/hardware/media/c2/1.0/IComponentInterface.h>
@@ -34,6 +33,8 @@
 #include <android/hardware/media/c2/1.0/IConfigurable.h>
 #include <android/hidl/manager/1.2/IServiceManager.h>
 
+#include <aidl/android/hardware/media/bufferpool2/IClientManager.h>
+#include <aidl/android/hardware/media/c2/BnComponentListener.h>
 #include <aidl/android/hardware/media/c2/FieldSupportedValues.h>
 #include <aidl/android/hardware/media/c2/FieldSupportedValuesQuery.h>
 #include <aidl/android/hardware/media/c2/FieldSupportedValuesQueryResult.h>
@@ -42,9 +43,18 @@
 #include <aidl/android/hardware/media/c2/IComponentStore.h>
 #include <aidl/android/hardware/media/c2/IConfigurable.h>
 #include <aidl/android/hardware/media/c2/ParamDescriptor.h>
+#include <aidl/android/hardware/media/c2/StructDescriptor.h>
 
+#include <aidlcommonsupport/NativeHandle.h>
+#include <android/binder_auto_utils.h>
+#include <android/binder_ibinder.h>
+#include <android/binder_manager.h>
 #include <android-base/properties.h>
+#include <android-base/stringprintf.h>
 #include <bufferpool/ClientManager.h>
+#include <bufferpool2/ClientManager.h>
+#include <codec2/aidl/BufferTypes.h>
+#include <codec2/aidl/ParamTypes.h>
 #include <codec2/hidl/1.0/types.h>
 #include <codec2/hidl/1.1/types.h>
 #include <codec2/hidl/1.2/types.h>
@@ -85,6 +95,7 @@
         V2_0::utils::H2BGraphicBufferProducer;
 using ::android::hardware::media::c2::V1_2::SurfaceSyncObj;
 
+namespace bufferpool2_aidl = ::aidl::android::hardware::media::bufferpool2;
 namespace bufferpool_hidl = ::android::hardware::media::bufferpool::V2_0;
 namespace c2_aidl = ::aidl::android::hardware::media::c2;
 namespace c2_hidl_base = ::android::hardware::media::c2;
@@ -178,6 +189,20 @@
     }
 };
 
+c2_status_t GetC2Status(const ::ndk::ScopedAStatus &transStatus, const char *method) {
+    if (!transStatus.isOk()) {
+        if (transStatus.getExceptionCode() == EX_SERVICE_SPECIFIC) {
+            c2_status_t status = static_cast<c2_status_t>(transStatus.getServiceSpecificError());
+            LOG(DEBUG) << method << " -- call failed: " << status << ".";
+            return status;
+        } else {
+            LOG(ERROR) << method << " -- transaction failed.";
+            return C2_TRANSACTION_FAILED;
+        }
+    }
+    return C2_OK;
+}
+
 }  // unnamed namespace
 
 // This class caches a Codec2Client object and its component traits. The client
@@ -585,33 +610,174 @@
         const std::vector<C2Param::Index> &heapParamIndices,
         c2_blocking_t mayBlock,
         std::vector<std::unique_ptr<C2Param>>* const heapParams) const {
-    (void)stackParams, (void)heapParamIndices, (void)mayBlock, (void)heapParams;
-    // TODO: implementation
-    return C2_OMITTED;
+    std::vector<int> indices(
+            stackParams.size() + heapParamIndices.size());
+    size_t numIndices = 0;
+    for (C2Param* const& stackParam : stackParams) {
+        if (!stackParam) {
+            LOG(WARNING) << "query -- null stack param encountered.";
+            continue;
+        }
+        indices[numIndices++] = int(stackParam->index());
+    }
+    size_t numStackIndices = numIndices;
+    for (const C2Param::Index& index : heapParamIndices) {
+        indices[numIndices++] = int(static_cast<uint32_t>(index));
+    }
+    indices.resize(numIndices);
+    if (heapParams) {
+        heapParams->reserve(heapParams->size() + numIndices);
+    }
+    c2_aidl::Params result;
+    ndk::ScopedAStatus transStatus = mBase->query(indices, (mayBlock == C2_MAY_BLOCK), &result);
+    c2_status_t status = GetC2Status(transStatus, "query");
+    if (status != C2_OK) {
+        return status;
+    }
+
+    std::vector<C2Param*> paramPointers;
+    if (!c2_aidl::utils::ParseParamsBlob(&paramPointers, result)) {
+        LOG(ERROR) << "query -- error while parsing params.";
+        return C2_CORRUPTED;
+    }
+    size_t i = 0;
+    for (auto it = paramPointers.begin();
+            it != paramPointers.end(); ) {
+        C2Param* paramPointer = *it;
+        if (numStackIndices > 0) {
+            --numStackIndices;
+            if (!paramPointer) {
+                LOG(DEBUG) << "query -- null stack param.";
+                ++it;
+                continue;
+            }
+            for (; i < stackParams.size() && !stackParams[i]; ) {
+                ++i;
+            }
+            if (i >= stackParams.size()) {
+                LOG(ERROR) << "query -- unexpected error.";
+                status = C2_CORRUPTED;
+                break;
+            }
+            if (stackParams[i]->index() != paramPointer->index()) {
+                LOG(DEBUG) << "query -- param skipped: "
+                              "index = "
+                           << stackParams[i]->index() << ".";
+                stackParams[i++]->invalidate();
+                // this means that the param could not be queried.
+                // signalling C2_BAD_INDEX to the client.
+                status = C2_BAD_INDEX;
+                continue;
+            }
+            if (!stackParams[i++]->updateFrom(*paramPointer)) {
+                LOG(WARNING) << "query -- param update failed: "
+                                "index = "
+                             << paramPointer->index() << ".";
+            }
+        } else {
+            if (!paramPointer) {
+                LOG(DEBUG) << "query -- null heap param.";
+                ++it;
+                continue;
+            }
+            if (!heapParams) {
+                LOG(WARNING) << "query -- "
+                                "unexpected extra stack param.";
+            } else {
+                heapParams->emplace_back(C2Param::Copy(*paramPointer));
+            }
+        }
+        ++it;
+    }
+    return status;
 }
 
 c2_status_t Codec2ConfigurableClient::AidlImpl::config(
         const std::vector<C2Param*> &params,
         c2_blocking_t mayBlock,
         std::vector<std::unique_ptr<C2SettingResult>>* const failures) {
-    (void)params, (void)mayBlock, (void)failures;
-    // TODO: implementation
-    return C2_OMITTED;
+    c2_aidl::Params aidlParams;
+    if (!c2_aidl::utils::CreateParamsBlob(&aidlParams, params)) {
+        LOG(ERROR) << "config -- bad input.";
+        return C2_TRANSACTION_FAILED;
+    }
+    c2_aidl::IConfigurable::ConfigResult result;
+    ndk::ScopedAStatus transStatus = mBase->config(aidlParams, (mayBlock == C2_MAY_BLOCK), &result);
+    c2_status_t status = GetC2Status(transStatus, "config");
+    if (status != C2_OK) {
+        return status;
+    }
+    size_t i = failures->size();
+    failures->resize(i + result.failures.size());
+    for (const c2_aidl::SettingResult& sf : result.failures) {
+        if (!c2_aidl::utils::FromAidl(&(*failures)[i++], sf)) {
+            LOG(ERROR) << "config -- invalid SettingResult returned.";
+            return C2_CORRUPTED;
+        }
+    }
+    if (!c2_aidl::utils::UpdateParamsFromBlob(params, result.params)) {
+        LOG(ERROR) << "config -- "
+                   << "failed to parse returned params.";
+        status = C2_CORRUPTED;
+    }
+    return status;
 }
 
 c2_status_t Codec2ConfigurableClient::AidlImpl::querySupportedParams(
         std::vector<std::shared_ptr<C2ParamDescriptor>>* const params) const {
-    (void)params;
-    // TODO: implementation
-    return C2_OMITTED;
+    // TODO: Cache and query properly!
+    std::vector<c2_aidl::ParamDescriptor> result;
+    ndk::ScopedAStatus transStatus = mBase->querySupportedParams(
+            std::numeric_limits<uint32_t>::min(),
+            std::numeric_limits<uint32_t>::max(),
+            &result);
+    c2_status_t status = GetC2Status(transStatus, "querySupportedParams");
+    if (status != C2_OK) {
+        return status;
+    }
+    size_t i = params->size();
+    params->resize(i + result.size());
+    for (const c2_aidl::ParamDescriptor& sp : result) {
+        if (!c2_aidl::utils::FromAidl(&(*params)[i++], sp)) {
+            LOG(ERROR) << "querySupportedParams -- invalid returned ParamDescriptor.";
+            return C2_CORRUPTED;
+        }
+    }
+    return status;
 }
 
 c2_status_t Codec2ConfigurableClient::AidlImpl::querySupportedValues(
         std::vector<C2FieldSupportedValuesQuery>& fields,
         c2_blocking_t mayBlock) const {
-    (void)fields, (void)mayBlock;
-    // TODO: implementation
-    return C2_OMITTED;
+    std::vector<c2_aidl::FieldSupportedValuesQuery> inFields(fields.size());
+    for (size_t i = 0; i < fields.size(); ++i) {
+        if (!c2_aidl::utils::ToAidl(&inFields[i], fields[i])) {
+            LOG(ERROR) << "querySupportedValues -- bad input";
+            return C2_TRANSACTION_FAILED;
+        }
+    }
+
+    std::vector<c2_aidl::FieldSupportedValuesQueryResult> result;
+    ndk::ScopedAStatus transStatus = mBase->querySupportedValues(
+            inFields, (mayBlock == C2_MAY_BLOCK), &result);
+    c2_status_t status = GetC2Status(transStatus, "querySupportedValues");
+    if (status != C2_OK) {
+        return status;
+    }
+    if (result.size() != fields.size()) {
+        LOG(ERROR) << "querySupportedValues -- "
+                      "input and output lists "
+                      "have different sizes.";
+        return C2_CORRUPTED;
+    }
+    for (size_t i = 0; i < fields.size(); ++i) {
+        if (!c2_aidl::utils::FromAidl(&fields[i], inFields[i], result[i])) {
+            LOG(ERROR) << "querySupportedValues -- "
+                          "invalid returned value.";
+            return C2_CORRUPTED;
+        }
+    }
+    return status;
 }
 
 // Codec2ConfigurableClient
@@ -753,14 +919,119 @@
 
 };
 
-// Codec2Client::Component::BufferPoolSender
-struct Codec2Client::Component::BufferPoolSender :
+// Codec2Client::Component::AidlListener
+struct Codec2Client::Component::AidlListener : public c2_aidl::BnComponentListener {
+    std::weak_ptr<Component> component;
+    std::weak_ptr<Listener> base;
+
+    virtual ::ndk::ScopedAStatus onWorkDone(const c2_aidl::WorkBundle& workBundle) override {
+        std::list<std::unique_ptr<C2Work>> workItems;
+        if (!c2_aidl::utils::FromAidl(&workItems, workBundle)) {
+            LOG(DEBUG) << "onWorkDone -- received corrupted WorkBundle.";
+            return ::ndk::ScopedAStatus::ok();
+        }
+        // release input buffers potentially held by the component from queue
+        std::shared_ptr<Codec2Client::Component> strongComponent =
+                component.lock();
+        if (strongComponent) {
+            strongComponent->handleOnWorkDone(workItems);
+        }
+        if (std::shared_ptr<Codec2Client::Listener> listener = base.lock()) {
+            listener->onWorkDone(component, workItems);
+        } else {
+            LOG(DEBUG) << "onWorkDone -- listener died.";
+        }
+        return ::ndk::ScopedAStatus::ok();
+    }
+
+    virtual ::ndk::ScopedAStatus onTripped(
+            const std::vector<c2_aidl::SettingResult>& settingResults) override {
+        std::vector<std::shared_ptr<C2SettingResult>> c2SettingResults(
+                settingResults.size());
+        for (size_t i = 0; i < settingResults.size(); ++i) {
+            std::unique_ptr<C2SettingResult> c2SettingResult;
+            if (!c2_aidl::utils::FromAidl(&c2SettingResult, settingResults[i])) {
+                LOG(DEBUG) << "onTripped -- received corrupted SettingResult.";
+                return ::ndk::ScopedAStatus::ok();
+            }
+            c2SettingResults[i] = std::move(c2SettingResult);
+        }
+        if (std::shared_ptr<Codec2Client::Listener> listener = base.lock()) {
+            listener->onTripped(component, c2SettingResults);
+        } else {
+            LOG(DEBUG) << "onTripped -- listener died.";
+        }
+        return ::ndk::ScopedAStatus::ok();
+    }
+
+    virtual ::ndk::ScopedAStatus onError(const c2_aidl::Status &s, int32_t errorCode) override {
+        LOG(DEBUG) << "onError --"
+                   << " status = " << s.status
+                   << ", errorCode = " << errorCode
+                   << ".";
+        if (std::shared_ptr<Listener> listener = base.lock()) {
+            listener->onError(component, s.status == c2_aidl::Status::OK ?
+                    errorCode : static_cast<c2_status_t>(s.status));
+        } else {
+            LOG(DEBUG) << "onError -- listener died.";
+        }
+        return ::ndk::ScopedAStatus::ok();
+    }
+
+    virtual ::ndk::ScopedAStatus onFramesRendered(
+            const std::vector<RenderedFrame>& renderedFrames) override {
+        std::shared_ptr<Listener> listener = base.lock();
+        if (!listener) {
+            LOG(DEBUG) << "onFramesRendered -- listener died.";
+            return ::ndk::ScopedAStatus::ok();
+        }
+        for (const RenderedFrame& renderedFrame : renderedFrames) {
+            listener->onFrameRendered(
+                    renderedFrame.bufferQueueId,
+                    renderedFrame.slotId,
+                    renderedFrame.timestampNs);
+        }
+        return ::ndk::ScopedAStatus::ok();
+    }
+
+    virtual ::ndk::ScopedAStatus onInputBuffersReleased(
+            const std::vector<InputBuffer>& inputBuffers) override {
+        std::shared_ptr<Listener> listener = base.lock();
+        if (!listener) {
+            LOG(DEBUG) << "onInputBuffersReleased -- listener died.";
+            return ::ndk::ScopedAStatus::ok();
+        }
+        for (const InputBuffer& inputBuffer : inputBuffers) {
+            LOG(VERBOSE) << "onInputBuffersReleased --"
+                            " received death notification of"
+                            " input buffer:"
+                            " frameIndex = " << inputBuffer.frameIndex
+                         << ", bufferIndex = " << inputBuffer.arrayIndex
+                         << ".";
+            listener->onInputBufferDone(
+                    inputBuffer.frameIndex, inputBuffer.arrayIndex);
+        }
+        return ::ndk::ScopedAStatus::ok();
+    }
+
+};
+
+// Codec2Client::Component::HidlBufferPoolSender
+struct Codec2Client::Component::HidlBufferPoolSender :
         hardware::media::c2::V1_1::utils::DefaultBufferPoolSender {
-    BufferPoolSender()
+    HidlBufferPoolSender()
           : hardware::media::c2::V1_1::utils::DefaultBufferPoolSender() {
     }
 };
 
+// Codec2Client::Component::AidlBufferPoolSender
+struct Codec2Client::Component::AidlBufferPoolSender :
+        c2_aidl::utils::DefaultBufferPoolSender {
+    AidlBufferPoolSender()
+          : c2_aidl::utils::DefaultBufferPoolSender() {
+    }
+};
+
 // Codec2Client::Component::OutputBufferQueue
 struct Codec2Client::Component::OutputBufferQueue :
         hardware::media::c2::OutputBufferQueue {
@@ -770,36 +1041,53 @@
 };
 
 // Codec2Client
-Codec2Client::Codec2Client(sp<Base> const& base,
+Codec2Client::Codec2Client(sp<HidlBase> const& base,
                            sp<c2_hidl::IConfigurable> const& configurable,
                            size_t serviceIndex)
       : Configurable{configurable},
-        mBase1_0{base},
-        mBase1_1{Base1_1::castFrom(base)},
-        mBase1_2{Base1_2::castFrom(base)},
+        mHidlBase1_0{base},
+        mHidlBase1_1{HidlBase1_1::castFrom(base)},
+        mHidlBase1_2{HidlBase1_2::castFrom(base)},
         mServiceIndex{serviceIndex} {
     Return<sp<bufferpool_hidl::IClientManager>> transResult = base->getPoolClientManager();
     if (!transResult.isOk()) {
         LOG(ERROR) << "getPoolClientManager -- transaction failed.";
     } else {
-        mHostPoolManager = static_cast<sp<bufferpool_hidl::IClientManager>>(transResult);
+        mHidlHostPoolManager = static_cast<sp<bufferpool_hidl::IClientManager>>(transResult);
     }
 }
 
-sp<Codec2Client::Base> const& Codec2Client::getBase() const {
-    return mBase1_0;
+Codec2Client::Codec2Client(std::shared_ptr<AidlBase> const& base,
+                           std::shared_ptr<c2_aidl::IConfigurable> const& configurable,
+                           size_t serviceIndex)
+      : Configurable{configurable},
+        mAidlBase{base},
+        mServiceIndex{serviceIndex} {
+    ::ndk::ScopedAStatus transStatus = base->getPoolClientManager(&mAidlHostPoolManager);
+    if (!transStatus.isOk()) {
+        LOG(ERROR) << "getPoolClientManager -- transaction failed.";
+        mAidlHostPoolManager.reset();
+    }
 }
 
-sp<Codec2Client::Base1_0> const& Codec2Client::getBase1_0() const {
-    return mBase1_0;
+sp<Codec2Client::HidlBase> const& Codec2Client::getHidlBase() const {
+    return mHidlBase1_0;
 }
 
-sp<Codec2Client::Base1_1> const& Codec2Client::getBase1_1() const {
-    return mBase1_1;
+sp<Codec2Client::HidlBase1_0> const& Codec2Client::getHidlBase1_0() const {
+    return mHidlBase1_0;
 }
 
-sp<Codec2Client::Base1_2> const& Codec2Client::getBase1_2() const {
-    return mBase1_2;
+sp<Codec2Client::HidlBase1_1> const& Codec2Client::getHidlBase1_1() const {
+    return mHidlBase1_1;
+}
+
+sp<Codec2Client::HidlBase1_2> const& Codec2Client::getHidlBase1_2() const {
+    return mHidlBase1_2;
+}
+
+::ndk::SpAIBinder Codec2Client::getAidlBase() const {
+    return mAidlBase ? mAidlBase->asBinder() : nullptr;
 }
 
 std::string const& Codec2Client::getServiceName() const {
@@ -810,13 +1098,41 @@
         const C2String& name,
         const std::shared_ptr<Codec2Client::Listener>& listener,
         std::shared_ptr<Codec2Client::Component>* const component) {
+    if (mAidlBase) {
+        std::shared_ptr<Component::AidlListener> aidlListener =
+                Component::AidlListener::make<Component::AidlListener>();
+        aidlListener->base = listener;
+        std::shared_ptr<c2_aidl::IComponent> aidlComponent;
+        ::ndk::ScopedAStatus transStatus = mAidlBase->createComponent(
+                name,
+                aidlListener,
+                bufferpool2_aidl::implementation::ClientManager::getInstance(),
+                &aidlComponent);
+        c2_status_t status = GetC2Status(transStatus, "createComponent");
+        if (status != C2_OK) {
+            return status;
+        } else if (!aidlComponent) {
+            LOG(ERROR) << "createComponent(" << name.c_str()
+                       << ") -- null component.";
+            return C2_CORRUPTED;
+        }
+        *component = std::make_shared<Codec2Client::Component>(aidlComponent);
+        status = (*component)->setDeathListener((*component), listener);
+        if (status != C2_OK) {
+            LOG(ERROR) << "createComponent(" << name.c_str()
+                       << ") -- failed to set up death listener: "
+                       << status << ".";
+        }
+        (*component)->mAidlBufferPoolSender->setReceiver(mAidlHostPoolManager);
+        return status;
+    }
 
     c2_status_t status;
     sp<Component::HidlListener> hidlListener = new Component::HidlListener{};
     hidlListener->base = listener;
     Return<void> transStatus;
-    if (mBase1_2) {
-        transStatus = mBase1_2->createComponent_1_2(
+    if (mHidlBase1_2) {
+        transStatus = mHidlBase1_2->createComponent_1_2(
             name,
             hidlListener,
             bufferpool_hidl::implementation::ClientManager::getInstance(),
@@ -831,8 +1147,8 @@
                 hidlListener->component = *component;
             });
     }
-    else if (mBase1_1) {
-        transStatus = mBase1_1->createComponent_1_1(
+    else if (mHidlBase1_1) {
+        transStatus = mHidlBase1_1->createComponent_1_1(
             name,
             hidlListener,
             bufferpool_hidl::implementation::ClientManager::getInstance(),
@@ -846,8 +1162,8 @@
                 *component = std::make_shared<Codec2Client::Component>(c);
                 hidlListener->component = *component;
             });
-    } else if (mBase1_0) { // ver1_0
-        transStatus = mBase1_0->createComponent(
+    } else if (mHidlBase1_0) { // ver1_0
+        transStatus = mHidlBase1_0->createComponent(
             name,
             hidlListener,
             bufferpool_hidl::implementation::ClientManager::getInstance(),
@@ -890,15 +1206,32 @@
                    << status << ".";
     }
 
-    (*component)->mBufferPoolSender->setReceiver(mHostPoolManager);
+    (*component)->mHidlBufferPoolSender->setReceiver(mHidlHostPoolManager);
     return status;
 }
 
 c2_status_t Codec2Client::createInterface(
         const C2String& name,
         std::shared_ptr<Codec2Client::Interface>* const interface) {
+    if (mAidlBase) {
+        std::shared_ptr<c2_aidl::IComponentInterface> aidlInterface;
+        ::ndk::ScopedAStatus transStatus = mAidlBase->createInterface(
+                name,
+                &aidlInterface);
+        c2_status_t status = GetC2Status(transStatus, "createInterface");
+        if (status != C2_OK) {
+            return status;
+        } else if (!aidlInterface) {
+            LOG(ERROR) << "createInterface(" << name.c_str()
+                       << ") -- null interface.";
+            return C2_CORRUPTED;
+        }
+        interface->reset(new Codec2Client::Interface(aidlInterface));
+        return C2_OK;
+    }
+
     c2_status_t status;
-    Return<void> transStatus = mBase1_0->createInterface(
+    Return<void> transStatus = mHidlBase1_0->createInterface(
             name,
             [&status, interface](
                     c2_hidl::Status s,
@@ -929,8 +1262,13 @@
 
 c2_status_t Codec2Client::createInputSurface(
         std::shared_ptr<InputSurface>* const inputSurface) {
+    if (mAidlBase) {
+        // FIXME
+        return C2_OMITTED;
+    }
+
     c2_status_t status;
-    Return<void> transStatus = mBase1_0->createInputSurface(
+    Return<void> transStatus = mHidlBase1_0->createInputSurface(
             [&status, inputSurface](
                     c2_hidl::Status s,
                     const sp<c2_hidl::IInputSurface>& i) {
@@ -958,7 +1296,29 @@
         bool* success) const {
     std::vector<C2Component::Traits> traits;
     std::string const& serviceName = getServiceName();
-    Return<void> transStatus = mBase1_0->listComponents(
+
+    if (mAidlBase) {
+        std::vector<c2_aidl::IComponentStore::ComponentTraits> aidlTraits;
+        ::ndk::ScopedAStatus transStatus = mAidlBase->listComponents(&aidlTraits);
+        if (!transStatus.isOk()) {
+            LOG(ERROR) << "_listComponents -- transaction failed.";
+            *success = false;
+        } else {
+            traits.resize(aidlTraits.size());
+            *success = true;
+            for (size_t i = 0; i < aidlTraits.size(); ++i) {
+                if (!c2_aidl::utils::FromAidl(&traits[i], aidlTraits[i])) {
+                    LOG(ERROR) << "_listComponents -- corrupted output.";
+                    *success = false;
+                    traits.clear();
+                    break;
+                }
+                traits[i].owner = serviceName;
+            }
+        }
+        return traits;
+    }
+    Return<void> transStatus = mHidlBase1_0->listComponents(
             [&traits, &serviceName](c2_hidl::Status s,
                    const hidl_vec<c2_hidl::IComponentStore::ComponentTraits>& t) {
                 if (s != c2_hidl::Status::OK) {
@@ -994,12 +1354,12 @@
     return C2_OMITTED;
 }
 
-std::shared_ptr<C2ParamReflector>
-        Codec2Client::getParamReflector() {
+std::shared_ptr<C2ParamReflector> Codec2Client::getParamReflector() {
     // TODO: this is not meant to be exposed as C2ParamReflector on the client side; instead, it
     // should reflect the HAL API.
-    struct SimpleParamReflector : public C2ParamReflector {
-        virtual std::unique_ptr<C2StructDescriptor> describe(C2Param::CoreIndex coreIndex) const {
+    struct HidlSimpleParamReflector : public C2ParamReflector {
+        std::unique_ptr<C2StructDescriptor> describe(
+                C2Param::CoreIndex coreIndex) const override {
             hidl_vec<c2_hidl::ParamIndex> indices(1);
             indices[0] = static_cast<c2_hidl::ParamIndex>(coreIndex.coreIndex());
             std::unique_ptr<C2StructDescriptor> descriptor;
@@ -1041,80 +1401,112 @@
             return descriptor;
         }
 
-        SimpleParamReflector(sp<Base> base)
+        HidlSimpleParamReflector(sp<HidlBase> base)
             : mBase(base) { }
 
-        sp<Base> mBase;
+        sp<HidlBase> mBase;
+    };
+    struct AidlSimpleParamReflector : public C2ParamReflector {
+        std::unique_ptr<C2StructDescriptor> describe(
+                C2Param::CoreIndex coreIndex) const override {
+            std::vector<c2_aidl::StructDescriptor> aidlDesc;
+            std::unique_ptr<C2StructDescriptor> descriptor;
+            ::ndk::ScopedAStatus transStatus = mBase->getStructDescriptors(
+                    {int32_t(coreIndex.coreIndex())},
+                    &aidlDesc);
+            c2_status_t status = GetC2Status(transStatus, "describe");
+            if (status != C2_OK) {
+                descriptor.reset();
+            } else if (!c2_aidl::utils::FromAidl(&descriptor, aidlDesc[0])) {
+                LOG(ERROR) << "describe -- conversion failed.";
+                descriptor.reset();
+            }
+            return descriptor;
+        }
+
+        AidlSimpleParamReflector(const std::shared_ptr<AidlBase> &base)
+            : mBase(base) { }
+
+        std::shared_ptr<AidlBase> mBase;
     };
 
-    return std::make_shared<SimpleParamReflector>(mBase1_0);
+    if (mAidlBase) {
+        return std::make_shared<AidlSimpleParamReflector>(mAidlBase);
+    }
+    return std::make_shared<HidlSimpleParamReflector>(mHidlBase1_0);
 };
 
-std::vector<std::string> const& Codec2Client::GetServiceNames() {
-    static std::vector<std::string> sServiceNames{[]() {
-        using ::android::hardware::media::c2::V1_0::IComponentStore;
-        using ::android::hidl::manager::V1_2::IServiceManager;
+std::vector<std::string> Codec2Client::CacheServiceNames() {
+    std::vector<std::string> names;
 
-        while (true) {
-            sp<IServiceManager> serviceManager = IServiceManager::getService();
-            CHECK(serviceManager) << "Hardware service manager is not running.";
+    if (c2_aidl::utils::IsEnabled()) {
+        // Get AIDL service names
+        AServiceManager_forEachDeclaredInstance(
+                AidlBase::descriptor, &names, [](const char *name, void *context) {
+                    std::vector<std::string> *names = (std::vector<std::string> *)context;
+                    names->emplace_back(name);
+                });
+    }
 
-            // There are three categories of services based on names.
-            std::vector<std::string> defaultNames; // Prefixed with "default"
-            std::vector<std::string> vendorNames;  // Prefixed with "vendor"
-            std::vector<std::string> otherNames;   // Others
-            Return<void> transResult;
-            transResult = serviceManager->listManifestByInterface(
-                    IComponentStore::descriptor,
-                    [&defaultNames, &vendorNames, &otherNames](
-                            hidl_vec<hidl_string> const& instanceNames) {
-                        for (hidl_string const& instanceName : instanceNames) {
-                            char const* name = instanceName.c_str();
-                            if (strncmp(name, "default", 7) == 0) {
-                                defaultNames.emplace_back(name);
-                            } else if (strncmp(name, "vendor", 6) == 0) {
-                                vendorNames.emplace_back(name);
-                            } else {
-                                otherNames.emplace_back(name);
-                            }
-                        }
-                    });
-            if (transResult.isOk()) {
-                // Sort service names in each category.
-                std::sort(defaultNames.begin(), defaultNames.end());
-                std::sort(vendorNames.begin(), vendorNames.end());
-                std::sort(otherNames.begin(), otherNames.end());
+    // Get HIDL service names
+    using ::android::hardware::media::c2::V1_0::IComponentStore;
+    using ::android::hidl::manager::V1_2::IServiceManager;
+    while (true) {
+        sp<IServiceManager> serviceManager = IServiceManager::getService();
+        CHECK(serviceManager) << "Hardware service manager is not running.";
 
-                // Concatenate the three lists in this order: default, vendor,
-                // other.
-                std::vector<std::string>& names = defaultNames;
-                names.reserve(names.size() + vendorNames.size() + otherNames.size());
-                names.insert(names.end(),
-                             std::make_move_iterator(vendorNames.begin()),
-                             std::make_move_iterator(vendorNames.end()));
-                names.insert(names.end(),
-                             std::make_move_iterator(otherNames.begin()),
-                             std::make_move_iterator(otherNames.end()));
-
-                // Summarize to logcat.
-                if (names.empty()) {
-                    LOG(INFO) << "No Codec2 services declared in the manifest.";
-                } else {
-                    std::stringstream stringOutput;
-                    stringOutput << "Available Codec2 services:";
-                    for (std::string const& name : names) {
-                        stringOutput << " \"" << name << "\"";
-                    }
-                    LOG(INFO) << stringOutput.str();
-                }
-
-                return names;
-            }
-            LOG(ERROR) << "Could not retrieve the list of service instances of "
-                       << IComponentStore::descriptor
-                       << ". Retrying...";
+        Return<void> transResult;
+        transResult = serviceManager->listManifestByInterface(
+                IComponentStore::descriptor,
+                [&names](
+                        hidl_vec<hidl_string> const& instanceNames) {
+                    names.insert(names.end(), instanceNames.begin(), instanceNames.end());
+                });
+        if (transResult.isOk()) {
+            break;
         }
-    }()};
+        LOG(ERROR) << "Could not retrieve the list of service instances of "
+                   << IComponentStore::descriptor
+                   << ". Retrying...";
+    }
+    // Sort service names in each category.
+    std::stable_sort(
+        names.begin(), names.end(),
+        [](const std::string &a, const std::string &b) {
+            // First compare by prefix: default -> vendor -> {everything else}
+            constexpr int DEFAULT = 1;
+            constexpr int VENDOR = 2;
+            constexpr int OTHER = 3;
+            int aPrefix = ((a.compare(0, 7, "default") == 0) ? DEFAULT :
+                           (a.compare(0, 6, "vendor") == 0) ? VENDOR :
+                           OTHER);
+            int bPrefix = ((b.compare(0, 7, "default") == 0) ? DEFAULT :
+                           (b.compare(0, 6, "vendor") == 0) ? VENDOR :
+                           OTHER);
+            if (aPrefix != bPrefix) {
+                return aPrefix < bPrefix;
+            }
+            // If the prefix is the same, compare alphabetically
+            return a < b;
+        });
+
+    // Summarize to logcat.
+    if (names.empty()) {
+        LOG(INFO) << "No Codec2 services declared in the manifest.";
+    } else {
+        std::stringstream stringOutput;
+        stringOutput << "Available Codec2 services:";
+        for (std::string const& name : names) {
+            stringOutput << " \"" << name << "\"";
+        }
+        LOG(INFO) << stringOutput.str();
+    }
+
+    return names;
+}
+
+std::vector<std::string> const& Codec2Client::GetServiceNames() {
+    static std::vector<std::string> sServiceNames = CacheServiceNames();
     return sServiceNames;
 }
 
@@ -1153,14 +1545,34 @@
 std::shared_ptr<Codec2Client> Codec2Client::_CreateFromIndex(size_t index) {
     std::string const& name = GetServiceNames()[index];
     LOG(VERBOSE) << "Creating a Codec2 client to service \"" << name << "\"";
-    sp<Base> baseStore = Base::getService(name);
+
+    if (c2_aidl::utils::IsEnabled()) {
+        std::string instanceName =
+            ::android::base::StringPrintf("%s/%s", AidlBase::descriptor, name.c_str());
+        if (AServiceManager_isDeclared(instanceName.c_str())) {
+            std::shared_ptr<AidlBase> baseStore = AidlBase::fromBinder(
+                    ::ndk::SpAIBinder(AServiceManager_waitForService(instanceName.c_str())));
+            CHECK(baseStore) << "Codec2 AIDL service \"" << name << "\""
+                                " inaccessible for unknown reasons.";
+            LOG(VERBOSE) << "Client to Codec2 AIDL service \"" << name << "\" created";
+            std::shared_ptr<c2_aidl::IConfigurable> configurable;
+            ::ndk::ScopedAStatus transStatus = baseStore->getConfigurable(&configurable);
+            CHECK(transStatus.isOk()) << "Codec2 AIDL service \"" << name << "\""
+                                        "does not have IConfigurable.";
+            return std::make_shared<Codec2Client>(baseStore, configurable, index);
+        }
+    }
+
+    std::string instanceName = "android.hardware.media.c2/" + name;
+    sp<HidlBase> baseStore = HidlBase::getService(name);
     CHECK(baseStore) << "Codec2 service \"" << name << "\""
                         " inaccessible for unknown reasons.";
     LOG(VERBOSE) << "Client to Codec2 service \"" << name << "\" created";
-    Return<sp<IConfigurable>> transResult = baseStore->getConfigurable();
+    Return<sp<c2_hidl::IConfigurable>> transResult = baseStore->getConfigurable();
     CHECK(transResult.isOk()) << "Codec2 service \"" << name << "\""
                                 "does not have IConfigurable.";
-    sp<IConfigurable> configurable = static_cast<sp<IConfigurable>>(transResult);
+    sp<c2_hidl::IConfigurable> configurable =
+        static_cast<sp<c2_hidl::IConfigurable>>(transResult);
     return std::make_shared<Codec2Client>(baseStore, configurable, index);
 }
 
@@ -1262,8 +1674,7 @@
     return status;
 }
 
-std::shared_ptr<Codec2Client::Interface>
-        Codec2Client::CreateInterfaceByName(
+std::shared_ptr<Codec2Client::Interface> Codec2Client::CreateInterfaceByName(
         const char* interfaceName,
         std::shared_ptr<Codec2Client>* owner,
         size_t numberOfAttempts) {
@@ -1349,13 +1760,8 @@
     return nullptr;
 }
 
-// Codec2Client::Listener
-
-Codec2Client::Listener::~Listener() {
-}
-
 // Codec2Client::Interface
-Codec2Client::Interface::Interface(const sp<Base>& base)
+Codec2Client::Interface::Interface(const sp<HidlBase>& base)
       : Configurable{
             [base]() -> sp<c2_hidl::IConfigurable> {
                 Return<sp<c2_hidl::IConfigurable>> transResult =
@@ -1365,11 +1771,91 @@
                         nullptr;
             }()
         },
-        mBase{base} {
+        mHidlBase{base} {
+}
+
+Codec2Client::Interface::Interface(const std::shared_ptr<AidlBase>& base)
+      : Configurable{
+            [base]() -> std::shared_ptr<c2_aidl::IConfigurable> {
+                std::shared_ptr<c2_aidl::IConfigurable> aidlConfigurable;
+                ::ndk::ScopedAStatus transStatus =
+                    base->getConfigurable(&aidlConfigurable);
+                return transStatus.isOk() ? aidlConfigurable : nullptr;
+            }()
+        },
+        mAidlBase{base} {
 }
 
 // Codec2Client::Component
-Codec2Client::Component::Component(const sp<Base>& base)
+
+class Codec2Client::Component::AidlDeathManager {
+public:
+    AidlDeathManager()
+        : mSeq(0),
+          mDeathRecipient(AIBinder_DeathRecipient_new(OnBinderDied)) {
+    }
+
+    ~AidlDeathManager() = default;
+
+    bool linkToDeath(
+            const std::shared_ptr<Component> &comp,
+            const std::shared_ptr<Listener> &listener,
+            size_t *seqPtr) {
+        std::unique_lock lock(mMutex);
+        size_t seq = mSeq++;
+        if (!mMap.try_emplace(seq, comp, listener).second) {
+            return false;
+        }
+        if (STATUS_OK != AIBinder_linkToDeath(
+                comp->mAidlBase->asBinder().get(), mDeathRecipient.get(), (void *)seq)) {
+            mMap.erase(seq);
+            return false;
+        }
+        *seqPtr = seq;
+        return true;
+    }
+
+    void unlinkToDeath(size_t seq, const std::shared_ptr<AidlBase> &base) {
+        std::unique_lock lock(mMutex);
+        AIBinder_unlinkToDeath(base->asBinder().get(), mDeathRecipient.get(), (void *)seq);
+        mMap.erase(seq);
+    }
+
+private:
+    std::mutex mMutex;
+    size_t mSeq;
+    typedef std::tuple<std::weak_ptr<Component>, std::weak_ptr<Listener>> Context;
+    std::map<size_t, Context> mMap;
+    ::ndk::ScopedAIBinder_DeathRecipient mDeathRecipient;
+
+    bool extractContext(size_t seq, Context *context) {
+        std::unique_lock lock(mMutex);
+        auto node = mMap.extract(seq);
+        if (!node) {
+            return false;
+        }
+        *context = node.mapped();
+        return true;
+    }
+
+    static void OnBinderDied(void *cookie) {
+        size_t seq = size_t(cookie);
+        Context context;
+        if (!Component::GetAidlDeathManager()->extractContext(seq, &context)) {
+            return;
+        }
+        std::weak_ptr<Component> weakComponent;
+        std::weak_ptr<Listener> weakListener;
+        std::tie(weakComponent, weakListener) = context;
+        if (std::shared_ptr<Listener> listener = weakListener.lock()) {
+            listener->onDeath(weakComponent);
+        } else {
+            LOG(DEBUG) << "onDeath -- listener died.";
+        }
+    }
+};
+
+Codec2Client::Component::Component(const sp<HidlBase>& base)
       : Configurable{
             [base]() -> sp<c2_hidl::IConfigurable> {
                 Return<sp<c2_hidl::IComponentInterface>> transResult1 =
@@ -1385,14 +1871,14 @@
                         nullptr;
             }()
         },
-        mBase1_0{base},
-        mBase1_1{Base1_1::castFrom(base)},
-        mBase1_2{Base1_2::castFrom(base)},
-        mBufferPoolSender{std::make_unique<BufferPoolSender>()},
+        mHidlBase1_0{base},
+        mHidlBase1_1{HidlBase1_1::castFrom(base)},
+        mHidlBase1_2{HidlBase1_2::castFrom(base)},
+        mHidlBufferPoolSender{std::make_unique<HidlBufferPoolSender>()},
         mOutputBufferQueue{std::make_unique<OutputBufferQueue>()} {
 }
 
-Codec2Client::Component::Component(const sp<Base1_1>& base)
+Codec2Client::Component::Component(const sp<HidlBase1_1>& base)
       : Configurable{
             [base]() -> sp<c2_hidl::IConfigurable> {
                 Return<sp<c2_hidl::IComponentInterface>> transResult1 =
@@ -1408,14 +1894,14 @@
                         nullptr;
             }()
         },
-        mBase1_0{base},
-        mBase1_1{base},
-        mBase1_2{Base1_2::castFrom(base)},
-        mBufferPoolSender{std::make_unique<BufferPoolSender>()},
+        mHidlBase1_0{base},
+        mHidlBase1_1{base},
+        mHidlBase1_2{HidlBase1_2::castFrom(base)},
+        mHidlBufferPoolSender{std::make_unique<HidlBufferPoolSender>()},
         mOutputBufferQueue{std::make_unique<OutputBufferQueue>()} {
 }
 
-Codec2Client::Component::Component(const sp<Base1_2>& base)
+Codec2Client::Component::Component(const sp<HidlBase1_2>& base)
       : Configurable{
             [base]() -> sp<c2_hidl::IConfigurable> {
                 Return<sp<c2_hidl::IComponentInterface>> transResult1 =
@@ -1431,22 +1917,54 @@
                         nullptr;
             }()
         },
-        mBase1_0{base},
-        mBase1_1{base},
-        mBase1_2{base},
-        mBufferPoolSender{std::make_unique<BufferPoolSender>()},
+        mHidlBase1_0{base},
+        mHidlBase1_1{base},
+        mHidlBase1_2{base},
+        mHidlBufferPoolSender{std::make_unique<HidlBufferPoolSender>()},
+        mOutputBufferQueue{std::make_unique<OutputBufferQueue>()} {
+}
+
+Codec2Client::Component::Component(const std::shared_ptr<AidlBase> &base)
+      : Configurable{
+            [base]() -> std::shared_ptr<c2_aidl::IConfigurable> {
+                std::shared_ptr<c2_aidl::IComponentInterface> aidlIntf;
+                ::ndk::ScopedAStatus transStatus = base->getInterface(&aidlIntf);
+                if (!transStatus.isOk()) {
+                    return nullptr;
+                }
+                std::shared_ptr<c2_aidl::IConfigurable> aidlConfigurable;
+                transStatus = aidlIntf->getConfigurable(&aidlConfigurable);
+                return transStatus.isOk() ? aidlConfigurable : nullptr;
+            }()
+        },
+        mAidlBase{base},
+        mAidlBufferPoolSender{std::make_unique<AidlBufferPoolSender>()},
         mOutputBufferQueue{std::make_unique<OutputBufferQueue>()} {
 }
 
 Codec2Client::Component::~Component() {
+    if (mAidlDeathSeq) {
+        GetAidlDeathManager()->unlinkToDeath(*mAidlDeathSeq, mAidlBase);
+    }
 }
 
 c2_status_t Codec2Client::Component::createBlockPool(
         C2Allocator::id_t id,
         C2BlockPool::local_id_t* blockPoolId,
         std::shared_ptr<Codec2Client::Configurable>* configurable) {
+    if (mAidlBase) {
+        c2_aidl::IComponent::BlockPool aidlBlockPool;
+        ::ndk::ScopedAStatus transStatus = mAidlBase->createBlockPool(id, &aidlBlockPool);
+        c2_status_t status = GetC2Status(transStatus, "createBlockPool");
+        if (status != C2_OK) {
+            return status;
+        }
+        *blockPoolId = aidlBlockPool.blockPoolId;
+        *configurable = std::make_shared<Configurable>(aidlBlockPool.configurable);
+        return C2_OK;
+    }
     c2_status_t status;
-    Return<void> transStatus = mBase1_0->createBlockPool(
+    Return<void> transStatus = mHidlBase1_0->createBlockPool(
             static_cast<uint32_t>(id),
             [&status, blockPoolId, configurable](
                     c2_hidl::Status s,
@@ -1471,7 +1989,11 @@
 
 c2_status_t Codec2Client::Component::destroyBlockPool(
         C2BlockPool::local_id_t localId) {
-    Return<c2_hidl::Status> transResult = mBase1_0->destroyBlockPool(
+    if (mAidlBase) {
+        ::ndk::ScopedAStatus transStatus = mAidlBase->destroyBlockPool(localId);
+        return GetC2Status(transStatus, "destroyBlockPool");
+    }
+    Return<c2_hidl::Status> transResult = mHidlBase1_0->destroyBlockPool(
             static_cast<uint64_t>(localId));
     if (!transResult.isOk()) {
         LOG(ERROR) << "destroyBlockPool -- transaction failed.";
@@ -1488,12 +2010,21 @@
 
 c2_status_t Codec2Client::Component::queue(
         std::list<std::unique_ptr<C2Work>>* const items) {
+    if (mAidlBase) {
+        c2_aidl::WorkBundle workBundle;
+        if (!c2_aidl::utils::ToAidl(&workBundle, *items, mAidlBufferPoolSender.get())) {
+            LOG(ERROR) << "queue -- bad input.";
+            return C2_TRANSACTION_FAILED;
+        }
+        ::ndk::ScopedAStatus transStatus = mAidlBase->queue(workBundle);
+        return GetC2Status(transStatus, "queue");
+    }
     c2_hidl::WorkBundle workBundle;
-    if (!objcpy(&workBundle, *items, mBufferPoolSender.get())) {
+    if (!c2_hidl::utils::objcpy(&workBundle, *items, mHidlBufferPoolSender.get())) {
         LOG(ERROR) << "queue -- bad input.";
         return C2_TRANSACTION_FAILED;
     }
-    Return<c2_hidl::Status> transStatus = mBase1_0->queue(workBundle);
+    Return<c2_hidl::Status> transStatus = mHidlBase1_0->queue(workBundle);
     if (!transStatus.isOk()) {
         LOG(ERROR) << "queue -- transaction failed.";
         return C2_TRANSACTION_FAILED;
@@ -1509,25 +2040,38 @@
 c2_status_t Codec2Client::Component::flush(
         C2Component::flush_mode_t mode,
         std::list<std::unique_ptr<C2Work>>* const flushedWork) {
-    (void)mode; // Flush mode isn't supported in HIDL yet.
-    c2_status_t status;
-    Return<void> transStatus = mBase1_0->flush(
-            [&status, flushedWork](
-                    c2_hidl::Status s, const c2_hidl::WorkBundle& wb) {
-                status = static_cast<c2_status_t>(s);
-                if (status != C2_OK) {
-                    LOG(DEBUG) << "flush -- call failed: " << status << ".";
-                    return;
-                }
-                if (!c2_hidl::utils::objcpy(flushedWork, wb)) {
-                    status = C2_CORRUPTED;
-                } else {
-                    status = C2_OK;
-                }
-            });
-    if (!transStatus.isOk()) {
-        LOG(ERROR) << "flush -- transaction failed.";
-        return C2_TRANSACTION_FAILED;
+    (void)mode; // Flush mode isn't supported in HIDL/AIDL yet.
+    c2_status_t status = C2_OK;
+    if (mAidlBase) {
+        c2_aidl::WorkBundle workBundle;
+        ::ndk::ScopedAStatus transStatus = mAidlBase->flush(&workBundle);
+        c2_status_t status = GetC2Status(transStatus, "flush");
+        if (status != C2_OK) {
+            return status;
+        }
+        if (!c2_aidl::utils::FromAidl(flushedWork, workBundle)) {
+            LOG(DEBUG) << "flush -- flushedWork corrupted.";
+            return C2_CORRUPTED;
+        }
+    } else {
+        Return<void> transStatus = mHidlBase1_0->flush(
+                [&status, flushedWork](
+                        c2_hidl::Status s, const c2_hidl::WorkBundle& wb) {
+                    status = static_cast<c2_status_t>(s);
+                    if (status != C2_OK) {
+                        LOG(DEBUG) << "flush -- call failed: " << status << ".";
+                        return;
+                    }
+                    if (!c2_hidl::utils::objcpy(flushedWork, wb)) {
+                        status = C2_CORRUPTED;
+                    } else {
+                        status = C2_OK;
+                    }
+                });
+        if (!transStatus.isOk()) {
+            LOG(ERROR) << "flush -- transaction failed.";
+            return C2_TRANSACTION_FAILED;
+        }
     }
 
     // Indices of flushed work items.
@@ -1552,7 +2096,12 @@
 }
 
 c2_status_t Codec2Client::Component::drain(C2Component::drain_mode_t mode) {
-    Return<c2_hidl::Status> transStatus = mBase1_0->drain(
+    if (mAidlBase) {
+        ::ndk::ScopedAStatus transStatus = mAidlBase->drain(
+                mode == C2Component::DRAIN_COMPONENT_WITH_EOS);
+        return GetC2Status(transStatus, "drain");
+    }
+    Return<c2_hidl::Status> transStatus = mHidlBase1_0->drain(
             mode == C2Component::DRAIN_COMPONENT_WITH_EOS);
     if (!transStatus.isOk()) {
         LOG(ERROR) << "drain -- transaction failed.";
@@ -1567,7 +2116,11 @@
 }
 
 c2_status_t Codec2Client::Component::start() {
-    Return<c2_hidl::Status> transStatus = mBase1_0->start();
+    if (mAidlBase) {
+        ::ndk::ScopedAStatus transStatus = mAidlBase->start();
+        return GetC2Status(transStatus, "start");
+    }
+    Return<c2_hidl::Status> transStatus = mHidlBase1_0->start();
     if (!transStatus.isOk()) {
         LOG(ERROR) << "start -- transaction failed.";
         return C2_TRANSACTION_FAILED;
@@ -1581,7 +2134,11 @@
 }
 
 c2_status_t Codec2Client::Component::stop() {
-    Return<c2_hidl::Status> transStatus = mBase1_0->stop();
+    if (mAidlBase) {
+        ::ndk::ScopedAStatus transStatus = mAidlBase->stop();
+        return GetC2Status(transStatus, "stop");
+    }
+    Return<c2_hidl::Status> transStatus = mHidlBase1_0->stop();
     if (!transStatus.isOk()) {
         LOG(ERROR) << "stop -- transaction failed.";
         return C2_TRANSACTION_FAILED;
@@ -1595,7 +2152,11 @@
 }
 
 c2_status_t Codec2Client::Component::reset() {
-    Return<c2_hidl::Status> transStatus = mBase1_0->reset();
+    if (mAidlBase) {
+        ::ndk::ScopedAStatus transStatus = mAidlBase->reset();
+        return GetC2Status(transStatus, "reset");
+    }
+    Return<c2_hidl::Status> transStatus = mHidlBase1_0->reset();
     if (!transStatus.isOk()) {
         LOG(ERROR) << "reset -- transaction failed.";
         return C2_TRANSACTION_FAILED;
@@ -1609,7 +2170,11 @@
 }
 
 c2_status_t Codec2Client::Component::release() {
-    Return<c2_hidl::Status> transStatus = mBase1_0->release();
+    if (mAidlBase) {
+        ::ndk::ScopedAStatus transStatus = mAidlBase->release();
+        return GetC2Status(transStatus, "release");
+    }
+    Return<c2_hidl::Status> transStatus = mHidlBase1_0->release();
     if (!transStatus.isOk()) {
         LOG(ERROR) << "release -- transaction failed.";
         return C2_TRANSACTION_FAILED;
@@ -1626,11 +2191,25 @@
         uint32_t avSyncHwId,
         native_handle_t** sidebandHandle) {
     *sidebandHandle = nullptr;
-    if (!mBase1_1) {
+    if (mAidlBase) {
+        ::aidl::android::hardware::common::NativeHandle handle;
+        ::ndk::ScopedAStatus transStatus = mAidlBase->configureVideoTunnel(avSyncHwId, &handle);
+        c2_status_t status = GetC2Status(transStatus, "configureVideoTunnel");
+        if (status != C2_OK) {
+            return status;
+        }
+        if (isAidlNativeHandleEmpty(handle)) {
+            LOG(DEBUG) << "configureVideoTunnel -- empty handle returned";
+        } else {
+            *sidebandHandle = dupFromAidl(handle);
+        }
+        return C2_OK;
+    }
+    if (!mHidlBase1_1) {
         return C2_OMITTED;
     }
     c2_status_t status{};
-    Return<void> transStatus = mBase1_1->configureVideoTunnel(avSyncHwId,
+    Return<void> transStatus = mHidlBase1_1->configureVideoTunnel(avSyncHwId,
             [&status, sidebandHandle](
                     c2_hidl::Status s, hardware::hidl_handle const& h) {
                 status = static_cast<c2_status_t>(s);
@@ -1671,8 +2250,8 @@
         bqId = 0;
         mOutputBufferQueue->configure(nullIgbp, generation, 0, maxDequeueCount, nullptr);
     } else {
-        mOutputBufferQueue->configure(surface, generation, bqId, maxDequeueCount, mBase1_2 ?
-                                      &syncObj : nullptr);
+        mOutputBufferQueue->configure(surface, generation, bqId, maxDequeueCount,
+                                      mHidlBase1_2 ? &syncObj : nullptr);
     }
 
     // set consumer bits
@@ -1711,11 +2290,15 @@
     ALOGD("setOutputSurface -- generation=%u consumer usage=%#llx%s",
             generation, (long long)consumerUsage, syncObj ? " sync" : "");
 
+    if (mAidlBase) {
+        // FIXME
+        return C2_OMITTED;
+    }
     Return<c2_hidl::Status> transStatus = syncObj ?
-            mBase1_2->setOutputSurfaceWithSyncObj(
+            mHidlBase1_2->setOutputSurfaceWithSyncObj(
                     static_cast<uint64_t>(blockPoolId),
                     bqId == 0 ? nullHgbp : igbp, *syncObj) :
-            mBase1_0->setOutputSurface(
+            mHidlBase1_0->setOutputSurface(
                     static_cast<uint64_t>(blockPoolId),
                     bqId == 0 ? nullHgbp : igbp);
 
@@ -1755,7 +2338,11 @@
         C2BlockPool::local_id_t blockPoolId) {
     std::scoped_lock lock(mOutputMutex);
     mOutputBufferQueue->stop();
-    Return<c2_hidl::Status> transStatus = mBase1_0->setOutputSurface(
+    if (mAidlBase) {
+        // FIXME
+        return;
+    }
+    Return<c2_hidl::Status> transStatus = mHidlBase1_0->setOutputSurface(
             static_cast<uint64_t>(blockPoolId), nullptr);
     if (!transStatus.isOk()) {
         LOG(ERROR) << "setOutputSurface(stopUsingOutputSurface) -- transaction failed.";
@@ -1773,8 +2360,12 @@
 c2_status_t Codec2Client::Component::connectToInputSurface(
         const std::shared_ptr<InputSurface>& inputSurface,
         std::shared_ptr<InputSurfaceConnection>* connection) {
+    if (mAidlBase) {
+        // FIXME
+        return C2_OMITTED;
+    }
     c2_status_t status;
-    Return<void> transStatus = mBase1_0->connectToInputSurface(
+    Return<void> transStatus = mHidlBase1_0->connectToInputSurface(
             inputSurface->mBase,
             [&status, connection](
                     c2_hidl::Status s, const sp<c2_hidl::IInputSurfaceConnection>& c) {
@@ -1797,8 +2388,12 @@
         const sp<HGraphicBufferProducer1>& producer,
         const sp<HGraphicBufferSource>& source,
         std::shared_ptr<InputSurfaceConnection>* connection) {
+    if (mAidlBase) {
+        LOG(WARNING) << "Connecting to OMX input surface is not supported for AIDL C2 HAL";
+        return C2_OMITTED;
+    }
     c2_status_t status;
-    Return<void> transStatus = mBase1_0->connectToOmxInputSurface(
+    Return<void> transStatus = mHidlBase1_0->connectToOmxInputSurface(
             producer, source,
             [&status, connection](
                     c2_hidl::Status s, const sp<c2_hidl::IInputSurfaceConnection>& c) {
@@ -1818,7 +2413,11 @@
 }
 
 c2_status_t Codec2Client::Component::disconnectFromInputSurface() {
-    Return<c2_hidl::Status> transStatus = mBase1_0->disconnectFromInputSurface();
+    if (mAidlBase) {
+        // FIXME
+        return C2_OMITTED;
+    }
+    Return<c2_hidl::Status> transStatus = mHidlBase1_0->disconnectFromInputSurface();
     if (!transStatus.isOk()) {
         LOG(ERROR) << "disconnectToInputSurface -- transaction failed.";
         return C2_TRANSACTION_FAILED;
@@ -1832,6 +2431,12 @@
     return status;
 }
 
+Codec2Client::Component::AidlDeathManager *Codec2Client::Component::GetAidlDeathManager() {
+    // This object never gets destructed
+    static AidlDeathManager *sManager = new AidlDeathManager();
+    return sManager;
+}
+
 c2_status_t Codec2Client::Component::setDeathListener(
         const std::shared_ptr<Component>& component,
         const std::shared_ptr<Listener>& listener) {
@@ -1852,12 +2457,20 @@
         }
     };
 
+    if (component->mAidlBase) {
+        size_t seq;
+        if (GetAidlDeathManager()->linkToDeath(component, listener, &seq)) {
+            component->mAidlDeathSeq = seq;
+        }
+        return C2_OK;
+    }
+
     sp<HidlDeathRecipient> deathRecipient = new HidlDeathRecipient();
     deathRecipient->base = listener;
     deathRecipient->component = component;
 
     component->mDeathRecipient = deathRecipient;
-    Return<bool> transResult = component->mBase1_0->linkToDeath(
+    Return<bool> transResult = component->mHidlBase1_0->linkToDeath(
             component->mDeathRecipient, 0);
     if (!transResult.isOk()) {
         LOG(ERROR) << "setDeathListener -- linkToDeath() transaction failed.";
diff --git a/media/codec2/hal/client/include/codec2/hidl/client.h b/media/codec2/hal/client/include/codec2/hidl/client.h
index 6fa19b0..0c7dd77 100644
--- a/media/codec2/hal/client/include/codec2/hidl/client.h
+++ b/media/codec2/hal/client/include/codec2/hidl/client.h
@@ -95,6 +95,11 @@
 struct IClientManager;
 }  // namespace android::hardware::media::bufferpool::V2_0
 
+namespace aidl::android::hardware::media::bufferpool2 {
+class IClientManager;
+}  // namespace aidl::android::hardware::media::c2
+
+
 namespace android::hardware::graphics::bufferqueue::V1_0 {
 struct IGraphicBufferProducer;
 }  // android::hardware::graphics::bufferqueue::V1_0
@@ -173,12 +178,12 @@
 
 struct Codec2Client : public Codec2ConfigurableClient {
 
-    typedef ::android::hardware::media::c2::V1_0::IComponentStore Base1_0;
-    typedef ::android::hardware::media::c2::V1_1::IComponentStore Base1_1;
-    typedef ::android::hardware::media::c2::V1_2::IComponentStore Base1_2;
-    typedef Base1_0 Base;
+    typedef ::android::hardware::media::c2::V1_0::IComponentStore HidlBase1_0;
+    typedef ::android::hardware::media::c2::V1_1::IComponentStore HidlBase1_1;
+    typedef ::android::hardware::media::c2::V1_2::IComponentStore HidlBase1_2;
+    typedef HidlBase1_0 HidlBase;
 
-    typedef ::android::hardware::media::c2::V1_0::IConfigurable IConfigurable;
+    typedef ::aidl::android::hardware::media::c2::IComponentStore AidlBase;
 
     struct Listener;
 
@@ -194,10 +199,11 @@
 
     typedef Codec2Client Store;
 
-    sp<Base> const& getBase() const;
-    sp<Base1_0> const& getBase1_0() const;
-    sp<Base1_1> const& getBase1_1() const;
-    sp<Base1_2> const& getBase1_2() const;
+    sp<HidlBase> const& getHidlBase() const;
+    sp<HidlBase1_0> const& getHidlBase1_0() const;
+    sp<HidlBase1_1> const& getHidlBase1_1() const;
+    sp<HidlBase1_2> const& getHidlBase1_2() const;
+    ::ndk::SpAIBinder getAidlBase() const;
 
     std::string const& getServiceName() const;
 
@@ -266,14 +272,19 @@
 
     // base and/or configurable cannot be null.
     Codec2Client(
-            sp<Base> const& base,
-            sp<IConfigurable> const& configurable,
+            sp<HidlBase> const& base,
+            sp<Codec2ConfigurableClient::HidlBase> const& configurable,
+            size_t serviceIndex);
+    Codec2Client(
+            std::shared_ptr<AidlBase> const& base,
+            std::shared_ptr<Codec2ConfigurableClient::AidlBase> const& configurable,
             size_t serviceIndex);
 
 protected:
-    sp<Base1_0> mBase1_0;
-    sp<Base1_1> mBase1_1;
-    sp<Base1_2> mBase1_2;
+    sp<HidlBase1_0> mHidlBase1_0;
+    sp<HidlBase1_1> mHidlBase1_1;
+    sp<HidlBase1_2> mHidlBase1_2;
+    std::shared_ptr<AidlBase> mAidlBase;
 
     // Finds the first store where the predicate returns C2_OK and returns the
     // last predicate result. The predicate will be tried on all stores. The
@@ -301,8 +312,11 @@
     mutable std::vector<C2Component::Traits> mTraitsList;
 
     sp<::android::hardware::media::bufferpool::V2_0::IClientManager>
-            mHostPoolManager;
+            mHidlHostPoolManager;
+    std::shared_ptr<::aidl::android::hardware::media::bufferpool2::IClientManager>
+            mAidlHostPoolManager;
 
+    static std::vector<std::string> CacheServiceNames();
     static std::shared_ptr<Codec2Client> _CreateFromIndex(size_t index);
 
     std::vector<C2Component::Traits> _listComponents(bool* success) const;
@@ -312,12 +326,15 @@
 
 struct Codec2Client::Interface : public Codec2Client::Configurable {
 
-    typedef ::android::hardware::media::c2::V1_0::IComponentInterface Base;
+    typedef ::android::hardware::media::c2::V1_0::IComponentInterface HidlBase;
+    typedef ::aidl::android::hardware::media::c2::IComponentInterface AidlBase;
 
-    Interface(const sp<Base>& base);
+    Interface(const sp<HidlBase>& base);
+    Interface(const std::shared_ptr<AidlBase>& base);
 
 protected:
-    sp<Base> mBase;
+    sp<HidlBase> mHidlBase;
+    std::shared_ptr<AidlBase> mAidlBase;
 };
 
 struct Codec2Client::Listener {
@@ -356,16 +373,17 @@
             int32_t slotId,
             int64_t timestampNs) = 0;
 
-    virtual ~Listener();
-
+    virtual ~Listener() = default;
 };
 
 struct Codec2Client::Component : public Codec2Client::Configurable {
 
-    typedef ::android::hardware::media::c2::V1_0::IComponent Base1_0;
-    typedef ::android::hardware::media::c2::V1_1::IComponent Base1_1;
-    typedef ::android::hardware::media::c2::V1_2::IComponent Base1_2;
-    typedef Base1_0 Base;
+    typedef ::android::hardware::media::c2::V1_0::IComponent HidlBase1_0;
+    typedef ::android::hardware::media::c2::V1_1::IComponent HidlBase1_1;
+    typedef ::android::hardware::media::c2::V1_2::IComponent HidlBase1_2;
+    typedef HidlBase1_0 HidlBase;
+
+    typedef ::aidl::android::hardware::media::c2::IComponent AidlBase;
 
     c2_status_t createBlockPool(
             C2Allocator::id_t id,
@@ -469,19 +487,23 @@
     c2_status_t disconnectFromInputSurface();
 
     // base cannot be null.
-    Component(const sp<Base>& base);
-    Component(const sp<Base1_1>& base);
-    Component(const sp<Base1_2>& base);
+    Component(const sp<HidlBase>& base);
+    Component(const sp<HidlBase1_1>& base);
+    Component(const sp<HidlBase1_2>& base);
+    Component(const std::shared_ptr<AidlBase>& base);
 
     ~Component();
 
 protected:
-    sp<Base1_0> mBase1_0;
-    sp<Base1_1> mBase1_1;
-    sp<Base1_2> mBase1_2;
+    sp<HidlBase1_0> mHidlBase1_0;
+    sp<HidlBase1_1> mHidlBase1_1;
+    sp<HidlBase1_2> mHidlBase1_2;
+    std::shared_ptr<AidlBase> mAidlBase;
 
-    struct BufferPoolSender;
-    std::unique_ptr<BufferPoolSender> mBufferPoolSender;
+    struct HidlBufferPoolSender;
+    struct AidlBufferPoolSender;
+    std::unique_ptr<HidlBufferPoolSender> mHidlBufferPoolSender;
+    std::unique_ptr<AidlBufferPoolSender> mAidlBufferPoolSender;
 
     struct OutputBufferQueue;
     std::unique_ptr<OutputBufferQueue> mOutputBufferQueue;
@@ -491,6 +513,10 @@
     // In order to prevent the race condition mutex is added.
     std::mutex mOutputMutex;
 
+    class AidlDeathManager;
+    static AidlDeathManager *GetAidlDeathManager();
+    std::optional<size_t> mAidlDeathSeq;
+
     static c2_status_t setDeathListener(
             const std::shared_ptr<Component>& component,
             const std::shared_ptr<Listener>& listener);
@@ -499,16 +525,15 @@
     friend struct Codec2Client;
 
     struct HidlListener;
+    struct AidlListener;
     void handleOnWorkDone(const std::list<std::unique_ptr<C2Work>> &workItems);
-
 };
 
 struct Codec2Client::InputSurface : public Codec2Client::Configurable {
 public:
     typedef ::android::hardware::media::c2::V1_0::IInputSurface Base;
 
-    typedef ::android::hardware::media::c2::V1_0::IInputSurfaceConnection
-            ConnectionBase;
+    typedef ::android::hardware::media::c2::V1_0::IInputSurfaceConnection ConnectionBase;
 
     typedef Codec2Client::InputSurfaceConnection Connection;
 
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/sfplugin/Android.bp b/media/codec2/sfplugin/Android.bp
index e4daf5c..d867eb1 100644
--- a/media/codec2/sfplugin/Android.bp
+++ b/media/codec2/sfplugin/Android.bp
@@ -52,7 +52,6 @@
         "android.hardware.drm@1.0",
         "android.hardware.media.c2@1.0",
         "android.hardware.media.omx@1.0",
-        "android.hardware.graphics.mapper@4.0",
         "libbase",
         "libbinder",
         "libcodec2",
diff --git a/media/codec2/sfplugin/CCodecBufferChannel.h b/media/codec2/sfplugin/CCodecBufferChannel.h
index f60b6fa..2bdb7bc 100644
--- a/media/codec2/sfplugin/CCodecBufferChannel.h
+++ b/media/codec2/sfplugin/CCodecBufferChannel.h
@@ -62,8 +62,8 @@
     void setCrypto(const sp<ICrypto> &crypto) override;
     void setDescrambler(const sp<IDescrambler> &descrambler) override;
 
-    virtual status_t queueInputBuffer(const sp<MediaCodecBuffer> &buffer) override;
-    virtual status_t queueSecureInputBuffer(
+    status_t queueInputBuffer(const sp<MediaCodecBuffer> &buffer) override;
+    status_t queueSecureInputBuffer(
             const sp<MediaCodecBuffer> &buffer,
             bool secure,
             const uint8_t *key,
@@ -73,10 +73,10 @@
             const CryptoPlugin::SubSample *subSamples,
             size_t numSubSamples,
             AString *errorDetailMsg) override;
-    virtual status_t attachBuffer(
+    status_t attachBuffer(
             const std::shared_ptr<C2Buffer> &c2Buffer,
             const sp<MediaCodecBuffer> &buffer) override;
-    virtual status_t attachEncryptedBuffer(
+    status_t attachEncryptedBuffer(
             const sp<hardware::HidlMemory> &memory,
             bool secure,
             const uint8_t *key,
@@ -88,12 +88,12 @@
             size_t numSubSamples,
             const sp<MediaCodecBuffer> &buffer,
             AString* errorDetailMsg) override;
-    virtual status_t renderOutputBuffer(
+    status_t renderOutputBuffer(
             const sp<MediaCodecBuffer> &buffer, int64_t timestampNs) override;
-    virtual void pollForRenderedBuffers() override;
-    virtual status_t discardBuffer(const sp<MediaCodecBuffer> &buffer) override;
-    virtual void getInputBufferArray(Vector<sp<MediaCodecBuffer>> *array) override;
-    virtual void getOutputBufferArray(Vector<sp<MediaCodecBuffer>> *array) override;
+    void pollForRenderedBuffers() override;
+    status_t discardBuffer(const sp<MediaCodecBuffer> &buffer) override;
+    void getInputBufferArray(Vector<sp<MediaCodecBuffer>> *array) override;
+    void getOutputBufferArray(Vector<sp<MediaCodecBuffer>> *array) override;
 
     // Methods below are interface for CCodec to use.
 
diff --git a/media/codec2/sfplugin/Codec2Buffer.cpp b/media/codec2/sfplugin/Codec2Buffer.cpp
index 228ad7e..3bb6593 100644
--- a/media/codec2/sfplugin/Codec2Buffer.cpp
+++ b/media/codec2/sfplugin/Codec2Buffer.cpp
@@ -26,9 +26,6 @@
 #include <android-base/properties.h>
 #include <android/hardware/cas/native/1.0/types.h>
 #include <android/hardware/drm/1.0/types.h>
-#include <android/hardware/graphics/common/1.2/types.h>
-#include <android/hardware/graphics/mapper/4.0/IMapper.h>
-#include <gralloctypes/Gralloc4.h>
 #include <hidlmemory/FrameworkUtils.h>
 #include <media/hardware/HardwareAPI.h>
 #include <media/stagefright/CodecBase.h>
@@ -38,6 +35,7 @@
 #include <media/stagefright/foundation/AUtils.h>
 #include <mediadrm/ICrypto.h>
 #include <nativebase/nativebase.h>
+#include <ui/GraphicBufferMapper.h>
 #include <ui/Fence.h>
 
 #include <C2AllocatorGralloc.h>
@@ -1039,34 +1037,15 @@
 }
 
 using ::aidl::android::hardware::graphics::common::Cta861_3;
-using ::aidl::android::hardware::graphics::common::Dataspace;
 using ::aidl::android::hardware::graphics::common::Smpte2086;
 
-using ::android::gralloc4::MetadataType_Cta861_3;
-using ::android::gralloc4::MetadataType_Dataspace;
-using ::android::gralloc4::MetadataType_Smpte2086;
-using ::android::gralloc4::MetadataType_Smpte2094_40;
-
-using ::android::hardware::Return;
-using ::android::hardware::hidl_vec;
-
-using Error4 = ::android::hardware::graphics::mapper::V4_0::Error;
-using IMapper4 = ::android::hardware::graphics::mapper::V4_0::IMapper;
-
 namespace {
 
-sp<IMapper4> GetMapper4() {
-    static ::android::base::NoDestructor<sp<IMapper4>> sMapper(IMapper4::getService());
-    return *sMapper;
-}
-
-class Gralloc4Buffer {
+class GrallocBuffer {
 public:
-    Gralloc4Buffer(const C2Handle *const handle) : mBuffer(nullptr) {
-        sp<IMapper4> mapper = GetMapper4();
-        if (!mapper) {
-            return;
-        }
+    GrallocBuffer(const C2Handle *const handle) : mBuffer(nullptr) {
+        GraphicBufferMapper& mapper = GraphicBufferMapper::get();
+
         // Unwrap raw buffer handle from the C2Handle
         native_handle_t *nh = UnwrapNativeCodec2GrallocHandle(handle);
         if (!nh) {
@@ -1074,13 +1053,14 @@
         }
         // Import the raw handle so IMapper can use the buffer. The imported
         // handle must be freed when the client is done with the buffer.
-        mapper->importBuffer(
-                hardware::hidl_handle(nh),
-                [&](const Error4 &error, void *buffer) {
-                    if (error == Error4::NONE) {
-                        mBuffer = buffer;
-                    }
-                });
+        status_t status = mapper.importBufferNoValidate(
+                nh,
+                &mBuffer);
+
+        if (status != OK) {
+            ALOGE("Failed to import buffer. Status: %d.", status);
+            return;
+        }
 
         // TRICKY: UnwrapNativeCodec2GrallocHandle creates a new handle but
         //         does not clone the fds. Thus we need to delete the handle
@@ -1088,19 +1068,19 @@
         native_handle_delete(nh);
     }
 
-    ~Gralloc4Buffer() {
-        sp<IMapper4> mapper = GetMapper4();
-        if (mapper && mBuffer) {
+    ~GrallocBuffer() {
+        GraphicBufferMapper& mapper = GraphicBufferMapper::get();
+        if (mBuffer) {
             // Free the imported buffer handle. This does not release the
             // underlying buffer itself.
-            mapper->freeBuffer(mBuffer);
+            mapper.freeBuffer(mBuffer);
         }
     }
 
-    void *get() const { return mBuffer; }
+    buffer_handle_t get() const { return mBuffer; }
     operator bool() const { return (mBuffer != nullptr); }
 private:
-    void *mBuffer;
+    buffer_handle_t mBuffer;
 };
 
 }  // namspace
@@ -1110,69 +1090,48 @@
         std::shared_ptr<C2StreamHdrStaticMetadataInfo::input> *staticInfo,
         std::shared_ptr<C2StreamHdrDynamicMetadataInfo::input> *dynamicInfo) {
     c2_status_t err = C2_OK;
-    sp<IMapper4> mapper = GetMapper4();
-    Gralloc4Buffer buffer(handle);
-    if (!mapper || !buffer) {
+    GraphicBufferMapper& mapper = GraphicBufferMapper::get();
+    GrallocBuffer buffer(handle);
+    if (!buffer) {
         // Gralloc4 not supported; nothing to do
         return err;
     }
-    Error4 mapperErr = Error4::NONE;
     if (staticInfo) {
-        ALOGV("Grabbing static HDR info from gralloc4 metadata");
+        ALOGV("Grabbing static HDR info from gralloc metadata");
         staticInfo->reset(new C2StreamHdrStaticMetadataInfo::input(0u));
         memset(&(*staticInfo)->mastering, 0, sizeof((*staticInfo)->mastering));
         (*staticInfo)->maxCll = 0;
         (*staticInfo)->maxFall = 0;
-        IMapper4::get_cb cb = [&mapperErr, staticInfo](Error4 err, const hidl_vec<uint8_t> &vec) {
-            mapperErr = err;
-            if (err != Error4::NONE) {
-                return;
-            }
 
-            std::optional<Smpte2086> smpte2086;
-            gralloc4::decodeSmpte2086(vec, &smpte2086);
+        std::optional<Smpte2086> smpte2086;
+        status_t status = mapper.getSmpte2086(buffer.get(), &smpte2086);
+        if (status != OK) {
+            err = C2_CORRUPTED;
+        } else {
             if (smpte2086) {
-                (*staticInfo)->mastering.red.x    = smpte2086->primaryRed.x;
-                (*staticInfo)->mastering.red.y    = smpte2086->primaryRed.y;
-                (*staticInfo)->mastering.green.x  = smpte2086->primaryGreen.x;
-                (*staticInfo)->mastering.green.y  = smpte2086->primaryGreen.y;
-                (*staticInfo)->mastering.blue.x   = smpte2086->primaryBlue.x;
-                (*staticInfo)->mastering.blue.y   = smpte2086->primaryBlue.y;
-                (*staticInfo)->mastering.white.x  = smpte2086->whitePoint.x;
-                (*staticInfo)->mastering.white.y  = smpte2086->whitePoint.y;
+                  (*staticInfo)->mastering.red.x    = smpte2086->primaryRed.x;
+                  (*staticInfo)->mastering.red.y    = smpte2086->primaryRed.y;
+                  (*staticInfo)->mastering.green.x  = smpte2086->primaryGreen.x;
+                  (*staticInfo)->mastering.green.y  = smpte2086->primaryGreen.y;
+                  (*staticInfo)->mastering.blue.x   = smpte2086->primaryBlue.x;
+                  (*staticInfo)->mastering.blue.y   = smpte2086->primaryBlue.y;
+                  (*staticInfo)->mastering.white.x  = smpte2086->whitePoint.x;
+                  (*staticInfo)->mastering.white.y  = smpte2086->whitePoint.y;
 
-                (*staticInfo)->mastering.maxLuminance = smpte2086->maxLuminance;
-                (*staticInfo)->mastering.minLuminance = smpte2086->minLuminance;
-            } else {
-                mapperErr = Error4::BAD_VALUE;
+                  (*staticInfo)->mastering.maxLuminance = smpte2086->maxLuminance;
+                  (*staticInfo)->mastering.minLuminance = smpte2086->minLuminance;
             }
-        };
-        Return<void> ret = mapper->get(buffer.get(), MetadataType_Smpte2086, cb);
-        if (!ret.isOk()) {
-            err = C2_REFUSED;
-        } else if (mapperErr != Error4::NONE) {
-            err = C2_CORRUPTED;
         }
-        cb = [&mapperErr, staticInfo](Error4 err, const hidl_vec<uint8_t> &vec) {
-            mapperErr = err;
-            if (err != Error4::NONE) {
-                return;
-            }
 
-            std::optional<Cta861_3> cta861_3;
-            gralloc4::decodeCta861_3(vec, &cta861_3);
-            if (cta861_3) {
-                (*staticInfo)->maxCll   = cta861_3->maxContentLightLevel;
-                (*staticInfo)->maxFall  = cta861_3->maxFrameAverageLightLevel;
-            } else {
-                mapperErr = Error4::BAD_VALUE;
-            }
-        };
-        ret = mapper->get(buffer.get(), MetadataType_Cta861_3, cb);
-        if (!ret.isOk()) {
-            err = C2_REFUSED;
-        } else if (mapperErr != Error4::NONE) {
+        std::optional<Cta861_3> cta861_3;
+        status = mapper.getCta861_3(buffer.get(), &cta861_3);
+        if (status != OK) {
             err = C2_CORRUPTED;
+        } else {
+            if (cta861_3) {
+                  (*staticInfo)->maxCll   = cta861_3->maxContentLightLevel;
+                  (*staticInfo)->maxFall  = cta861_3->maxFrameAverageLightLevel;
+            }
         }
     }
 
@@ -1181,23 +1140,19 @@
     }
 
     if (dynamicInfo) {
-        ALOGV("Grabbing dynamic HDR info from gralloc4 metadata");
+        ALOGV("Grabbing dynamic HDR info from gralloc metadata");
         dynamicInfo->reset();
-        IMapper4::get_cb cb = [&mapperErr, dynamicInfo](Error4 err, const hidl_vec<uint8_t> &vec) {
-            mapperErr = err;
-            if (err != Error4::NONE) {
-                return;
-            }
-            if (!dynamicInfo) {
-                return;
-            }
-            *dynamicInfo = C2StreamHdrDynamicMetadataInfo::input::AllocShared(
-                    vec.size(), 0u, C2Config::HDR_DYNAMIC_METADATA_TYPE_SMPTE_2094_40);
-            memcpy((*dynamicInfo)->m.data, vec.data(), vec.size());
-        };
-        Return<void> ret = mapper->get(buffer.get(), MetadataType_Smpte2094_40, cb);
-        if (!ret.isOk() || mapperErr != Error4::NONE) {
+        std::optional<std::vector<uint8_t>> vec;
+        status_t status = mapper.getSmpte2094_40(buffer.get(), &vec);
+        if (status != OK) {
             dynamicInfo->reset();
+            err = C2_CORRUPTED;
+        } else {
+            if (vec) {
+                *dynamicInfo = C2StreamHdrDynamicMetadataInfo::input::AllocShared(
+                      vec->size(), 0u, C2Config::HDR_DYNAMIC_METADATA_TYPE_SMPTE_2094_40);
+                memcpy((*dynamicInfo)->m.data, vec->data(), vec->size());
+            }
         }
     }
 
@@ -1210,25 +1165,18 @@
         const std::shared_ptr<const C2StreamHdrDynamicMetadataInfo::output> &dynamicInfo,
         const C2Handle *const handle) {
     c2_status_t err = C2_OK;
-    sp<IMapper4> mapper = GetMapper4();
-    Gralloc4Buffer buffer(handle);
-    if (!mapper || !buffer) {
+    GraphicBufferMapper& mapper = GraphicBufferMapper::get();
+    GrallocBuffer buffer(handle);
+    if (!buffer) {
         // Gralloc4 not supported; nothing to do
         return err;
     }
-    {
-        hidl_vec<uint8_t> metadata;
-        if (gralloc4::encodeDataspace(static_cast<Dataspace>(dataSpace), &metadata) == OK) {
-            Return<Error4> ret = mapper->set(buffer.get(), MetadataType_Dataspace, metadata);
-            if (!ret.isOk()) {
-                err = C2_REFUSED;
-            } else if (ret != Error4::NONE) {
-                err = C2_CORRUPTED;
-            }
-        }
+    status_t status = mapper.setDataspace(buffer.get(), static_cast<ui::Dataspace>(dataSpace));
+    if (status != OK) {
+       err = C2_CORRUPTED;
     }
     if (staticInfo && *staticInfo) {
-        ALOGV("Setting static HDR info as gralloc4 metadata");
+        ALOGV("Setting static HDR info as gralloc metadata");
         std::optional<Smpte2086> smpte2086 = Smpte2086{
             {staticInfo->mastering.red.x, staticInfo->mastering.red.y},
             {staticInfo->mastering.green.x, staticInfo->mastering.green.y},
@@ -1237,7 +1185,6 @@
             staticInfo->mastering.maxLuminance,
             staticInfo->mastering.minLuminance,
         };
-        hidl_vec<uint8_t> vec;
         if (0.0 <= smpte2086->primaryRed.x && smpte2086->primaryRed.x <= 1.0
                 && 0.0 <= smpte2086->primaryRed.y && smpte2086->primaryRed.y <= 1.0
                 && 0.0 <= smpte2086->primaryGreen.x && smpte2086->primaryGreen.x <= 1.0
@@ -1246,12 +1193,9 @@
                 && 0.0 <= smpte2086->primaryBlue.y && smpte2086->primaryBlue.y <= 1.0
                 && 0.0 <= smpte2086->whitePoint.x && smpte2086->whitePoint.x <= 1.0
                 && 0.0 <= smpte2086->whitePoint.y && smpte2086->whitePoint.y <= 1.0
-                && 0.0 <= smpte2086->maxLuminance && 0.0 <= smpte2086->minLuminance
-                && gralloc4::encodeSmpte2086(smpte2086, &vec) == OK) {
-            Return<Error4> ret = mapper->set(buffer.get(), MetadataType_Smpte2086, vec);
-            if (!ret.isOk()) {
-                err = C2_REFUSED;
-            } else if (ret != Error4::NONE) {
+                && 0.0 <= smpte2086->maxLuminance && 0.0 <= smpte2086->minLuminance) {
+            status = mapper.setSmpte2086(buffer.get(), smpte2086);
+            if (status != OK) {
                 err = C2_CORRUPTED;
             }
         }
@@ -1259,41 +1203,23 @@
             staticInfo->maxCll,
             staticInfo->maxFall,
         };
-        if (0.0 <= cta861_3->maxContentLightLevel && 0.0 <= cta861_3->maxFrameAverageLightLevel
-                && gralloc4::encodeCta861_3(cta861_3, &vec) == OK) {
-            Return<Error4> ret = mapper->set(buffer.get(), MetadataType_Cta861_3, vec);
-            if (!ret.isOk()) {
-                err = C2_REFUSED;
-            } else if (ret != Error4::NONE) {
+        if (0.0 <= cta861_3->maxContentLightLevel && 0.0 <= cta861_3->maxFrameAverageLightLevel) {
+            status = mapper.setCta861_3(buffer.get(), cta861_3);
+            if (status != OK) {
                 err = C2_CORRUPTED;
             }
         }
     }
     if (dynamicInfo && *dynamicInfo && dynamicInfo->flexCount() > 0) {
-        ALOGV("Setting dynamic HDR info as gralloc4 metadata");
-        std::optional<IMapper4::MetadataType> metadataType;
-        switch (dynamicInfo->m.type_) {
-        case C2Config::HDR_DYNAMIC_METADATA_TYPE_SMPTE_2094_10:
-            // TODO
-            break;
-        case C2Config::HDR_DYNAMIC_METADATA_TYPE_SMPTE_2094_40:
-            metadataType = MetadataType_Smpte2094_40;
-            break;
-        }
+        ALOGV("Setting dynamic HDR info as gralloc metadata");
+        if (dynamicInfo->m.type_ == C2Config::HDR_DYNAMIC_METADATA_TYPE_SMPTE_2094_40) {
+            std::optional<std::vector<uint8_t>> smpte2094_40 = std::vector<uint8_t>();
+            smpte2094_40->resize(dynamicInfo->flexCount());
+            memcpy(smpte2094_40->data(), dynamicInfo->m.data, dynamicInfo->flexCount());
 
-        if (metadataType) {
-            std::vector<uint8_t> smpte2094_40;
-            smpte2094_40.resize(dynamicInfo->flexCount());
-            memcpy(smpte2094_40.data(), dynamicInfo->m.data, dynamicInfo->flexCount());
-
-            hidl_vec<uint8_t> vec;
-            if (gralloc4::encodeSmpte2094_40({ smpte2094_40 }, &vec) == OK) {
-                Return<Error4> ret = mapper->set(buffer.get(), *metadataType, vec);
-                if (!ret.isOk()) {
-                    err = C2_REFUSED;
-                } else if (ret != Error4::NONE) {
-                    err = C2_CORRUPTED;
-                }
+            status = mapper.setSmpte2094_40(buffer.get(), smpte2094_40);
+            if (status != OK) {
+                err = C2_CORRUPTED;
             }
         } else {
             err = C2_BAD_VALUE;
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/codec2/vndk/internal/C2BlockInternal.h b/media/codec2/vndk/internal/C2BlockInternal.h
index 1eefd87..81cdb43 100644
--- a/media/codec2/vndk/internal/C2BlockInternal.h
+++ b/media/codec2/vndk/internal/C2BlockInternal.h
@@ -17,10 +17,14 @@
 #ifndef ANDROID_STAGEFRIGHT_C2BLOCK_INTERNAL_H_
 #define ANDROID_STAGEFRIGHT_C2BLOCK_INTERNAL_H_
 
-#include <android/hardware/graphics/bufferqueue/2.0/IGraphicBufferProducer.h>
-
 #include <C2Buffer.h>
 
+#include <utils/RefBase.h>
+
+namespace android::hardware::graphics::bufferqueue::V2_0 {
+struct IGraphicBufferProducer;
+}
+
 // Note: HIDL-BufferPool and AIDL-BufferPool are not compatible
 namespace android::hardware::media::bufferpool {
 
diff --git a/media/img_utils/src/FileInput.cpp b/media/img_utils/src/FileInput.cpp
index 4c85a51..1eb614b 100644
--- a/media/img_utils/src/FileInput.cpp
+++ b/media/img_utils/src/FileInput.cpp
@@ -33,12 +33,12 @@
 
 status_t FileInput::open() {
     if (mOpen) {
-        ALOGW("%s: Open called when file %s already open.", __FUNCTION__, mPath.string());
+        ALOGW("%s: Open called when file %s already open.", __FUNCTION__, mPath.c_str());
         return OK;
     }
     mFp = ::fopen(mPath, "rb");
     if (!mFp) {
-        ALOGE("%s: Could not open file %s", __FUNCTION__, mPath.string());
+        ALOGE("%s: Could not open file %s", __FUNCTION__, mPath.c_str());
         return BAD_VALUE;
     }
     mOpen = true;
@@ -47,14 +47,14 @@
 
 ssize_t FileInput::read(uint8_t* buf, size_t offset, size_t count) {
     if (!mOpen) {
-        ALOGE("%s: Could not read file %s, file not open.", __FUNCTION__, mPath.string());
+        ALOGE("%s: Could not read file %s, file not open.", __FUNCTION__, mPath.c_str());
         return BAD_VALUE;
     }
 
     size_t bytesRead = ::fread(buf + offset, sizeof(uint8_t), count, mFp);
     int error = ::ferror(mFp);
     if (error != 0) {
-        ALOGE("%s: Error %d occurred while reading file %s.", __FUNCTION__, error, mPath.string());
+        ALOGE("%s: Error %d occurred while reading file %s.", __FUNCTION__, error, mPath.c_str());
         return BAD_VALUE;
     }
 
@@ -68,13 +68,13 @@
 
 status_t FileInput::close() {
     if(!mOpen) {
-        ALOGW("%s: Close called when file %s already close.", __FUNCTION__, mPath.string());
+        ALOGW("%s: Close called when file %s already close.", __FUNCTION__, mPath.c_str());
         return OK;
     }
 
     status_t ret = OK;
     if(::fclose(mFp) != 0) {
-        ALOGE("%s: Failed to close file %s.", __FUNCTION__, mPath.string());
+        ALOGE("%s: Failed to close file %s.", __FUNCTION__, mPath.c_str());
         ret = BAD_VALUE;
     }
     mOpen = false;
diff --git a/media/img_utils/src/FileOutput.cpp b/media/img_utils/src/FileOutput.cpp
index 0346762..5e37324 100644
--- a/media/img_utils/src/FileOutput.cpp
+++ b/media/img_utils/src/FileOutput.cpp
@@ -25,19 +25,19 @@
 
 FileOutput::~FileOutput() {
     if (mOpen) {
-        ALOGW("%s: Destructor called with %s still open.", __FUNCTION__, mPath.string());
+        ALOGW("%s: Destructor called with %s still open.", __FUNCTION__, mPath.c_str());
         close();
     }
 }
 
 status_t FileOutput::open() {
     if (mOpen) {
-        ALOGW("%s: Open called when file %s already open.", __FUNCTION__, mPath.string());
+        ALOGW("%s: Open called when file %s already open.", __FUNCTION__, mPath.c_str());
         return OK;
     }
     mFp = ::fopen(mPath, "wb");
     if (!mFp) {
-        ALOGE("%s: Could not open file %s", __FUNCTION__, mPath.string());
+        ALOGE("%s: Could not open file %s", __FUNCTION__, mPath.c_str());
         return BAD_VALUE;
     }
     mOpen = true;
@@ -46,7 +46,7 @@
 
 status_t FileOutput::write(const uint8_t* buf, size_t offset, size_t count) {
     if (!mOpen) {
-        ALOGE("%s: Could not write file %s, file not open.", __FUNCTION__, mPath.string());
+        ALOGE("%s: Could not write file %s, file not open.", __FUNCTION__, mPath.c_str());
         return BAD_VALUE;
     }
 
@@ -54,7 +54,7 @@
 
     int error = ::ferror(mFp);
     if (error != 0) {
-        ALOGE("%s: Error %d occurred while writing file %s.", __FUNCTION__, error, mPath.string());
+        ALOGE("%s: Error %d occurred while writing file %s.", __FUNCTION__, error, mPath.c_str());
         return BAD_VALUE;
     }
     return OK;
@@ -62,13 +62,13 @@
 
 status_t FileOutput::close() {
     if(!mOpen) {
-        ALOGW("%s: Close called when file %s already close.", __FUNCTION__, mPath.string());
+        ALOGW("%s: Close called when file %s already close.", __FUNCTION__, mPath.c_str());
         return OK;
     }
 
     status_t ret = OK;
     if(::fclose(mFp) != 0) {
-        ALOGE("%s: Failed to close file %s.", __FUNCTION__, mPath.string());
+        ALOGE("%s: Failed to close file %s.", __FUNCTION__, mPath.c_str());
         ret = BAD_VALUE;
     }
     mOpen = false;
diff --git a/media/img_utils/src/TiffIfd.cpp b/media/img_utils/src/TiffIfd.cpp
index 3fb00cc..b272814 100644
--- a/media/img_utils/src/TiffIfd.cpp
+++ b/media/img_utils/src/TiffIfd.cpp
@@ -377,7 +377,7 @@
     size_t s = mEntries.size();
     ALOGI("[ifd: %x, num_entries: %zu, entries:\n", getId(), s);
     for(size_t i = 0; i < s; ++i) {
-        ALOGI("\t%s", mEntries[i]->toString().string());
+        ALOGI("\t%s", mEntries[i]->toString().c_str());
     }
     ALOGI(", next_ifd: %x]", ((mNextIfd != NULL) ? mNextIfd->getId() : 0));
 }
diff --git a/media/libaaudio/include/aaudio/AAudio.h b/media/libaaudio/include/aaudio/AAudio.h
index 74f7e6b..c3b32e6 100644
--- a/media/libaaudio/include/aaudio/AAudio.h
+++ b/media/libaaudio/include/aaudio/AAudio.h
@@ -539,6 +539,22 @@
      * Available since API level 29.
      */
     AAUDIO_INPUT_PRESET_VOICE_PERFORMANCE = 10,
+
+    /**
+     * Use this preset for an echo canceller to capture the reference signal.
+     * Reserved for system components.
+     * Requires CAPTURE_AUDIO_OUTPUT permission
+     * Available since API level 35.
+     */
+    AAUDIO_INPUT_PRESET_SYSTEM_ECHO_REFERENCE = 1997,
+
+    /**
+     * Use this preset for preemptible, low-priority software hotword detection.
+     * Reserved for system components.
+     * Requires CAPTURE_AUDIO_HOTWORD permission.
+     * Available since API level 35.
+     */
+    AAUDIO_INPUT_PRESET_SYSTEM_HOTWORD = 1999,
 };
 typedef int32_t aaudio_input_preset_t;
 
diff --git a/media/libaaudio/src/core/AAudioStreamParameters.cpp b/media/libaaudio/src/core/AAudioStreamParameters.cpp
index f305e46..1db62f3 100644
--- a/media/libaaudio/src/core/AAudioStreamParameters.cpp
+++ b/media/libaaudio/src/core/AAudioStreamParameters.cpp
@@ -184,6 +184,8 @@
         case AAUDIO_INPUT_PRESET_VOICE_RECOGNITION:
         case AAUDIO_INPUT_PRESET_UNPROCESSED:
         case AAUDIO_INPUT_PRESET_VOICE_PERFORMANCE:
+        case AAUDIO_INPUT_PRESET_SYSTEM_ECHO_REFERENCE:
+        case AAUDIO_INPUT_PRESET_SYSTEM_HOTWORD:
             break; // valid
         default:
             ALOGD("input preset not valid = %d", mInputPreset);
@@ -317,4 +319,4 @@
     ALOGD("mHardwareSamplesPerFrame = %6d", mHardwareSamplesPerFrame);
     ALOGD("mHardwareSampleRate   = %6d", mHardwareSampleRate);
     ALOGD("mHardwareAudioFormat  = %6d", (int)mHardwareAudioFormat);
-}
\ No newline at end of file
+}
diff --git a/media/libaudioclient/Android.bp b/media/libaudioclient/Android.bp
index 01e3d53..d35708c 100644
--- a/media/libaudioclient/Android.bp
+++ b/media/libaudioclient/Android.bp
@@ -336,6 +336,7 @@
     srcs: [
         "aidl/android/media/AudioAttributesEx.aidl",
         "aidl/android/media/AudioMix.aidl",
+        "aidl/android/media/AudioMixUpdate.aidl",
         "aidl/android/media/AudioMixerAttributesInternal.aidl",
         "aidl/android/media/AudioMixerBehavior.aidl",
         "aidl/android/media/AudioMixCallbackFlag.aidl",
diff --git a/media/libaudioclient/AudioRecord.cpp b/media/libaudioclient/AudioRecord.cpp
index f07ea1d..073a030 100644
--- a/media/libaudioclient/AudioRecord.cpp
+++ b/media/libaudioclient/AudioRecord.cpp
@@ -760,7 +760,7 @@
                         mInput, mLatency, mSelectedDeviceId, mRoutedDeviceId);
     result.appendFormat("  mic direction(%d) mic field dimension(%f)",
                         mSelectedMicDirection, mSelectedMicFieldDimension);
-    ::write(fd, result.string(), result.size());
+    ::write(fd, result.c_str(), result.size());
     return NO_ERROR;
 }
 
diff --git a/media/libaudioclient/AudioSystem.cpp b/media/libaudioclient/AudioSystem.cpp
index 763de70..5bfdd5f 100644
--- a/media/libaudioclient/AudioSystem.cpp
+++ b/media/libaudioclient/AudioSystem.cpp
@@ -20,6 +20,7 @@
 #include <utils/Log.h>
 
 #include <android/media/IAudioPolicyService.h>
+#include <android/media/AudioMixUpdate.h>
 #include <android/media/BnCaptureStateListener.h>
 #include <binder/IServiceManager.h>
 #include <binder/ProcessState.h>
@@ -87,7 +88,7 @@
 void AudioSystem::setAudioFlingerBinder(const sp<IBinder>& audioFlinger) {
     if (audioFlinger->getInterfaceDescriptor() != media::IAudioFlingerService::descriptor) {
         ALOGE("setAudioFlingerBinder: received a binder of type %s",
-              String8(audioFlinger->getInterfaceDescriptor()).string());
+              String8(audioFlinger->getInterfaceDescriptor()).c_str());
         return;
     }
     Mutex::Autolock _l(gLock);
@@ -1842,6 +1843,27 @@
     return statusTFromBinderStatus(aps->registerPolicyMixes(mixesAidl, registration));
 }
 
+status_t AudioSystem::updatePolicyMixes(
+        const std::vector<std::pair<AudioMix, std::vector<AudioMixMatchCriterion>>>&
+                mixesWithUpdates) {
+    const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+    if (aps == 0) return PERMISSION_DENIED;
+
+    std::vector<media::AudioMixUpdate> updatesAidl;
+    updatesAidl.reserve(mixesWithUpdates.size());
+
+    for (const auto& update : mixesWithUpdates) {
+        media::AudioMixUpdate updateAidl;
+        updateAidl.audioMix = VALUE_OR_RETURN_STATUS(legacy2aidl_AudioMix(update.first));
+        RETURN_STATUS_IF_ERROR(convertRange(update.second.begin(), update.second.end(),
+                                            std::back_inserter(updateAidl.newCriteria),
+                                            legacy2aidl_AudioMixMatchCriterion));
+        updatesAidl.emplace_back(updateAidl);
+    }
+
+    return statusTFromBinderStatus(aps->updatePolicyMixes(updatesAidl));
+}
+
 status_t AudioSystem::setUidDeviceAffinities(uid_t uid, const AudioDeviceTypeAddrVector& devices) {
     const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
     if (aps == 0) return PERMISSION_DENIED;
diff --git a/media/libaudioclient/AudioTrack.cpp b/media/libaudioclient/AudioTrack.cpp
index 4269aa2..8b8f7cd 100644
--- a/media/libaudioclient/AudioTrack.cpp
+++ b/media/libaudioclient/AudioTrack.cpp
@@ -3036,7 +3036,7 @@
     param.addInt(String8(AudioParameter::keyPresentationId), presentationId);
     param.addInt(String8(AudioParameter::keyProgramId), programId);
     ALOGV("%s(%d): PresentationId/ProgramId[%s]",
-            __func__, mPortId, param.toString().string());
+            __func__, mPortId, param.toString().c_str());
 
     status_t status;
     mAudioTrack->setParameters(param.toString().c_str(), &status);
@@ -3479,7 +3479,7 @@
     if (output != AUDIO_IO_HANDLE_NONE) {
         return AudioSystem::getParameters(output, keys);
     } else {
-        return String8::empty();
+        return String8();
     }
 }
 
@@ -3525,7 +3525,7 @@
                         mLatency, mSelectedDeviceId, mRoutedDeviceId);
     result.appendFormat("  output(%d) AF latency (%u) AF frame count(%zu) AF SampleRate(%u)\n",
                         mOutput, mAfLatency, mAfFrameCount, mAfSampleRate);
-    ::write(fd, result.string(), result.size());
+    ::write(fd, result.c_str(), result.size());
     return NO_ERROR;
 }
 
diff --git a/media/libaudioclient/aidl/android/media/AudioMixUpdate.aidl b/media/libaudioclient/aidl/android/media/AudioMixUpdate.aidl
new file mode 100644
index 0000000..d481b1c
--- /dev/null
+++ b/media/libaudioclient/aidl/android/media/AudioMixUpdate.aidl
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media;
+
+import android.media.AudioMix;
+import android.media.AudioMixMatchCriterion;
+
+
+/**
+ * {@hide}
+ */
+parcelable AudioMixUpdate {
+    // Audio mix to update.
+    AudioMix audioMix;
+    // Updated audio mixing rule.
+    AudioMixMatchCriterion[] newCriteria;
+}
diff --git a/media/libaudioclient/aidl/android/media/IAudioPolicyService.aidl b/media/libaudioclient/aidl/android/media/IAudioPolicyService.aidl
index 3e9b27f..52c8da0 100644
--- a/media/libaudioclient/aidl/android/media/IAudioPolicyService.aidl
+++ b/media/libaudioclient/aidl/android/media/IAudioPolicyService.aidl
@@ -20,6 +20,7 @@
 
 import android.media.AudioDirectMode;
 import android.media.AudioMix;
+import android.media.AudioMixUpdate;
 import android.media.AudioMixerAttributesInternal;
 import android.media.AudioOffloadMode;
 import android.media.AudioPatchFw;
@@ -262,6 +263,8 @@
 
     void registerPolicyMixes(in AudioMix[] mixes, boolean registration);
 
+    void updatePolicyMixes(in AudioMixUpdate[] updates);
+
     void setUidDeviceAffinities(int /* uid_t */ uid, in AudioDevice[] devices);
 
     void removeUidDeviceAffinities(int /* uid_t */ uid);
diff --git a/media/libaudioclient/include/media/AudioSystem.h b/media/libaudioclient/include/media/AudioSystem.h
index 0215f3c..a1f7941 100644
--- a/media/libaudioclient/include/media/AudioSystem.h
+++ b/media/libaudioclient/include/media/AudioSystem.h
@@ -462,6 +462,10 @@
 
     static status_t registerPolicyMixes(const Vector<AudioMix>& mixes, bool registration);
 
+    static status_t updatePolicyMixes(
+        const std::vector<
+                std::pair<AudioMix, std::vector<AudioMixMatchCriterion>>>& mixesWithUpdates);
+
     static status_t setUidDeviceAffinities(uid_t uid, const AudioDeviceTypeAddrVector& devices);
 
     static status_t removeUidDeviceAffinities(uid_t uid);
diff --git a/media/libaudioclient/tests/audio_aidl_legacy_conversion_tests.cpp b/media/libaudioclient/tests/audio_aidl_legacy_conversion_tests.cpp
index 976a532..9a46b20 100644
--- a/media/libaudioclient/tests/audio_aidl_legacy_conversion_tests.cpp
+++ b/media/libaudioclient/tests/audio_aidl_legacy_conversion_tests.cpp
@@ -143,7 +143,8 @@
 }
 
 AudioDeviceDescription make_ADD_RSubmixIn() {
-    return make_AudioDeviceDescription(AudioDeviceType::IN_SUBMIX);
+    return make_AudioDeviceDescription(AudioDeviceType::IN_SUBMIX,
+                                       AudioDeviceDescription::CONNECTION_VIRTUAL());
 }
 
 AudioDeviceDescription make_ADD_DefaultOut() {
diff --git a/media/libaudioclient/tests/audiotrack_tests.cpp b/media/libaudioclient/tests/audiotrack_tests.cpp
index 8daba0a..2b68225 100644
--- a/media/libaudioclient/tests/audiotrack_tests.cpp
+++ b/media/libaudioclient/tests/audiotrack_tests.cpp
@@ -144,7 +144,7 @@
     EXPECT_EQ(cb->mDeviceId, ap->getAudioTrackHandle()->getRoutedDeviceId());
     String8 keys;
     keys = ap->getAudioTrackHandle()->getParameters(keys);
-    if (!keys.isEmpty()) {
+    if (!keys.empty()) {
         std::cerr << "track parameters :: " << keys << std::endl;
     }
     EXPECT_TRUE(checkPatchPlayback(cb->mAudioIo, cb->mDeviceId));
diff --git a/media/libaudiohal/impl/ConversionHelperAidl.cpp b/media/libaudiohal/impl/ConversionHelperAidl.cpp
index 7197bf2..46abfda 100644
--- a/media/libaudiohal/impl/ConversionHelperAidl.cpp
+++ b/media/libaudiohal/impl/ConversionHelperAidl.cpp
@@ -69,7 +69,7 @@
         // Re-parse the vendor-provided string to ensure that it is correct.
         AudioParameter reparse(String8(vendorParameters.c_str()));
         if (reparse.size() != 0) {
-            if (!values->empty()) {
+            if (values->length() > 0) {
                 values->append(";");
             }
             values->append(reparse.toString().c_str());
diff --git a/media/libaudiohal/impl/CoreConversionHelperHidl.cpp b/media/libaudiohal/impl/CoreConversionHelperHidl.cpp
index 2ac8a42..b801187 100644
--- a/media/libaudiohal/impl/CoreConversionHelperHidl.cpp
+++ b/media/libaudiohal/impl/CoreConversionHelperHidl.cpp
@@ -69,7 +69,7 @@
             keepValueParam.add(key, value);
             key = keepValueParam.toString();
         }
-        (*hidlKeys)[i] = key.string();
+        (*hidlKeys)[i] = key.c_str();
     }
     return OK;
 }
@@ -84,8 +84,8 @@
         String8 key, value;
         status_t status = params.getAt(i, key, value);
         if (status != OK) return status;
-        (*hidlParams)[i].key = key.string();
-        (*hidlParams)[i].value = value.string();
+        (*hidlParams)[i].key = key.c_str();
+        (*hidlParams)[i].value = value.c_str();
     }
     return OK;
 }
@@ -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/impl/EffectConversionHelperAidl.cpp b/media/libaudiohal/impl/EffectConversionHelperAidl.cpp
index 9cf0cb8..4e34fca 100644
--- a/media/libaudiohal/impl/EffectConversionHelperAidl.cpp
+++ b/media/libaudiohal/impl/EffectConversionHelperAidl.cpp
@@ -25,6 +25,7 @@
 #include <media/AidlConversionCppNdk.h>
 #include <media/AidlConversionNdk.h>
 #include <media/AidlConversionEffect.h>
+#include <media/AudioContainers.h>
 #include <system/audio_effects/effect_visualizer.h>
 
 #include <utils/Log.h>
@@ -61,6 +62,7 @@
                 {EFFECT_CMD_RESET, &EffectConversionHelperAidl::handleReset},
                 {EFFECT_CMD_ENABLE, &EffectConversionHelperAidl::handleEnable},
                 {EFFECT_CMD_DISABLE, &EffectConversionHelperAidl::handleDisable},
+                {EFFECT_CMD_SET_AUDIO_MODE, &EffectConversionHelperAidl::handleSetAudioMode},
                 {EFFECT_CMD_SET_AUDIO_SOURCE, &EffectConversionHelperAidl::handleSetAudioSource},
                 {EFFECT_CMD_SET_DEVICE, &EffectConversionHelperAidl::handleSetDevice},
                 {EFFECT_CMD_SET_INPUT_DEVICE, &EffectConversionHelperAidl::handleSetDevice},
@@ -279,6 +281,10 @@
               pReplyData);
         return BAD_VALUE;
     }
+    if (!getDescriptor().common.flags.audioSourceIndication) {
+        ALOGW("%s parameter no audioSourceIndication, skipping", __func__);
+        return OK;
+    }
 
     audio_source_t source = *(audio_source_t*)pCmdData;
     AudioSource aidlSource =
@@ -295,6 +301,10 @@
               pReplyData);
         return BAD_VALUE;
     }
+    if (!getDescriptor().common.flags.audioModeIndication) {
+        ALOGW("%s parameter no audioModeIndication, skipping", __func__);
+        return OK;
+    }
     audio_mode_t mode = *(audio_mode_t *)pCmdData;
     AudioMode aidlMode =
             VALUE_OR_RETURN_STATUS(::aidl::android::legacy2aidl_audio_mode_t_AudioMode(mode));
@@ -310,9 +320,26 @@
               pReplyData);
         return BAD_VALUE;
     }
-    // TODO: convert from audio_devices_t to std::vector<AudioDeviceDescription>
-    // const auto& legacyDevice = *(uint32_t*)(pCmdData);
+    if (!getDescriptor().common.flags.deviceIndication) {
+        ALOGW("%s parameter no deviceIndication, skipping", __func__);
+        return OK;
+    }
+    // convert from bitmask of audio_devices_t to std::vector<AudioDeviceDescription>
+    auto legacyDevices = *(uint32_t*)(pCmdData);
+    // extract the input bit and remove it from bitmasks
+    const auto inputBit = legacyDevices & AUDIO_DEVICE_BIT_IN;
+    legacyDevices &= ~AUDIO_DEVICE_BIT_IN;
     std::vector<AudioDeviceDescription> aidlDevices;
+    while (legacyDevices) {
+        // get audio_devices_t represented by the last true bit and convert to AIDL
+        const auto lowestBitDevice = legacyDevices & -legacyDevices;
+        AudioDeviceDescription deviceDesc = VALUE_OR_RETURN_STATUS(
+                ::aidl::android::legacy2aidl_audio_devices_t_AudioDeviceDescription(
+                        static_cast<audio_devices_t>(lowestBitDevice | inputBit)));
+        aidlDevices.emplace_back(deviceDesc);
+        legacyDevices -= lowestBitDevice;
+    }
+
     RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
             mEffect->setParameter(Parameter::make<Parameter::deviceDescription>(aidlDevices))));
     return *static_cast<int32_t*>(pReplyData) = OK;
@@ -435,5 +462,19 @@
             (mIsProxyEffect && std::static_pointer_cast<EffectProxy>(mEffect)->isBypassing()));
 }
 
+Descriptor EffectConversionHelperAidl::getDescriptor() const {
+    if (!mIsProxyEffect) {
+        return mDesc;
+    }
+
+    Descriptor desc;
+    if (const auto status = mEffect->getDescriptor(&desc); !status.isOk()) {
+        ALOGE("%s failed to get proxy descriptor (%d:%s), using default", __func__,
+              status.getStatus(), status.getMessage());
+        return mDesc;
+    }
+    return desc;
+}
+
 }  // namespace effect
 }  // namespace android
diff --git a/media/libaudiohal/impl/EffectConversionHelperAidl.h b/media/libaudiohal/impl/EffectConversionHelperAidl.h
index 7c8f11b..85e877e 100644
--- a/media/libaudiohal/impl/EffectConversionHelperAidl.h
+++ b/media/libaudiohal/impl/EffectConversionHelperAidl.h
@@ -43,6 +43,8 @@
     std::shared_ptr<android::hardware::EventFlag> getEventFlagGroup() { return mEfGroup; }
     bool isBypassing() const;
 
+    ::aidl::android::hardware::audio::effect::Descriptor getDescriptor() const;
+
   protected:
     const int32_t mSessionId;
     const int32_t mIoId;
@@ -134,7 +136,6 @@
     virtual status_t visualizerMeasure(uint32_t* replySize __unused, void* pReplyData __unused) {
         return BAD_VALUE;
     }
-
 };
 
 }  // namespace effect
diff --git a/media/libaudiohal/impl/EffectHalAidl.cpp b/media/libaudiohal/impl/EffectHalAidl.cpp
index b8e62ae..642d352 100644
--- a/media/libaudiohal/impl/EffectHalAidl.cpp
+++ b/media/libaudiohal/impl/EffectHalAidl.cpp
@@ -69,7 +69,6 @@
       mEffect(effect),
       mSessionId(sessionId),
       mIoId(ioId),
-      mDesc(desc),
       mIsProxyEffect(isProxyEffect) {
     createAidlConversion(effect, sessionId, ioId, desc);
 }
@@ -169,7 +168,8 @@
     State state = State::INIT;
     if (mConversion->isBypassing() || !mEffect->getState(&state).isOk() ||
         state != State::PROCESSING) {
-        ALOGI("%s skipping %s process because it's %s", __func__, mDesc.common.name.c_str(),
+        ALOGI("%s skipping %s process because it's %s", __func__,
+              mConversion->getDescriptor().common.name.c_str(),
               mConversion->isBypassing()
                       ? "bypassing"
                       : aidl::android::hardware::audio::effect::toString(state).c_str());
@@ -225,8 +225,8 @@
         return INVALID_OPERATION;
     }
 
-    ALOGD("%s %s consumed %zu produced %zu", __func__, mDesc.common.name.c_str(), floatsToWrite,
-          floatsToRead);
+    ALOGD("%s %s consumed %zu produced %zu", __func__,
+          mConversion->getDescriptor().common.name.c_str(), floatsToWrite, floatsToRead);
     return OK;
 }
 
diff --git a/media/libaudiohal/impl/EffectHalAidl.h b/media/libaudiohal/impl/EffectHalAidl.h
index 1b7a3d6..bbcb7e2 100644
--- a/media/libaudiohal/impl/EffectHalAidl.h
+++ b/media/libaudiohal/impl/EffectHalAidl.h
@@ -72,7 +72,6 @@
     const std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> mEffect;
     const int32_t mSessionId;
     const int32_t mIoId;
-    const ::aidl::android::hardware::audio::effect::Descriptor mDesc;
     const bool mIsProxyEffect;
 
     std::unique_ptr<EffectConversionHelperAidl> mConversion;
diff --git a/media/libaudiohal/impl/EffectProxy.cpp b/media/libaudiohal/impl/EffectProxy.cpp
index 8b629ed..7b5e195 100644
--- a/media/libaudiohal/impl/EffectProxy.cpp
+++ b/media/libaudiohal/impl/EffectProxy.cpp
@@ -169,12 +169,6 @@
             common.flags.hwAcceleratorMode = Flags::HardwareAccelerator::TUNNEL;
         }
 
-        // initial flag values before we know which sub-effect to active (with setOffloadParam)
-        // same as HIDL EffectProxy flags
-        common.flags.type = Flags::Type::INSERT;
-        common.flags.insert = Flags::Insert::LAST;
-        common.flags.volume = Flags::Volume::NONE;
-
         // set indication if any sub-effect indication was set
         common.flags.offloadIndication |= desc.common.flags.offloadIndication;
         common.flags.deviceIndication |= desc.common.flags.deviceIndication;
diff --git a/media/libaudiohal/impl/StreamHalAidl.cpp b/media/libaudiohal/impl/StreamHalAidl.cpp
index 80e19a0..f9aea37 100644
--- a/media/libaudiohal/impl/StreamHalAidl.cpp
+++ b/media/libaudiohal/impl/StreamHalAidl.cpp
@@ -267,7 +267,11 @@
     if (status_t status = updateCountersIfNeeded(&reply); status != OK) {
         return status;
     }
-    *latency = std::max<int32_t>(0, reply.latencyMs);
+
+    *latency = std::clamp(std::max<int32_t>(0, reply.latencyMs), 1, 3000);
+    ALOGW_IF(reply.latencyMs != static_cast<int32_t>(*latency),
+             "Suspicious latency value reported by HAL: %d, clamped to %u", reply.latencyMs,
+             *latency);
     return OK;
 }
 
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/libaudiohal/tests/EffectsFactoryHalInterface_test.cpp b/media/libaudiohal/tests/EffectsFactoryHalInterface_test.cpp
index 2854496..0cb654c 100644
--- a/media/libaudiohal/tests/EffectsFactoryHalInterface_test.cpp
+++ b/media/libaudiohal/tests/EffectsFactoryHalInterface_test.cpp
@@ -347,6 +347,45 @@
     }
 }
 
+TEST_P(libAudioHalEffectParamTest, deviceIndicationUpdate) {
+    for (auto& interface : mHalInterfaces) {
+        EXPECT_NO_FATAL_FAILURE(initEffect(interface));
+
+        // output device
+        uint32_t deviceTypes = AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_BLE_SPEAKER;
+        status_t cmdStatus;
+        uint32_t replySize = sizeof(cmdStatus);
+        EXPECT_EQ(OK, interface->command(EFFECT_CMD_SET_DEVICE, sizeof(uint32_t), &deviceTypes,
+                                         &replySize, &cmdStatus));
+        // input device
+        deviceTypes = AUDIO_DEVICE_IN_WIRED_HEADSET | AUDIO_DEVICE_IN_BLUETOOTH_BLE;
+        EXPECT_EQ(OK, interface->command(EFFECT_CMD_SET_DEVICE, sizeof(uint32_t), &deviceTypes,
+                                         &replySize, &cmdStatus));
+    }
+}
+
+TEST_P(libAudioHalEffectParamTest, audioModeIndicationUpdate) {
+    for (auto& interface : mHalInterfaces) {
+        EXPECT_NO_FATAL_FAILURE(initEffect(interface));
+        uint32_t mode = AUDIO_MODE_IN_CALL;
+        status_t cmdStatus;
+        uint32_t replySize = sizeof(cmdStatus);
+        EXPECT_EQ(OK, interface->command(EFFECT_CMD_SET_AUDIO_MODE, sizeof(uint32_t), &mode,
+                                         &replySize, &cmdStatus));
+    }
+}
+
+TEST_P(libAudioHalEffectParamTest, audioSourceIndicationUpdate) {
+    for (auto& interface : mHalInterfaces) {
+        EXPECT_NO_FATAL_FAILURE(initEffect(interface));
+        uint32_t source = AUDIO_SOURCE_MIC;
+        status_t cmdStatus;
+        uint32_t replySize = sizeof(cmdStatus);
+        EXPECT_EQ(OK, interface->command(EFFECT_CMD_SET_AUDIO_SOURCE, sizeof(uint32_t), &source,
+                                         &replySize, &cmdStatus));
+    }
+}
+
 INSTANTIATE_TEST_SUITE_P(
         libAudioHalEffectParamTest, libAudioHalEffectParamTest, ::testing::ValuesIn(testPairs),
         [](const testing::TestParamInfo<libAudioHalEffectParamTest::ParamType>& info) {
diff --git a/media/libdatasource/DataSourceFactory.cpp b/media/libdatasource/DataSourceFactory.cpp
index f91e3ea..e9936a3 100644
--- a/media/libdatasource/DataSourceFactory.cpp
+++ b/media/libdatasource/DataSourceFactory.cpp
@@ -92,7 +92,7 @@
 
         source = NuCachedSource2::Create(
                 mediaHTTP,
-                cacheConfig.isEmpty() ? NULL : cacheConfig.string(),
+                cacheConfig.empty() ? NULL : cacheConfig.c_str(),
                 disconnectAtHighwatermark);
     } else if (!strncasecmp("data:", uri, 5)) {
         source = DataURISource::Create(uri);
diff --git a/media/libdatasource/MediaHTTP.cpp b/media/libdatasource/MediaHTTP.cpp
index 58c1ce8..b1f2140 100644
--- a/media/libdatasource/MediaHTTP.cpp
+++ b/media/libdatasource/MediaHTTP.cpp
@@ -156,7 +156,7 @@
 
 String8 MediaHTTP::getUri() {
     if (mInitCheck != OK) {
-        return String8::empty();
+        return String8();
     }
 
     String8 uri;
diff --git a/media/libdatasource/NuCachedSource2.cpp b/media/libdatasource/NuCachedSource2.cpp
index 6d63ffb..4e71d5f 100644
--- a/media/libdatasource/NuCachedSource2.cpp
+++ b/media/libdatasource/NuCachedSource2.cpp
@@ -225,7 +225,7 @@
     // IMediaHTTPConnection::readAt and therefore call back into JAVA.
     mLooper->start(false /* runOnCallingThread */, true /* canCallJava */);
 
-    mName = String8::format("NuCachedSource2(%s)", mSource->toString().string());
+    mName = String8::format("NuCachedSource2(%s)", mSource->toString().c_str());
 }
 
 NuCachedSource2::~NuCachedSource2() {
@@ -765,7 +765,7 @@
 
         headers->removeItemsAt(index);
 
-        ALOGV("Using special cache config '%s'", cacheConfig->string());
+        ALOGV("Using special cache config '%s'", cacheConfig->c_str());
     }
 
     if ((index = headers->indexOfKey(
diff --git a/media/libheif/HeifDecoderImpl.cpp b/media/libheif/HeifDecoderImpl.cpp
index 6834b7d..085a7e4 100644
--- a/media/libheif/HeifDecoderImpl.cpp
+++ b/media/libheif/HeifDecoderImpl.cpp
@@ -41,8 +41,8 @@
 namespace android {
 
 void initFrameInfo(HeifFrameInfo *info, const VideoFrame *videoFrame) {
-    info->mWidth = videoFrame->mWidth;
-    info->mHeight = videoFrame->mHeight;
+    info->mWidth = videoFrame->mDisplayWidth;
+    info->mHeight = videoFrame->mDisplayHeight;
     info->mRotationAngle = videoFrame->mRotationAngle;
     info->mBytesPerPixel = videoFrame->mBytesPerPixel;
     info->mDurationUs = videoFrame->mDurationUs;
@@ -742,8 +742,11 @@
     //       Either document why it is safe in this case or address the
     //       issue (e.g. by copying).
     VideoFrame* videoFrame = static_cast<VideoFrame*>(mFrameMemory->unsecurePointer());
-    uint8_t* src = videoFrame->getFlattenedData() + videoFrame->mRowBytes * mCurScanline++;
-    memcpy(dst, src, videoFrame->mBytesPerPixel * videoFrame->mWidth);
+    uint8_t* src = videoFrame->getFlattenedData() +
+                   (videoFrame->mRowBytes * (mCurScanline + videoFrame->mDisplayTop)) +
+                   (videoFrame->mBytesPerPixel * videoFrame->mDisplayLeft);
+    mCurScanline++;
+    memcpy(dst, src, videoFrame->mBytesPerPixel * videoFrame->mDisplayWidth);
     return true;
 }
 
diff --git a/media/libmedia/IMediaExtractor.cpp b/media/libmedia/IMediaExtractor.cpp
index eb436d1..8485ac0 100644
--- a/media/libmedia/IMediaExtractor.cpp
+++ b/media/libmedia/IMediaExtractor.cpp
@@ -304,7 +304,7 @@
     }
     for (size_t i = 0; i < tracks.size(); i++) {
         const String8 desc = trackDescriptions.itemAt(i);
-        str.appendFormat("    track {%s} ", desc.string());
+        str.appendFormat("    track {%s} ", desc.c_str());
         wp<IMediaSource> wSource = tracks.itemAt(i);
         if (wSource == NULL) {
             str.append(": null\n");
@@ -339,7 +339,7 @@
             if (source != NULL) {
                 instance.trackDescriptions.push_front(source->getFormat()->toString());
             } else {
-                instance.trackDescriptions.push_front(String8::empty());
+                instance.trackDescriptions.push_front(String8());
             }
             break;
         }
@@ -386,7 +386,7 @@
             }
         }
     }
-    write(fd, out.string(), out.size());
+    write(fd, out.c_str(), out.size());
     return OK;
 }
 
diff --git a/media/libmedia/IMediaHTTPConnection.cpp b/media/libmedia/IMediaHTTPConnection.cpp
index 8cbb4c2..b029b97 100644
--- a/media/libmedia/IMediaHTTPConnection.cpp
+++ b/media/libmedia/IMediaHTTPConnection.cpp
@@ -54,8 +54,8 @@
         tmp = String16("");
         if (headers != NULL) {
             for (size_t i = 0; i < headers->size(); ++i) {
-                String16 key(headers->keyAt(i).string());
-                String16 val(headers->valueAt(i).string());
+                String16 key(headers->keyAt(i).c_str());
+                String16 val(headers->valueAt(i).c_str());
 
                 tmp.append(key);
                 tmp.append(String16(": "));
diff --git a/media/libmedia/IMediaMetadataRetriever.cpp b/media/libmedia/IMediaMetadataRetriever.cpp
index 86427ed..cdb1837 100644
--- a/media/libmedia/IMediaMetadataRetriever.cpp
+++ b/media/libmedia/IMediaMetadataRetriever.cpp
@@ -218,7 +218,7 @@
             } else {
                 mMetadata.replaceValueFor(keyCode, value);
             }
-            return mMetadata.valueFor(keyCode).string();
+            return mMetadata.valueFor(keyCode).c_str();
         } else {
             return NULL;
         }
diff --git a/media/libmedia/IMediaRecorder.cpp b/media/libmedia/IMediaRecorder.cpp
index e191999..755a147 100644
--- a/media/libmedia/IMediaRecorder.cpp
+++ b/media/libmedia/IMediaRecorder.cpp
@@ -255,7 +255,7 @@
 
     status_t setParameters(const String8& params)
     {
-        ALOGV("setParameter(%s)", params.string());
+        ALOGV("setParameter(%s)", params.c_str());
         Parcel data, reply;
         data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
         data.writeString8(params);
@@ -275,7 +275,7 @@
 
     status_t setClientName(const String16& clientName)
     {
-        ALOGV("setClientName(%s)", String8(clientName).string());
+        ALOGV("setClientName(%s)", String8(clientName).c_str());
         Parcel data, reply;
         data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
         data.writeString16(clientName);
diff --git a/media/libmedia/include/media/omx/1.0/Conversion.h b/media/libmedia/include/media/omx/1.0/Conversion.h
index 37cb059..af25015 100644
--- a/media/libmedia/include/media/omx/1.0/Conversion.h
+++ b/media/libmedia/include/media/omx/1.0/Conversion.h
@@ -811,11 +811,11 @@
  */
 // convert: IOMX::ComponentInfo -> IOmx::ComponentInfo
 inline bool convertTo(IOmx::ComponentInfo* t, IOMX::ComponentInfo const& l) {
-    t->mName = l.mName.string();
+    t->mName = l.mName.c_str();
     t->mRoles.resize(l.mRoles.size());
     size_t i = 0;
     for (auto& role : l.mRoles) {
-        t->mRoles[i++] = role.string();
+        t->mRoles[i++] = role.c_str();
     }
     return true;
 }
diff --git a/media/libmedia/mediarecorder.cpp b/media/libmedia/mediarecorder.cpp
index bd06fb6..48f5e4b 100644
--- a/media/libmedia/mediarecorder.cpp
+++ b/media/libmedia/mediarecorder.cpp
@@ -472,7 +472,7 @@
 }
 
 status_t MediaRecorder::setParameters(const String8& params) {
-    ALOGV("setParameters(%s)", params.string());
+    ALOGV("setParameters(%s)", params.c_str());
     if (mMediaRecorder == NULL) {
         ALOGE("media recorder is not initialized yet");
         return INVALID_OPERATION;
@@ -496,7 +496,7 @@
 
     status_t ret = mMediaRecorder->setParameters(params);
     if (OK != ret) {
-        ALOGE("setParameters(%s) failed: %d", params.string(), ret);
+        ALOGE("setParameters(%s) failed: %d", params.c_str(), ret);
         // Do not change our current state to MEDIA_RECORDER_ERROR, failures
         // of the only currently supported parameters, "max-duration" and
         // "max-filesize" are _not_ fatal.
diff --git a/media/libmediahelper/AudioParameter.cpp b/media/libmediahelper/AudioParameter.cpp
index c081629..f21ea53 100644
--- a/media/libmediahelper/AudioParameter.cpp
+++ b/media/libmediahelper/AudioParameter.cpp
@@ -96,7 +96,7 @@
     mKeyValuePairs = keyValuePairs;
     char *last;
 
-    strcpy(str, keyValuePairs.string());
+    strcpy(str, keyValuePairs.c_str());
     char *pair = strtok_r(str, ";", &last);
     while (pair != NULL) {
         if (strlen(pair) != 0) {
@@ -208,7 +208,7 @@
     value = 0;
     if (result == NO_ERROR) {
         int val;
-        if (sscanf(str8.string(), "%d", &val) == 1) {
+        if (sscanf(str8.c_str(), "%d", &val) == 1) {
             value = val;
         } else {
             result = INVALID_OPERATION;
@@ -224,7 +224,7 @@
     value = 0;
     if (result == NO_ERROR) {
         float val;
-        if (sscanf(str8.string(), "%f", &val) == 1) {
+        if (sscanf(str8.c_str(), "%f", &val) == 1) {
             value = val;
         } else {
             result = INVALID_OPERATION;
diff --git a/media/libmediametrics/MediaMetrics.cpp b/media/libmediametrics/MediaMetrics.cpp
index 2240223..26fe306 100644
--- a/media/libmediametrics/MediaMetrics.cpp
+++ b/media/libmediametrics/MediaMetrics.cpp
@@ -87,7 +87,7 @@
 }
 
 void mediametrics_setString(mediametrics_handle_t handle, attr_t attr,
-                                 const std::string &string) {
+                            const std::string &string) {
     mediametrics_setCString(handle, attr, string.c_str());
 }
 
diff --git a/media/libmediaplayerservice/Android.bp b/media/libmediaplayerservice/Android.bp
index 44e78d6..718f782 100644
--- a/media/libmediaplayerservice/Android.bp
+++ b/media/libmediaplayerservice/Android.bp
@@ -47,6 +47,7 @@
         "framework-permission-aidl-cpp",
         "libaudioclient_aidl_conversion",
         "libbase",
+        "libbinder_ndk",
         "libactivitymanager_aidl",
         "libandroid_net",
         "libaudioclient",
diff --git a/media/libmediaplayerservice/DeathNotifier.cpp b/media/libmediaplayerservice/DeathNotifier.cpp
index d13bdf5..ab22f67 100644
--- a/media/libmediaplayerservice/DeathNotifier.cpp
+++ b/media/libmediaplayerservice/DeathNotifier.cpp
@@ -31,6 +31,10 @@
     DeathRecipient(Notify const& notify): mNotify{notify} {
     }
 
+    void initNdk() {
+        mNdkRecipient.set(AIBinder_DeathRecipient_new(OnBinderDied));
+    }
+
     virtual void binderDied(wp<IBinder> const&) override {
         mNotify();
     }
@@ -39,8 +43,18 @@
         mNotify();
     }
 
+    static void OnBinderDied(void *cookie) {
+        DeathRecipient *thiz = (DeathRecipient *)cookie;
+        thiz->mNotify();
+    }
+
+    AIBinder_DeathRecipient *getNdkRecipient() {
+        return mNdkRecipient.get();;
+    }
+
 private:
     Notify mNotify;
+    ::ndk::ScopedAIBinder_DeathRecipient mNdkRecipient;
 };
 
 DeathNotifier::DeathNotifier(sp<IBinder> const& service, Notify const& notify)
@@ -55,6 +69,14 @@
     service->linkToDeath(mDeathRecipient, 0);
 }
 
+DeathNotifier::DeathNotifier(::ndk::SpAIBinder const& service, Notify const& notify)
+      : mService{std::in_place_index<3>, service},
+        mDeathRecipient{new DeathRecipient(notify)} {
+    mDeathRecipient->initNdk();
+    AIBinder_linkToDeath(
+            service.get(), mDeathRecipient->getNdkRecipient(), mDeathRecipient.get());
+}
+
 DeathNotifier::DeathNotifier(DeathNotifier&& other)
       : mService{other.mService}, mDeathRecipient{other.mDeathRecipient} {
     other.mService.emplace<0>();
@@ -71,6 +93,12 @@
     case 2:
         std::get<2>(mService)->unlinkToDeath(mDeathRecipient);
         break;
+    case 3:
+        AIBinder_unlinkToDeath(
+                std::get<3>(mService).get(),
+                mDeathRecipient->getNdkRecipient(),
+                mDeathRecipient.get());
+        break;
     default:
         CHECK(false) << "Corrupted service type during destruction.";
     }
diff --git a/media/libmediaplayerservice/DeathNotifier.h b/media/libmediaplayerservice/DeathNotifier.h
index 7bc2611..24e45a3 100644
--- a/media/libmediaplayerservice/DeathNotifier.h
+++ b/media/libmediaplayerservice/DeathNotifier.h
@@ -17,6 +17,7 @@
 #ifndef ANDROID_MEDIASERVICE_DEATHNOTIFIER_H
 #define ANDROID_MEDIASERVICE_DEATHNOTIFIER_H
 
+#include <android/binder_auto_utils.h>
 #include <android/hidl/base/1.0/IBase.h>
 #include <binder/Binder.h>
 #include <hidl/HidlSupport.h>
@@ -32,11 +33,12 @@
 
     DeathNotifier(sp<IBinder> const& service, Notify const& notify);
     DeathNotifier(sp<HBase> const& service, Notify const& notify);
+    DeathNotifier(::ndk::SpAIBinder const& service, Notify const& notify);
     DeathNotifier(DeathNotifier&& other);
     ~DeathNotifier();
 
 private:
-    std::variant<std::monostate, sp<IBinder>, sp<HBase>> mService;
+    std::variant<std::monostate, sp<IBinder>, sp<HBase>, ::ndk::SpAIBinder> mService;
 
     class DeathRecipient;
     sp<DeathRecipient> mDeathRecipient;
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index 2e1fdcf..10a1da7 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -237,7 +237,7 @@
     if (hasFlattenedTag) {
         // the tags are UTF16, convert to UTF8
         String16 tags = parcel.readString16();
-        ssize_t realTagSize = utf16_to_utf8_length(tags.string(), tags.size());
+        ssize_t realTagSize = utf16_to_utf8_length(tags.c_str(), tags.size());
         if (realTagSize <= 0) {
             strcpy(attributes->tags, "");
         } else {
@@ -245,7 +245,7 @@
             // copying array size -1, array for tags was calloc'd, no need to NULL-terminate it
             size_t tagSize = realTagSize > AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - 1 ?
                     AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - 1 : realTagSize;
-            utf16_to_utf8(tags.string(), tagSize, attributes->tags,
+            utf16_to_utf8(tags.c_str(), tagSize, attributes->tags,
                     sizeof(attributes->tags) / sizeof(attributes->tags[0]));
         }
     } else {
@@ -434,7 +434,7 @@
         }
     }
     result.append("\n");
-    ::write(fd, result.string(), result.size());
+    ::write(fd, result.c_str(), result.size());
 }
 
 
@@ -549,7 +549,7 @@
             mAuxEffectId, mSendLevel);
     result.append(buffer);
 
-    ::write(fd, result.string(), result.size());
+    ::write(fd, result.c_str(), result.size());
     if (mTrack != 0) {
         mTrack->dump(fd, args);
     }
@@ -584,7 +584,7 @@
     } else {
         result.append("  lock is taken, no dump from player and audio output\n");
     }
-    write(fd, result.string(), result.size());
+    write(fd, result.c_str(), result.size());
 
     if (p != NULL) {
         p->dump(fd, args);
@@ -644,7 +644,7 @@
                 snprintf(buffer, 255, " MediaRecorderClient pid(%d)\n",
                         c->mAttributionSource.pid);
                 result.append(buffer);
-                write(fd, result.string(), result.size());
+                write(fd, result.c_str(), result.size());
                 result = "\n";
                 c->dump(fd, args);
 
@@ -746,7 +746,7 @@
             result.append(s.c_str(), s.size());
         }
     }
-    write(fd, result.string(), result.size());
+    write(fd, result.c_str(), result.size());
 
     return NO_ERROR;
 }
@@ -927,10 +927,10 @@
         {
             for (std::shared_ptr<Codec2Client> const& client :
                     Codec2Client::CreateFromAllServices()) {
-                sp<IBase> base = client->getBase();
-                deathNotifiers.emplace_back(
-                        base, [l = wp<MediaPlayerBase>(p),
-                               name = std::string(client->getServiceName())]() {
+                sp<IBase> hidlBase = client->getHidlBase();
+                ::ndk::SpAIBinder aidlBase = client->getAidlBase();
+                auto onBinderDied = [l = wp<MediaPlayerBase>(p),
+                                     name = std::string(client->getServiceName())]() {
                     sp<MediaPlayerBase> listener = l.promote();
                     if (listener) {
                         ALOGI("Codec2 service \"%s\" died. "
@@ -944,7 +944,12 @@
                               "without a death handler.",
                               name.c_str());
                     }
-                });
+                };
+                if (hidlBase) {
+                    deathNotifiers.emplace_back(hidlBase, onBinderDied);
+                } else if (aidlBase.get() != nullptr) {
+                    deathNotifiers.emplace_back(aidlBase, onBinderDied);
+                }
             }
         }
     }
@@ -1249,7 +1254,7 @@
         const BufferingSettings& buffering)
 {
     ALOGV("[%d] setBufferingSettings{%s}",
-            mConnId, buffering.toString().string());
+            mConnId, buffering.toString().c_str());
     sp<MediaPlayerBase> p = getPlayer();
     if (p == 0) return UNKNOWN_ERROR;
     return p->setBufferingSettings(buffering);
@@ -1264,7 +1269,7 @@
     status_t ret = p->getBufferingSettings(buffering);
     if (ret == NO_ERROR) {
         ALOGV("[%d] getBufferingSettings{%s}",
-                mConnId, buffering->toString().string());
+                mConnId, buffering->toString().c_str());
     } else {
         ALOGE("[%d] getBufferingSettings returned %d", mConnId, ret);
     }
@@ -2008,7 +2013,7 @@
 String8  MediaPlayerService::AudioOutput::getParameters(const String8& keys)
 {
     Mutex::Autolock lock(mLock);
-    if (mTrack == 0) return String8::empty();
+    if (mTrack == 0) return String8();
     return mTrack->getParameters(keys);
 }
 
diff --git a/media/libmediaplayerservice/MediaRecorderClient.cpp b/media/libmediaplayerservice/MediaRecorderClient.cpp
index 58fc06d..ed3ec89 100644
--- a/media/libmediaplayerservice/MediaRecorderClient.cpp
+++ b/media/libmediaplayerservice/MediaRecorderClient.cpp
@@ -22,6 +22,7 @@
 #include "MediaPlayerService.h"
 #include "StagefrightRecorder.h"
 
+#include <android/binder_auto_utils.h>
 #include <android/hardware/media/omx/1.0/IOmx.h>
 #include <android/hardware/media/c2/1.0/IComponentStore.h>
 #include <binder/IPCThreadState.h>
@@ -245,7 +246,7 @@
 }
 
 status_t MediaRecorderClient::setParameters(const String8& params) {
-    ALOGV("setParameters(%s)", params.string());
+    ALOGV("setParameters(%s)", params.c_str());
     Mutex::Autolock lock(mLock);
     if (mRecorder == NULL) {
         ALOGE("recorder is not initialized");
@@ -490,9 +491,9 @@
         {
             for (std::shared_ptr<Codec2Client> const& client :
                     Codec2Client::CreateFromAllServices()) {
-                sp<IBase> base = client->getBase();
-                mDeathNotifiers.emplace_back(
-                        base, [l = wp<IMediaRecorderClient>(listener),
+                sp<IBase> hidlBase = client->getHidlBase();
+                ::ndk::SpAIBinder aidlBase = client->getAidlBase();
+                auto onBinderDied = [l = wp<IMediaRecorderClient>(listener),
                                name = std::string(client->getServiceName())]() {
                     sp<IMediaRecorderClient> listener = l.promote();
                     if (listener) {
@@ -507,7 +508,12 @@
                               "without a death handler",
                               name.c_str());
                     }
-                });
+                };
+                if (hidlBase) {
+                    mDeathNotifiers.emplace_back(hidlBase, onBinderDied);
+                } else if (aidlBase.get() != nullptr) {
+                    mDeathNotifiers.emplace_back(aidlBase, onBinderDied);
+                }
             }
         }
     }
@@ -519,7 +525,7 @@
 }
 
 status_t MediaRecorderClient::setClientName(const String16& clientName) {
-    ALOGV("setClientName(%s)", String8(clientName).string());
+    ALOGV("setClientName(%s)", String8(clientName).c_str());
     Mutex::Autolock lock(mLock);
     if (mRecorder == NULL) {
         ALOGE("recorder is not initialized");
diff --git a/media/libmediaplayerservice/MetadataRetrieverClient.cpp b/media/libmediaplayerservice/MetadataRetrieverClient.cpp
index fb228ca..9e289d0 100644
--- a/media/libmediaplayerservice/MetadataRetrieverClient.cpp
+++ b/media/libmediaplayerservice/MetadataRetrieverClient.cpp
@@ -67,7 +67,7 @@
     result.append(" MetadataRetrieverClient\n");
     snprintf(buffer, 255, "  pid(%d)\n", mPid);
     result.append(buffer);
-    write(fd, result.string(), result.size());
+    write(fd, result.c_str(), result.size());
     write(fd, "\n", 1);
     return NO_ERROR;
 }
diff --git a/media/libmediaplayerservice/StagefrightMetadataRetriever.cpp b/media/libmediaplayerservice/StagefrightMetadataRetriever.cpp
index db979d7..605e659 100644
--- a/media/libmediaplayerservice/StagefrightMetadataRetriever.cpp
+++ b/media/libmediaplayerservice/StagefrightMetadataRetriever.cpp
@@ -472,7 +472,7 @@
         return NULL;
     }
 
-    return mMetaData.valueAt(index).string();
+    return mMetaData.valueAt(index).c_str();
 }
 
 void StagefrightMetadataRetriever::parseColorAspects(const sp<MetaData>& meta) {
@@ -672,6 +672,18 @@
                     if (trackMeta->findInt32(kKeyWidth, &imageWidth)
                         && trackMeta->findInt32(kKeyHeight, &imageHeight)) {
                         imagePrimary = imageCount;
+                        int32_t displayLeft;
+                        int32_t displayTop;
+                        int32_t displayRight;
+                        int32_t displayBottom;
+                        if (trackMeta->findRect(kKeyCropRect, &displayLeft, &displayTop,
+                                                &displayRight, &displayBottom)
+                            && displayLeft >= 0 && displayTop >= 0 && displayRight < imageWidth
+                            && displayBottom < imageHeight && displayLeft <= displayRight
+                            && displayTop <= displayBottom) {
+                            imageWidth = displayRight - displayLeft + 1;
+                            imageHeight = displayBottom - displayTop + 1;
+                        }
                     } else {
                         ALOGE("primary image track ignored for missing dimensions");
                     }
@@ -692,7 +704,7 @@
     // To save the language codes for all timed text tracks
     // If multiple text tracks present, the format will look
     // like "eng:chi"
-    if (!timedTextLang.isEmpty()) {
+    if (!timedTextLang.empty()) {
         mMetaData.add(METADATA_KEY_TIMED_TEXT_LANGUAGES, timedTextLang);
     }
 
diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp
index cb2007d..89348a4 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.cpp
+++ b/media/libmediaplayerservice/StagefrightRecorder.cpp
@@ -519,7 +519,7 @@
 // Trim both leading and trailing whitespace from the given string.
 static void TrimString(String8 *s) {
     size_t num_bytes = s->bytes();
-    const char *data = s->string();
+    const char *data = s->c_str();
 
     size_t leading_space = 0;
     while (leading_space < num_bytes && isspace(data[leading_space])) {
@@ -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) {
@@ -823,9 +823,9 @@
 }
 
 status_t StagefrightRecorder::setParamRtpLocalIp(const String8 &localIp) {
-    ALOGV("setParamVideoLocalIp: %s", localIp.string());
+    ALOGV("setParamVideoLocalIp: %s", localIp.c_str());
 
-    mLocalIp.setTo(localIp.string());
+    mLocalIp = localIp.c_str();
     return OK;
 }
 
@@ -837,9 +837,9 @@
 }
 
 status_t StagefrightRecorder::setParamRtpRemoteIp(const String8 &remoteIp) {
-    ALOGV("setParamVideoRemoteIp: %s", remoteIp.string());
+    ALOGV("setParamVideoRemoteIp: %s", remoteIp.c_str());
 
-    mRemoteIp.setTo(remoteIp.string());
+    mRemoteIp = remoteIp.c_str();
     return OK;
 }
 
@@ -929,197 +929,197 @@
 }
 
 status_t StagefrightRecorder::setLogSessionId(const String8 &log_session_id) {
-    ALOGV("setLogSessionId: %s", log_session_id.string());
+    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.string());
+    mLogSessionId = log_session_id.c_str();
     return OK;
 }
 
 status_t StagefrightRecorder::setParameter(
         const String8 &key, const String8 &value) {
-    ALOGV("setParameter: key (%s) => value (%s)", key.string(), value.string());
+    ALOGV("setParameter: key (%s) => value (%s)", key.c_str(), value.c_str());
     if (key == "max-duration") {
         int64_t max_duration_ms;
-        if (safe_strtoi64(value.string(), &max_duration_ms)) {
+        if (safe_strtoi64(value.c_str(), &max_duration_ms)) {
             return setParamMaxFileDurationUs(1000LL * max_duration_ms);
         }
     } else if (key == "max-filesize") {
         int64_t max_filesize_bytes;
-        if (safe_strtoi64(value.string(), &max_filesize_bytes)) {
+        if (safe_strtoi64(value.c_str(), &max_filesize_bytes)) {
             return setParamMaxFileSizeBytes(max_filesize_bytes);
         }
     } else if (key == "interleave-duration-us") {
         int32_t durationUs;
-        if (safe_strtoi32(value.string(), &durationUs)) {
+        if (safe_strtoi32(value.c_str(), &durationUs)) {
             return setParamInterleaveDuration(durationUs);
         }
     } else if (key == "param-movie-time-scale") {
         int32_t timeScale;
-        if (safe_strtoi32(value.string(), &timeScale)) {
+        if (safe_strtoi32(value.c_str(), &timeScale)) {
             return setParamMovieTimeScale(timeScale);
         }
     } else if (key == "param-use-64bit-offset") {
         int32_t use64BitOffset;
-        if (safe_strtoi32(value.string(), &use64BitOffset)) {
+        if (safe_strtoi32(value.c_str(), &use64BitOffset)) {
             return setParam64BitFileOffset(use64BitOffset != 0);
         }
     } else if (key == "param-geotag-longitude") {
         int64_t longitudex10000;
-        if (safe_strtoi64(value.string(), &longitudex10000)) {
+        if (safe_strtoi64(value.c_str(), &longitudex10000)) {
             return setParamGeoDataLongitude(longitudex10000);
         }
     } else if (key == "param-geotag-latitude") {
         int64_t latitudex10000;
-        if (safe_strtoi64(value.string(), &latitudex10000)) {
+        if (safe_strtoi64(value.c_str(), &latitudex10000)) {
             return setParamGeoDataLatitude(latitudex10000);
         }
     } else if (key == "param-track-time-status") {
         int64_t timeDurationUs;
-        if (safe_strtoi64(value.string(), &timeDurationUs)) {
+        if (safe_strtoi64(value.c_str(), &timeDurationUs)) {
             return setParamTrackTimeStatus(timeDurationUs);
         }
     } else if (key == "audio-param-sampling-rate") {
         int32_t sampling_rate;
-        if (safe_strtoi32(value.string(), &sampling_rate)) {
+        if (safe_strtoi32(value.c_str(), &sampling_rate)) {
             return setParamAudioSamplingRate(sampling_rate);
         }
     } else if (key == "audio-param-number-of-channels") {
         int32_t number_of_channels;
-        if (safe_strtoi32(value.string(), &number_of_channels)) {
+        if (safe_strtoi32(value.c_str(), &number_of_channels)) {
             return setParamAudioNumberOfChannels(number_of_channels);
         }
     } else if (key == "audio-param-encoding-bitrate") {
         int32_t audio_bitrate;
-        if (safe_strtoi32(value.string(), &audio_bitrate)) {
+        if (safe_strtoi32(value.c_str(), &audio_bitrate)) {
             return setParamAudioEncodingBitRate(audio_bitrate);
         }
     } else if (key == "audio-param-time-scale") {
         int32_t timeScale;
-        if (safe_strtoi32(value.string(), &timeScale)) {
+        if (safe_strtoi32(value.c_str(), &timeScale)) {
             return setParamAudioTimeScale(timeScale);
         }
     } else if (key == "video-param-encoding-bitrate") {
         int32_t video_bitrate;
-        if (safe_strtoi32(value.string(), &video_bitrate)) {
+        if (safe_strtoi32(value.c_str(), &video_bitrate)) {
             return setParamVideoEncodingBitRate(video_bitrate);
         }
     } else if (key == "video-param-bitrate-mode") {
         int32_t video_bitrate_mode;
-        if (safe_strtoi32(value.string(), &video_bitrate_mode)) {
+        if (safe_strtoi32(value.c_str(), &video_bitrate_mode)) {
             return setParamVideoBitRateMode(video_bitrate_mode);
         }
     } else if (key == "video-param-rotation-angle-degrees") {
         int32_t degrees;
-        if (safe_strtoi32(value.string(), &degrees)) {
+        if (safe_strtoi32(value.c_str(), &degrees)) {
             return setParamVideoRotation(degrees);
         }
     } else if (key == "video-param-i-frames-interval") {
         int32_t seconds;
-        if (safe_strtoi32(value.string(), &seconds)) {
+        if (safe_strtoi32(value.c_str(), &seconds)) {
             return setParamVideoIFramesInterval(seconds);
         }
     } else if (key == "video-param-encoder-profile") {
         int32_t profile;
-        if (safe_strtoi32(value.string(), &profile)) {
+        if (safe_strtoi32(value.c_str(), &profile)) {
             return setParamVideoEncoderProfile(profile);
         }
     } else if (key == "video-param-encoder-level") {
         int32_t level;
-        if (safe_strtoi32(value.string(), &level)) {
+        if (safe_strtoi32(value.c_str(), &level)) {
             return setParamVideoEncoderLevel(level);
         }
     } else if (key == "video-param-camera-id") {
         int32_t cameraId;
-        if (safe_strtoi32(value.string(), &cameraId)) {
+        if (safe_strtoi32(value.c_str(), &cameraId)) {
             return setParamVideoCameraId(cameraId);
         }
     } else if (key == "video-param-time-scale") {
         int32_t timeScale;
-        if (safe_strtoi32(value.string(), &timeScale)) {
+        if (safe_strtoi32(value.c_str(), &timeScale)) {
             return setParamVideoTimeScale(timeScale);
         }
     } else if (key == "time-lapse-enable") {
         int32_t captureFpsEnable;
-        if (safe_strtoi32(value.string(), &captureFpsEnable)) {
+        if (safe_strtoi32(value.c_str(), &captureFpsEnable)) {
             return setParamCaptureFpsEnable(captureFpsEnable);
         }
     } else if (key == "time-lapse-fps") {
         double fps;
-        if (safe_strtod(value.string(), &fps)) {
+        if (safe_strtod(value.c_str(), &fps)) {
             return setParamCaptureFps(fps);
         }
     } else if (key == "rtp-param-local-ip") {
         return setParamRtpLocalIp(value);
     } else if (key == "rtp-param-local-port") {
         int32_t localPort;
-        if (safe_strtoi32(value.string(), &localPort)) {
+        if (safe_strtoi32(value.c_str(), &localPort)) {
             return setParamRtpLocalPort(localPort);
         }
     } else if (key == "rtp-param-remote-ip") {
         return setParamRtpRemoteIp(value);
     } else if (key == "rtp-param-remote-port") {
         int32_t remotePort;
-        if (safe_strtoi32(value.string(), &remotePort)) {
+        if (safe_strtoi32(value.c_str(), &remotePort)) {
             return setParamRtpRemotePort(remotePort);
         }
     } else if (key == "rtp-param-self-id") {
         int32_t selfID;
         int64_t temp;
-        if (safe_strtoi64(value.string(), &temp)) {
+        if (safe_strtoi64(value.c_str(), &temp)) {
             selfID = static_cast<int32_t>(temp);
             return setParamSelfID(selfID);
         }
     } else if (key == "rtp-param-opponent-id") {
         int32_t opnId;
         int64_t temp;
-        if (safe_strtoi64(value.string(), &temp)) {
+        if (safe_strtoi64(value.c_str(), &temp)) {
             opnId = static_cast<int32_t>(temp);
             return setParamVideoOpponentID(opnId);
         }
     } else if (key == "rtp-param-payload-type") {
         int32_t payloadType;
-        if (safe_strtoi32(value.string(), &payloadType)) {
+        if (safe_strtoi32(value.c_str(), &payloadType)) {
             return setParamPayloadType(payloadType);
         }
     } else if (key == "rtp-param-ext-cvo-extmap") {
         int32_t extmap;
-        if (safe_strtoi32(value.string(), &extmap)) {
+        if (safe_strtoi32(value.c_str(), &extmap)) {
             return setRTPCVOExtMap(extmap);
         }
     } else if (key == "rtp-param-ext-cvo-degrees") {
         int32_t degrees;
-        if (safe_strtoi32(value.string(), &degrees)) {
+        if (safe_strtoi32(value.c_str(), &degrees)) {
             return setRTPCVODegrees(degrees);
         }
     } else if (key == "video-param-request-i-frame") {
         return requestIDRFrame();
     } else if (key == "rtp-param-set-socket-dscp") {
         int32_t dscp;
-        if (safe_strtoi32(value.string(), &dscp)) {
+        if (safe_strtoi32(value.c_str(), &dscp)) {
             return setParamRtpDscp(dscp);
         }
     } else if (key == "rtp-param-set-socket-ecn") {
         int32_t targetEcn;
-        if (safe_strtoi32(value.string(), &targetEcn)) {
+        if (safe_strtoi32(value.c_str(), &targetEcn)) {
             return setParamRtpEcn(targetEcn);
         }
     } else if (key == "rtp-param-set-socket-network") {
         int64_t networkHandle;
-        if (safe_strtoi64(value.string(), &networkHandle)) {
+        if (safe_strtoi64(value.c_str(), &networkHandle)) {
             return setSocketNetwork(networkHandle);
         }
     } else if (key == "log-session-id") {
         return setLogSessionId(value);
     } else {
-        ALOGE("setParameter: failed to find key %s", key.string());
+        ALOGE("setParameter: failed to find key %s", key.c_str());
     }
     return BAD_VALUE;
 }
 
 status_t StagefrightRecorder::setParameters(const String8 &params) {
-    ALOGV("setParameters: %s", params.string());
-    const char *cparams = params.string();
+    ALOGV("setParameters: %s", params.c_str());
+    const char *cparams = params.c_str();
     const char *key_start = cparams;
     for (;;) {
         const char *equal_pos = strchr(key_start, '=');
@@ -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;
@@ -2680,7 +2680,7 @@
     result.append(buffer);
     snprintf(buffer, SIZE, "     Bit rate (bps): %d\n", mVideoBitRate);
     result.append(buffer);
-    ::write(fd, result.string(), result.size());
+    ::write(fd, result.c_str(), result.size());
     return OK;
 }
 }  // namespace android
diff --git a/media/libmediaplayerservice/fuzzer/Android.bp b/media/libmediaplayerservice/fuzzer/Android.bp
index 017f403..b511372 100644
--- a/media/libmediaplayerservice/fuzzer/Android.bp
+++ b/media/libmediaplayerservice/fuzzer/Android.bp
@@ -35,6 +35,7 @@
     shared_libs: [
         "framework-permission-aidl-cpp",
         "libbinder",
+        "libbinder_ndk",
         "libcutils",
         "libmedia",
         "libstagefright",
@@ -173,6 +174,7 @@
         "libnetd_client",
         "libpowermanager",
         "libstagefright_httplive",
+        "libaudiohal@7.0",
     ],
 }
 
diff --git a/media/libmediaplayerservice/include/MediaPlayerInterface.h b/media/libmediaplayerservice/include/MediaPlayerInterface.h
index fb20aab..be1aa00 100644
--- a/media/libmediaplayerservice/include/MediaPlayerInterface.h
+++ b/media/libmediaplayerservice/include/MediaPlayerInterface.h
@@ -149,7 +149,7 @@
         virtual bool        needsTrailingPadding() { return true; }
 
         virtual status_t    setParameters(const String8& /* keyValuePairs */) { return NO_ERROR; }
-        virtual String8     getParameters(const String8& /* keys */) { return String8::empty(); }
+        virtual String8     getParameters(const String8& /* keys */) { return String8(); }
 
         virtual media::VolumeShaper::Status applyVolumeShaper(
                                     const sp<media::VolumeShaper::Configuration>& configuration,
diff --git a/media/libmediaplayerservice/nuplayer/GenericSource.cpp b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
index 1358faa..991c77b 100644
--- a/media/libmediaplayerservice/nuplayer/GenericSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
@@ -270,7 +270,7 @@
     }
 
     ALOGV("initFromDataSource mSources.size(): %zu  mIsSecure: %d  mime[0]: %s", mSources.size(),
-            mIsSecure, (mMimes.isEmpty() ? "NONE" : mMimes[0].string()));
+            mIsSecure, (mMimes.isEmpty() ? "NONE" : mMimes[0].c_str()));
 
     if (mSources.size() == 0) {
         ALOGE("b/23705695");
@@ -292,12 +292,12 @@
         *buffering = mBufferingSettings;
     }
 
-    ALOGV("getBufferingSettings{%s}", buffering->toString().string());
+    ALOGV("getBufferingSettings{%s}", buffering->toString().c_str());
     return OK;
 }
 
 status_t NuPlayer::GenericSource::setBufferingSettings(const BufferingSettings& buffering) {
-    ALOGV("setBufferingSettings{%s}", buffering.toString().string());
+    ALOGV("setBufferingSettings{%s}", buffering.toString().c_str());
 
     Mutex::Autolock _l(mLock);
     mBufferingSettings = buffering;
@@ -1619,7 +1619,7 @@
         return status;
     }
     ALOGV("prepareDrm: createCryptoAndPlugin succeeded for uuid: %s",
-            DrmUUID::toHexString(uuid).string());
+            DrmUUID::toHexString(uuid).c_str());
 
     *outCrypto = crypto;
     // as long a there is an active crypto
@@ -1632,7 +1632,7 @@
     }
 
     // first mime in this list is either the video track, or the first audio track
-    const char *mime = mMimes[0].string();
+    const char *mime = mMimes[0].c_str();
     mIsSecure = crypto->requiresSecureDecoderComponent(mime);
     ALOGV("prepareDrm: requiresSecureDecoderComponent mime: %s  isSecure: %d",
             mime, mIsSecure);
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
index 485923f..a625893 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
@@ -370,7 +370,7 @@
 }
 
 void NuPlayer::setDataSourceAsync(const String8& rtpParams) {
-    ALOGD("setDataSourceAsync for RTP = %s", rtpParams.string());
+    ALOGD("setDataSourceAsync for RTP = %s", rtpParams.c_str());
     sp<AMessage> msg = new AMessage(kWhatSetDataSource, this);
 
     sp<AMessage> notify = new AMessage(kWhatSourceNotify, this);
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDrm.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDrm.cpp
index a964d4f..8525192 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDrm.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDrm.cpp
@@ -89,8 +89,8 @@
         drmSchemes.add(_uuid);
 
         ALOGV("ParsePSSH[%zu]: %s: %s", numentries,
-                _uuid.toHexString().string(),
-                DrmUUID::arrayToHex(data, datalen).string()
+                _uuid.toHexString().c_str(),
+                DrmUUID::arrayToHex(data, datalen).c_str()
              );
 
         numentries++;
@@ -167,7 +167,7 @@
     parcel->writeByteArray(psshsize, (const uint8_t*)pssh);
 
     ALOGV("retrieveDrmInfo: MEDIA_DRM_INFO  PSSH: size: %zu %s", psshsize,
-            DrmUUID::arrayToHex((uint8_t*)pssh, psshsize).string());
+            DrmUUID::arrayToHex((uint8_t*)pssh, psshsize).c_str());
 
     // 2) supportedDRMs
     Vector<DrmUUID> supportedDRMs = getSupportedDrmSchemes(pssh, psshsize);
@@ -177,7 +177,7 @@
         parcel->writeByteArray(DrmUUID::UUID_SIZE, uuid.ptr());
 
         ALOGV("retrieveDrmInfo: MEDIA_DRM_INFO  supportedScheme[%zu] %s", i,
-                uuid.toHexString().string());
+                uuid.toHexString().c_str());
     }
 }
 
diff --git a/media/libmediaplayerservice/nuplayer/RTPSource.cpp b/media/libmediaplayerservice/nuplayer/RTPSource.cpp
index fd03150..9a33120 100644
--- a/media/libmediaplayerservice/nuplayer/RTPSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/RTPSource.cpp
@@ -56,7 +56,7 @@
       mReceivedFirstRTPPacket(false),
       mPausing(false),
       mPauseGeneration(0) {
-    ALOGD("RTPSource initialized with rtpParams=%s", rtpParams.string());
+    ALOGD("RTPSource initialized with rtpParams=%s", rtpParams.c_str());
 }
 
 NuPlayer::RTPSource::~RTPSource() {
@@ -661,7 +661,7 @@
 }
 
 status_t NuPlayer::RTPSource::setParameter(const String8 &key, const String8 &value) {
-    ALOGV("setParameter: key (%s) => value (%s)", key.string(), value.string());
+    ALOGV("setParameter: key (%s) => value (%s)", key.c_str(), value.c_str());
 
     bool isAudioKey = key.contains("audio");
     TrackInfo *info = NULL;
@@ -684,12 +684,12 @@
     if (key == "rtp-param-mime-type") {
         info->mMimeType = value;
 
-        const char *mime = value.string();
+        const char *mime = value.c_str();
         const char *delimiter = strchr(mime, '/');
         info->mCodecName = delimiter ? (delimiter + 1) : "<none>";
 
         ALOGV("rtp-param-mime-type: mMimeType (%s) => mCodecName (%s)",
-                info->mMimeType.string(), info->mCodecName.string());
+                info->mMimeType.c_str(), info->mCodecName.c_str());
     } else if (key == "video-param-decoder-profile") {
         info->mCodecProfile = atoi(value);
     } else if (key == "video-param-decoder-level") {
@@ -732,8 +732,8 @@
 }
 
 status_t NuPlayer::RTPSource::setParameters(const String8 &params) {
-    ALOGV("setParameters: %s", params.string());
-    const char *cparams = params.string();
+    ALOGV("setParameters: %s", params.c_str());
+    const char *cparams = params.c_str();
     const char *key_start = cparams;
     for (;;) {
         const char *equal_pos = strchr(key_start, '=');
@@ -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;
@@ -784,7 +784,7 @@
 //static
 void NuPlayer::RTPSource::TrimString(String8 *s) {
     size_t num_bytes = s->bytes();
-    const char *data = s->string();
+    const char *data = s->c_str();
 
     size_t leading_space = 0;
     while (leading_space < num_bytes && isspace(data[leading_space])) {
@@ -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/libnblog/PerformanceAnalysis.cpp b/media/libnblog/PerformanceAnalysis.cpp
index e91a511..7982805 100644
--- a/media/libnblog/PerformanceAnalysis.cpp
+++ b/media/libnblog/PerformanceAnalysis.cpp
@@ -393,7 +393,7 @@
             PerformanceAnalysis& curr = hash.second;
             // write performance data to console
             curr.reportPerformance(&body, thread.first, hash.first);
-            if (!body.isEmpty()) {
+            if (!body.empty()) {
                 dumpLine(fd, indent, body);
                 body.clear();
             }
@@ -409,7 +409,7 @@
 
 // Writes a string into specified file descriptor
 void dumpLine(int fd, int indent, const String8 &body) {
-    dprintf(fd, "%.*s%s \n", indent, "", body.string());
+    dprintf(fd, "%.*s%s \n", indent, "", body.c_str());
 }
 
 } // namespace ReportPerformance
diff --git a/media/libnblog/Reader.cpp b/media/libnblog/Reader.cpp
index d6232d4..71ebfd1 100644
--- a/media/libnblog/Reader.cpp
+++ b/media/libnblog/Reader.cpp
@@ -282,8 +282,8 @@
         default:
             break;
         }
-        if (!body.isEmpty()) {
-            dprintf(fd, "%.*s%s %s\n", (int)indent, "", timestamp.string(), body.string());
+        if (!body.empty()) {
+            dprintf(fd, "%.*s%s %s\n", (int)indent, "", timestamp.c_str(), body.c_str());
             body.clear();
         }
         timestamp.clear();
diff --git a/media/libstagefright/Android.bp b/media/libstagefright/Android.bp
index a26fcbe..0af9d12 100644
--- a/media/libstagefright/Android.bp
+++ b/media/libstagefright/Android.bp
@@ -270,10 +270,10 @@
         "SurfaceUtils.cpp",
         "ThrottledSource.cpp",
         "Utils.cpp",
-        "VideoRenderQualityTracker.cpp",
         "VideoFrameSchedulerBase.cpp",
         "VideoFrameScheduler.cpp",
-    ],
+        "VideoRenderQualityTracker.cpp",
+      ],
 
     shared_libs: [
         "libstagefright_framecapture_utils",
diff --git a/media/libstagefright/CallbackDataSource.cpp b/media/libstagefright/CallbackDataSource.cpp
index eb3cb45..ede4855 100644
--- a/media/libstagefright/CallbackDataSource.cpp
+++ b/media/libstagefright/CallbackDataSource.cpp
@@ -38,7 +38,7 @@
     mName = String8::format("CallbackDataSource(%d->%d, %s)",
             getpid(),
             IPCThreadState::self()->getCallingPid(),
-            mIDataSource->toString().string());
+            mIDataSource->toString().c_str());
 
 }
 
@@ -120,7 +120,7 @@
 
 TinyCacheSource::TinyCacheSource(const sp<DataSource>& source)
     : mSource(source), mCachedOffset(0), mCachedSize(0) {
-    mName = String8::format("TinyCacheSource(%s)", mSource->toString().string());
+    mName = String8::format("TinyCacheSource(%s)", mSource->toString().c_str());
 }
 
 status_t TinyCacheSource::initCheck() const {
diff --git a/media/libstagefright/FrameDecoder.cpp b/media/libstagefright/FrameDecoder.cpp
index 57937f9..1a0bb7f 100644
--- a/media/libstagefright/FrameDecoder.cpp
+++ b/media/libstagefright/FrameDecoder.cpp
@@ -86,6 +86,22 @@
         displayWidth = width;
         displayHeight = height;
     }
+    int32_t displayLeft = 0;
+    int32_t displayTop = 0;
+    int32_t displayRight;
+    int32_t displayBottom;
+    if (trackMeta->findRect(kKeyCropRect, &displayLeft, &displayTop, &displayRight,
+                            &displayBottom)) {
+        if (displayLeft >= 0 && displayTop >= 0 && displayRight < width && displayBottom < height &&
+            displayLeft <= displayRight && displayTop <= displayBottom) {
+            displayWidth = displayRight - displayLeft + 1;
+            displayHeight = displayBottom - displayTop + 1;
+        } else {
+            // Crop rectangle is invalid, use the whole frame.
+            displayLeft = 0;
+            displayTop = 0;
+        }
+    }
 
     if (allocRotated) {
         if (rotationAngle == 90 || rotationAngle == 270) {
@@ -108,8 +124,8 @@
         }
     }
 
-    VideoFrame frame(width, height, displayWidth, displayHeight,
-            tileWidth, tileHeight, rotationAngle, dstBpp, bitDepth, !metaOnly, iccSize);
+    VideoFrame frame(width, height, displayWidth, displayHeight, displayLeft, displayTop, tileWidth,
+                     tileHeight, rotationAngle, dstBpp, bitDepth, !metaOnly, iccSize);
 
     size_t size = frame.getFlattenedSize();
     sp<MemoryHeapBase> heap = new MemoryHeapBase(size, 0, "MetadataRetrieverClient");
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index 2cd3768..e399cbe 100644
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -612,7 +612,7 @@
     result.append(buffer);
     snprintf(buffer, SIZE, "     mStarted: %s\n", mStarted? "true": "false");
     result.append(buffer);
-    ::write(fd, result.string(), result.size());
+    ::write(fd, result.c_str(), result.size());
     for (List<Track *>::iterator it = mTracks.begin();
          it != mTracks.end(); ++it) {
         (*it)->dump(fd, args);
@@ -634,7 +634,7 @@
     result.append(buffer);
     snprintf(buffer, SIZE, "       duration encoded : %" PRId64 " us\n", mTrackDurationUs);
     result.append(buffer);
-    ::write(fd, result.string(), result.size());
+    ::write(fd, result.c_str(), result.size());
     return OK;
 }
 
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index aeee3a8..d80cfa6 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -243,7 +243,7 @@
         "android.media.mediacodec.judder-score-histogram-buckets";
 // Freeze event
 static const char *kCodecFreezeEventCount = "android.media.mediacodec.freeze-event-count";
-static const char *kFreezeEventKeyName = "freeze";
+static const char *kFreezeEventKeyName = "videofreeze";
 static const char *kFreezeEventInitialTimeUs = "android.media.mediacodec.freeze.initial-time-us";
 static const char *kFreezeEventDurationMs = "android.media.mediacodec.freeze.duration-ms";
 static const char *kFreezeEventCount = "android.media.mediacodec.freeze.count";
@@ -255,7 +255,7 @@
         "android.media.mediacodec.freeze.details-distance-ms";
 // Judder event
 static const char *kCodecJudderEventCount = "android.media.mediacodec.judder-event-count";
-static const char *kJudderEventKeyName = "judder";
+static const char *kJudderEventKeyName = "videojudder";
 static const char *kJudderEventInitialTimeUs = "android.media.mediacodec.judder.initial-time-us";
 static const char *kJudderEventDurationMs = "android.media.mediacodec.judder.duration-ms";
 static const char *kJudderEventCount = "android.media.mediacodec.judder.count";
diff --git a/media/libstagefright/MediaExtractorFactory.cpp b/media/libstagefright/MediaExtractorFactory.cpp
index 2520e2a..1c72a65 100644
--- a/media/libstagefright/MediaExtractorFactory.cpp
+++ b/media/libstagefright/MediaExtractorFactory.cpp
@@ -242,22 +242,22 @@
                 continue;
             }
             void *libHandle = android_dlopen_ext(
-                    libPath.string(),
+                    libPath.c_str(),
                     RTLD_NOW | RTLD_LOCAL, dlextinfo);
             if (libHandle == nullptr) {
-                ALOGI("dlopen(%s) reported error %s", libPath.string(), strerror(errno));
+                ALOGI("dlopen(%s) reported error %s", libPath.c_str(), strerror(errno));
                 continue;
             }
 
             GetExtractorDef getDef =
                 (GetExtractorDef) dlsym(libHandle, "GETEXTRACTORDEF");
             if (getDef == nullptr) {
-                ALOGI("no sniffer found in %s", libPath.string());
+                ALOGI("no sniffer found in %s", libPath.c_str());
                 dlclose(libHandle);
                 continue;
             }
 
-            ALOGV("registering sniffer for %s", libPath.string());
+            ALOGV("registering sniffer for %s", libPath.c_str());
             RegisterExtractor(
                     new ExtractorPlugin(getDef(), libHandle, libPath), pluginList);
         }
@@ -387,7 +387,7 @@
             out.append("  (no plugins registered)\n");
         }
     }
-    write(fd, out.string(), out.size());
+    write(fd, out.c_str(), out.size());
     return OK;
 }
 
diff --git a/media/libstagefright/NuMediaExtractor.cpp b/media/libstagefright/NuMediaExtractor.cpp
index 28ca9ff..92ec56b 100644
--- a/media/libstagefright/NuMediaExtractor.cpp
+++ b/media/libstagefright/NuMediaExtractor.cpp
@@ -164,7 +164,7 @@
 
 const char* NuMediaExtractor::getName() const {
     Mutex::Autolock autoLock(mLock);
-    return mImpl == nullptr ? nullptr : mName.string();
+    return mImpl == nullptr ? nullptr : mName.c_str();
 }
 
 static String8 arrayToString(const std::vector<uint8_t> &array) {
@@ -172,7 +172,7 @@
     for (size_t i = 0; i < array.size(); i++) {
         result.appendFormat("%02x ", array[i]);
     }
-    if (result.isEmpty()) {
+    if (result.empty()) {
         result.append("(null)");
     }
     return result;
diff --git a/media/libstagefright/colorconversion/ColorConverter.cpp b/media/libstagefright/colorconversion/ColorConverter.cpp
index f91a8b2..6c26c28 100644
--- a/media/libstagefright/colorconversion/ColorConverter.cpp
+++ b/media/libstagefright/colorconversion/ColorConverter.cpp
@@ -363,6 +363,7 @@
     int32_t _g_u;
     int32_t _g_v;
     int32_t _b_u;
+    int32_t _c16;  // 16 for limited range matrix, 0 for full rance
 };
 
 /*
@@ -425,18 +426,18 @@
  *
  * clip range 8-bit: [-277, 535], 10-bit: [-1111, 2155]
  */
-const struct ColorConverter::Coeffs BT601_FULL      = { 256, 359,  88, 183, 454 };
-const struct ColorConverter::Coeffs BT601_LIMITED   = { 298, 409, 100, 208, 516 };
-const struct ColorConverter::Coeffs BT601_LTD_10BIT = { 299, 410, 101, 209, 518 };
+const struct ColorConverter::Coeffs BT601_FULL      = { 256, 359,  88, 183, 454, 0 };
+const struct ColorConverter::Coeffs BT601_LIMITED   = { 298, 409, 100, 208, 516, 16 };
+const struct ColorConverter::Coeffs BT601_LTD_10BIT = { 299, 410, 101, 209, 518, 16 };
 
 /**
  * BT.709:  K_R = 0.2126; K_B = 0.0722
  *
  * clip range 8-bit: [-289, 547], 10-bit: [-1159, 2202]
  */
-const struct ColorConverter::Coeffs BT709_FULL      = { 256, 403,  48, 120, 475 };
-const struct ColorConverter::Coeffs BT709_LIMITED   = { 298, 459,  55, 136, 541 };
-const struct ColorConverter::Coeffs BT709_LTD_10BIT = { 290, 460,  55, 137, 542 };
+const struct ColorConverter::Coeffs BT709_FULL      = { 256, 403,  48, 120, 475, 0 };
+const struct ColorConverter::Coeffs BT709_LIMITED   = { 298, 459,  55, 136, 541, 16 };
+const struct ColorConverter::Coeffs BT709_LTD_10BIT = { 299, 460,  55, 137, 542, 16 };
 
 /**
  * BT.2020:  K_R = 0.2627; K_B = 0.0593
@@ -445,9 +446,9 @@
  *
  * This is the largest clip range.
  */
-const struct ColorConverter::Coeffs BT2020_FULL      = { 256, 377,  42, 146, 482 };
-const struct ColorConverter::Coeffs BT2020_LIMITED   = { 298, 430,  48, 167, 548 };
-const struct ColorConverter::Coeffs BT2020_LTD_10BIT = { 299, 431,  48, 167, 550 };
+const struct ColorConverter::Coeffs BT2020_FULL      = { 256, 377,  42, 146, 482, 0 };
+const struct ColorConverter::Coeffs BT2020_LIMITED   = { 298, 430,  48, 167, 548, 16 };
+const struct ColorConverter::Coeffs BT2020_LTD_10BIT = { 299, 431,  48, 167, 550, 16 };
 
 constexpr int CLIP_RANGE_MIN_8BIT = -294;
 constexpr int CLIP_RANGE_MAX_8BIT = 552;
@@ -781,7 +782,7 @@
     signed _neg_g_v = -matrix->_g_v;
     signed _r_v = matrix->_r_v;
     signed _y = matrix->_y;
-    signed _c16 = mSrcColorSpace.mRange == ColorUtils::kColorRangeLimited ? 16 : 0;
+    signed _c16 = matrix->_c16;
 
     uint8_t *kAdjustedClip = initClip();
 
@@ -1257,6 +1258,7 @@
     signed _neg_g_v = -matrix->_g_v;
     signed _r_v = matrix->_r_v;
     signed _y = matrix->_y;
+    signed _c16 = matrix->_c16;
 
     uint8_t *dst_ptr = (uint8_t *)dst.mBits
             + dst.mCropTop * dst.mStride + dst.mCropLeft * dst.mBpp;
@@ -1275,13 +1277,12 @@
 
     //TODO: optimize for chroma sampling, reading and writing multiple pixels
     //      within the same loop
-    signed _c16 = 0;
+
     void *kAdjustedClip = nullptr;
     if (mSrcImage->getBitDepth() != ImageBitDepth8) {
         ALOGE("BitDepth != 8 for MediaImage2");
         return ERROR_UNSUPPORTED;
     }
-    _c16 = mSrcColorSpace.mRange == ColorUtils::kColorRangeLimited ? 16 : 0;
     kAdjustedClip = initClip();
 
     auto writeToDst = getWriteToDst(mDstFormat, (void *)kAdjustedClip);
@@ -1388,7 +1389,7 @@
     signed _neg_g_v = -matrix->_g_v;
     signed _r_v = matrix->_r_v;
     signed _y = matrix->_y;
-    signed _c16 = mSrcColorSpace.mRange == ColorUtils::kColorRangeLimited ? 16 : 0;
+    signed _c16 = matrix->_c16;
 
     uint8_t *kAdjustedClip = initClip();
 
@@ -1463,7 +1464,7 @@
     signed _neg_g_v = -matrix->_g_v;
     signed _r_v = matrix->_r_v;
     signed _y = matrix->_y;
-    signed _c16 = mSrcColorSpace.mRange == ColorUtils::kColorRangeLimited ? 64 : 0;
+    signed _c64 = matrix->_c16 * 4;
 
     uint16_t *kAdjustedClip10bit = initClip10Bit();
 
@@ -1483,8 +1484,8 @@
     for (size_t y = 0; y < src.cropHeight(); ++y) {
         for (size_t x = 0; x < src.cropWidth(); x += 2) {
             signed y1, y2, u, v;
-            y1 = (src_y[x] >> 6) - _c16;
-            y2 = (src_y[x + 1] >> 6) - _c16;
+            y1 = (src_y[x] >> 6) - _c64;
+            y2 = (src_y[x + 1] >> 6) - _c64;
             u = int(src_uv[x] >> 6) - 512;
             v = int(src_uv[x + 1] >> 6) - 512;
 
diff --git a/media/libstagefright/httplive/HTTPDownloader.cpp b/media/libstagefright/httplive/HTTPDownloader.cpp
index 68f1de9..5ac1b9f 100644
--- a/media/libstagefright/httplive/HTTPDownloader.cpp
+++ b/media/libstagefright/httplive/HTTPDownloader.cpp
@@ -209,7 +209,7 @@
     *out = buffer;
     if (actualUrl != NULL) {
         *actualUrl = mDataSource->getUri();
-        if (actualUrl->isEmpty()) {
+        if (actualUrl->empty()) {
             *actualUrl = url;
         }
     }
@@ -265,7 +265,7 @@
 #endif
 
     sp<M3UParser> playlist =
-        new M3UParser(actualUrl.string(), buffer->data(), buffer->size());
+        new M3UParser(actualUrl.c_str(), buffer->data(), buffer->size());
 
     if (playlist->initCheck() != OK) {
         ALOGE("failed to parse .m3u8 playlist");
diff --git a/media/libstagefright/include/ACodecBufferChannel.h b/media/libstagefright/include/ACodecBufferChannel.h
index a464504..946d533 100644
--- a/media/libstagefright/include/ACodecBufferChannel.h
+++ b/media/libstagefright/include/ACodecBufferChannel.h
@@ -72,8 +72,8 @@
     void setCrypto(const sp<ICrypto> &crypto) override;
     void setDescrambler(const sp<IDescrambler> &descrambler) override;
 
-    virtual status_t queueInputBuffer(const sp<MediaCodecBuffer> &buffer) override;
-    virtual status_t queueSecureInputBuffer(
+    status_t queueInputBuffer(const sp<MediaCodecBuffer> &buffer) override;
+    status_t queueSecureInputBuffer(
             const sp<MediaCodecBuffer> &buffer,
             bool secure,
             const uint8_t *key,
@@ -83,10 +83,10 @@
             const CryptoPlugin::SubSample *subSamples,
             size_t numSubSamples,
             AString *errorDetailMsg) override;
-    virtual status_t attachBuffer(
+    status_t attachBuffer(
             const std::shared_ptr<C2Buffer> &c2Buffer,
             const sp<MediaCodecBuffer> &buffer) override;
-    virtual status_t attachEncryptedBuffer(
+    status_t attachEncryptedBuffer(
             const sp<hardware::HidlMemory> &memory,
             bool secure,
             const uint8_t *key,
@@ -98,12 +98,12 @@
             size_t numSubSamples,
             const sp<MediaCodecBuffer> &buffer,
             AString* errorDetailMsg) override;
-    virtual status_t renderOutputBuffer(
+    status_t renderOutputBuffer(
             const sp<MediaCodecBuffer> &buffer, int64_t timestampNs) override;
-    virtual void pollForRenderedBuffers() override;
-    virtual status_t discardBuffer(const sp<MediaCodecBuffer> &buffer) override;
-    virtual void getInputBufferArray(Vector<sp<MediaCodecBuffer>> *array) override;
-    virtual void getOutputBufferArray(Vector<sp<MediaCodecBuffer>> *array) override;
+    void pollForRenderedBuffers() override;
+    status_t discardBuffer(const sp<MediaCodecBuffer> &buffer) override;
+    void getInputBufferArray(Vector<sp<MediaCodecBuffer>> *array) override;
+    void getOutputBufferArray(Vector<sp<MediaCodecBuffer>> *array) override;
 
     // Methods below are interface for ACodec to use.
 
diff --git a/media/libstagefright/include/media/stagefright/MediaHistogram.h b/media/libstagefright/include/media/stagefright/MediaHistogram.h
index 50fa258..46ee288 100644
--- a/media/libstagefright/include/media/stagefright/MediaHistogram.h
+++ b/media/libstagefright/include/media/stagefright/MediaHistogram.h
@@ -29,11 +29,11 @@
 public:
     MediaHistogram();
     void clear();
-    bool setup(int bucketCount, T width, T floor = 0);
+    bool setup(size_t bucketCount, T width, T floor = 0);
     bool setup(const std::vector<T> &bucketLimits);
     void insert(T sample);
-    size_t size();
-    int64_t operator[](int);
+    size_t size() const;
+    int64_t operator[](int) const;
     T getMin() const { return mMin; }
     T getMax() const { return mMax; }
     T getCount() const { return mCount; }
@@ -45,7 +45,7 @@
 private:
     MediaHistogram(const MediaHistogram &); // disallow
 
-    bool allocate(int bucketCount, bool withBucketLimits);
+    void allocate(size_t bucketCount, bool withBucketLimits);
 
     T mFloor, mCeiling, mWidth;
     T mMin, mMax, mSum;
@@ -73,13 +73,12 @@
 }
 
 template<typename T>
-bool MediaHistogram<T>::setup(int bucketCount, T width, T floor) {
+bool MediaHistogram<T>::setup(size_t bucketCount, T width, T floor) {
     if (bucketCount <= 0 || width <= 0) {
         return false;
     }
-    if (!allocate(bucketCount, false)) {
-        return false;
-    }
+    allocate(bucketCount, false);
+
     mWidth = width;
     mFloor = floor;
     mCeiling = floor + bucketCount * width;
@@ -92,14 +91,14 @@
     if (bucketLimits.size() <= 1) {
         return false;
     }
-    int bucketCount = bucketLimits.size() - 1;
-    if (!allocate(bucketCount, true)) {
-        return false;
-    }
+    // The floor is the first bucket limit value, so offset by 1
+    size_t bucketCount = bucketLimits.size() - 1;
+    allocate(bucketCount, true);
 
     mWidth = -1;
     mFloor = bucketLimits[0];
-    for (int i = 0; i < bucketCount; ++i) {
+    for (size_t i = 0; i < bucketCount; ++i) {
+        // The floor is the first bucket, so offset by 1
         mBucketLimits[i] = bucketLimits[i + 1];
     }
     mCeiling = bucketLimits[bucketCount];
@@ -108,7 +107,7 @@
 }
 
 template<typename T>
-bool MediaHistogram<T>::allocate(int bucketCount, bool withBucketLimits) {
+void MediaHistogram<T>::allocate(size_t bucketCount, bool withBucketLimits) {
     assert(bucketCount > 0);
     if (bucketCount != mBuckets.size()) {
         mBuckets = std::vector<T>(bucketCount, 0);
@@ -116,7 +115,6 @@
     if (withBucketLimits && mBucketLimits.size() != bucketCount) {
         mBucketLimits = std::vector<T>(bucketCount, 0);
     }
-    return true;
 }
 
 template<typename T>
@@ -128,8 +126,8 @@
 
     mCount++;
     mSum += sample;
-    if (mMin > sample) mMin = sample;
-    if (mMax < sample) mMax = sample;
+    mMin = std::min(mMin, sample);
+    mMax = std::max(mMax, sample);
 
     if (sample < mFloor) {
         mBelow++;
@@ -138,7 +136,7 @@
     } else if (mWidth == -1) {
         // A binary search might be more efficient for large number of buckets, but it is expected
         // that there will never be a large amount of buckets, so keep the code simple.
-        for (int slot = 0; slot < mBucketLimits.size(); ++slot) {
+        for (size_t slot = 0; slot < mBucketLimits.size(); ++slot) {
             if (sample < mBucketLimits[slot]) {
                 mBuckets[slot]++;
                 break;
@@ -153,12 +151,12 @@
 }
 
 template<typename T>
-size_t MediaHistogram<T>::size() {
+size_t MediaHistogram<T>::size() const {
     return mBuckets.size() + 1;
 }
 
 template<typename T>
-int64_t MediaHistogram<T>::operator[](int i) {
+int64_t MediaHistogram<T>::operator[](int i) const {
     assert(i >= 0);
     assert(i <= mBuckets.size());
     if (i == mBuckets.size()) {
@@ -179,7 +177,7 @@
     } else {
         ss << mFloor << "," << mWidth << "," << mBelow << "{";
     }
-    for (int i = 0; i < mBuckets.size(); i++) {
+    for (size_t i = 0; i < mBuckets.size(); i++) {
         if (i != 0) {
             ss << ",";
         }
@@ -194,12 +192,12 @@
     std::stringstream ss("");
     if (mWidth == -1) {
         ss << mFloor;
-        for (int i = 0; i < mBucketLimits.size(); ++i) {
+        for (size_t i = 0; i < mBucketLimits.size(); ++i) {
             ss << ',' << mBucketLimits[i];
         }
     } else {
         ss << mFloor;
-        for (int i = 1; i <= mBuckets.size(); ++i) {
+        for (size_t i = 1; i <= mBuckets.size(); ++i) {
             ss << ',' << (mFloor + i * mWidth);
         }
     }
diff --git a/media/libstagefright/include/media/stagefright/RemoteDataSource.h b/media/libstagefright/include/media/stagefright/RemoteDataSource.h
index d605cda..621d772 100644
--- a/media/libstagefright/include/media/stagefright/RemoteDataSource.h
+++ b/media/libstagefright/include/media/stagefright/RemoteDataSource.h
@@ -106,7 +106,7 @@
         if (mMemory.get() == nullptr) {
             ALOGE("Failed to allocate memory!");
         }
-        mName = String8::format("RemoteDataSource(%s)", mSource->toString().string());
+        mName = String8::format("RemoteDataSource(%s)", mSource->toString().c_str());
     }
 
     DISALLOW_EVIL_CONSTRUCTORS(RemoteDataSource);
diff --git a/media/libstagefright/omx/OMXStore.cpp b/media/libstagefright/omx/OMXStore.cpp
index 0906433..b2d5a70 100644
--- a/media/libstagefright/omx/OMXStore.cpp
+++ b/media/libstagefright/omx/OMXStore.cpp
@@ -167,7 +167,7 @@
 
         if (mPluginByComponentName.indexOfKey(name8) >= 0) {
             ALOGE("A component of name '%s' already exists, ignoring this one.",
-                 name8.string());
+                 name8.c_str());
 
             continue;
         }
@@ -263,7 +263,7 @@
     const String8 &name8 = mPluginByComponentName.keyAt(index);
 
     CHECK(size >= 1 + name8.size());
-    strcpy(name, name8.string());
+    strcpy(name, name8.c_str());
 
     return OMX_ErrorNone;
 }
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/1.0/Conversion.h b/media/libstagefright/omx/include/media/stagefright/omx/1.0/Conversion.h
index 1c3cb4e..a6e23ed 100644
--- a/media/libstagefright/omx/include/media/stagefright/omx/1.0/Conversion.h
+++ b/media/libstagefright/omx/include/media/stagefright/omx/1.0/Conversion.h
@@ -540,11 +540,11 @@
  */
 // convert: IOMX::ComponentInfo -> IOmx::ComponentInfo
 inline bool convertTo(IOmx::ComponentInfo* t, IOMX::ComponentInfo const& l) {
-    t->mName = l.mName.string();
+    t->mName = l.mName.c_str();
     t->mRoles.resize(l.mRoles.size());
     size_t i = 0;
     for (auto& role : l.mRoles) {
-        t->mRoles[i++] = role.string();
+        t->mRoles[i++] = role.c_str();
     }
     return true;
 }
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/libstagefright/omx/tests/OMXHarness.cpp b/media/libstagefright/omx/tests/OMXHarness.cpp
index 039991c..b9bea1a 100644
--- a/media/libstagefright/omx/tests/OMXHarness.cpp
+++ b/media/libstagefright/omx/tests/OMXHarness.cpp
@@ -789,7 +789,7 @@
     for (List<IOMX::ComponentInfo>::iterator it = componentInfos.begin();
          it != componentInfos.end(); ++it) {
         const IOMX::ComponentInfo &info = *it;
-        const char *componentName = info.mName.string();
+        const char *componentName = info.mName.c_str();
 
         if (strncmp(componentName, "OMX.google.", 11)) {
             continue;
@@ -797,7 +797,7 @@
 
         for (List<String8>::const_iterator role_it = info.mRoles.begin();
              role_it != info.mRoles.end(); ++role_it) {
-            const char *componentRole = (*role_it).string();
+            const char *componentRole = (*role_it).c_str();
 
             err = test(componentName, componentRole);
 
diff --git a/media/libstagefright/renderfright/gl/GLExtensions.cpp b/media/libstagefright/renderfright/gl/GLExtensions.cpp
index 2924b0e..4717c68 100644
--- a/media/libstagefright/renderfright/gl/GLExtensions.cpp
+++ b/media/libstagefright/renderfright/gl/GLExtensions.cpp
@@ -68,19 +68,19 @@
 }
 
 char const* GLExtensions::getVendor() const {
-    return mVendor.string();
+    return mVendor.c_str();
 }
 
 char const* GLExtensions::getRenderer() const {
-    return mRenderer.string();
+    return mRenderer.c_str();
 }
 
 char const* GLExtensions::getVersion() const {
-    return mVersion.string();
+    return mVersion.c_str();
 }
 
 char const* GLExtensions::getExtensions() const {
-    return mExtensions.string();
+    return mExtensions.c_str();
 }
 
 void GLExtensions::initWithEGLStrings(char const* eglVersion, char const* eglExtensions) {
@@ -123,11 +123,11 @@
 }
 
 char const* GLExtensions::getEGLVersion() const {
-    return mEGLVersion.string();
+    return mEGLVersion.c_str();
 }
 
 char const* GLExtensions::getEGLExtensions() const {
-    return mEGLExtensions.string();
+    return mEGLExtensions.c_str();
 }
 
 } // namespace gl
diff --git a/media/libstagefright/renderfright/gl/ProgramCache.cpp b/media/libstagefright/renderfright/gl/ProgramCache.cpp
index af55172..350f0b7 100644
--- a/media/libstagefright/renderfright/gl/ProgramCache.cpp
+++ b/media/libstagefright/renderfright/gl/ProgramCache.cpp
@@ -62,7 +62,7 @@
         return out;
     }
     friend inline Formatter& operator<<(Formatter& out, const String8& in) {
-        return operator<<(out, in.string());
+        return operator<<(out, in.c_str());
     }
     friend inline Formatter& operator<<(Formatter& to, FormaterManipFunc func) {
         return (*func)(to);
@@ -778,7 +778,7 @@
     // fragment shader
     String8 fs = generateFragmentShader(needs);
 
-    return std::make_unique<Program>(needs, vs.string(), fs.string());
+    return std::make_unique<Program>(needs, vs.c_str(), fs.c_str());
 }
 
 void ProgramCache::useProgram(EGLContext context, const Description& description) {
diff --git a/media/libstagefright/rtsp/AAVCAssembler.cpp b/media/libstagefright/rtsp/AAVCAssembler.cpp
index 100c0cd..fc9f58e 100644
--- a/media/libstagefright/rtsp/AAVCAssembler.cpp
+++ b/media/libstagefright/rtsp/AAVCAssembler.cpp
@@ -203,12 +203,12 @@
                     seqNum, mNextExpectedSeqNo,
                     baseJbTimeMs, dynamicJbTimeMs, tryJbTimeMs, JITTER_MULTIPLE);
         if (isSecondLineBroken) {
-            ALOGE("%s", info.string());
+            ALOGE("%s", info.c_str());
             printNowTimeMs(startTimeMs, nowTimeMs, playedTimeMs);
             printRTPTime(rtpTime, playedTimeRtp, expiredTimeRtp, isExpired);
 
         }  else {
-            ALOGW("%s", info.string());
+            ALOGW("%s", info.c_str());
         }
     }
 
diff --git a/media/libstagefright/rtsp/AHEVCAssembler.cpp b/media/libstagefright/rtsp/AHEVCAssembler.cpp
index 7b5c24a..06f19ab 100644
--- a/media/libstagefright/rtsp/AHEVCAssembler.cpp
+++ b/media/libstagefright/rtsp/AHEVCAssembler.cpp
@@ -213,12 +213,12 @@
                     seqNum, mNextExpectedSeqNo,
                     baseJbTimeMs, dynamicJbTimeMs, tryJbTimeMs, JITTER_MULTIPLE);
         if (isSecondLineBroken) {
-            ALOGE("%s", info.string());
+            ALOGE("%s", info.c_str());
             printNowTimeMs(startTimeMs, nowTimeMs, playedTimeMs);
             printRTPTime(rtpTime, playedTimeRtp, expiredTimeRtp, isExpired);
 
         }  else {
-            ALOGW("%s", info.string());
+            ALOGW("%s", info.c_str());
         }
     }
 
diff --git a/media/libstagefright/rtsp/ARTPWriter.cpp b/media/libstagefright/rtsp/ARTPWriter.cpp
index bc83410..bc57ef7 100644
--- a/media/libstagefright/rtsp/ARTPWriter.cpp
+++ b/media/libstagefright/rtsp/ARTPWriter.cpp
@@ -1648,11 +1648,11 @@
         memset(&mRTCPAddr6, 0, sizeof(mRTCPAddr6));
 
         mLocalAddr6.sin6_family = AF_INET6;
-        inet_pton(AF_INET6, localIp.string(), &mLocalAddr6.sin6_addr);
+        inet_pton(AF_INET6, localIp.c_str(), &mLocalAddr6.sin6_addr);
         mLocalAddr6.sin6_port = htons((uint16_t)localPort);
 
         mRTPAddr6.sin6_family = AF_INET6;
-        inet_pton(AF_INET6, remoteIp.string(), &mRTPAddr6.sin6_addr);
+        inet_pton(AF_INET6, remoteIp.c_str(), &mRTPAddr6.sin6_addr);
         mRTPAddr6.sin6_port = htons((uint16_t)remotePort);
 
         mRTCPAddr6 = mRTPAddr6;
@@ -1663,11 +1663,11 @@
         memset(&mRTCPAddr, 0, sizeof(mRTCPAddr));
 
         mLocalAddr.sin_family = AF_INET;
-        mLocalAddr.sin_addr.s_addr = inet_addr(localIp.string());
+        mLocalAddr.sin_addr.s_addr = inet_addr(localIp.c_str());
         mLocalAddr.sin_port = htons((uint16_t)localPort);
 
         mRTPAddr.sin_family = AF_INET;
-        mRTPAddr.sin_addr.s_addr = inet_addr(remoteIp.string());
+        mRTPAddr.sin_addr.s_addr = inet_addr(remoteIp.c_str());
         mRTPAddr.sin_port = htons((uint16_t)remotePort);
 
         mRTCPAddr = mRTPAddr;
@@ -1680,9 +1680,9 @@
     int sizeSockSt = mIsIPv6 ? sizeof(mLocalAddr6) : sizeof(mLocalAddr);
 
     if (bind(mRTPSocket, localAddr, sizeSockSt) == -1) {
-        ALOGE("failed to bind rtp %s:%d err=%s", localIp.string(), localPort, strerror(errno));
+        ALOGE("failed to bind rtp %s:%d err=%s", localIp.c_str(), localPort, strerror(errno));
     } else {
-        ALOGD("succeed to bind rtp %s:%d", localIp.string(), localPort);
+        ALOGD("succeed to bind rtp %s:%d", localIp.c_str(), localPort);
     }
 
     if (mIsIPv6)
@@ -1691,9 +1691,9 @@
         mLocalAddr.sin_port = htons((uint16_t)(localPort + 1));
 
     if (bind(mRTCPSocket, localAddr, sizeSockSt) == -1) {
-        ALOGE("failed to bind rtcp %s:%d err=%s", localIp.string(), localPort + 1, strerror(errno));
+        ALOGE("failed to bind rtcp %s:%d err=%s", localIp.c_str(), localPort + 1, strerror(errno));
     } else {
-        ALOGD("succeed to bind rtcp %s:%d", localIp.string(), localPort + 1);
+        ALOGD("succeed to bind rtcp %s:%d", localIp.c_str(), localPort + 1);
     }
 }
 
diff --git a/media/libstagefright/writer_fuzzers/WriterFuzzerBase.cpp b/media/libstagefright/writer_fuzzers/WriterFuzzerBase.cpp
index b97f347..2016b2a 100644
--- a/media/libstagefright/writer_fuzzers/WriterFuzzerBase.cpp
+++ b/media/libstagefright/writer_fuzzers/WriterFuzzerBase.cpp
@@ -192,7 +192,9 @@
     sp<MetaData> trackMeta = new MetaData;
     convertMessageToMetaData(format, trackMeta);
     mCurrentTrack[trackIndex] = new MediaAdapter(trackMeta);
-    mWriter->addSource(mCurrentTrack[trackIndex]);
+    if (mWriter->addSource(mCurrentTrack[trackIndex]) != OK) {
+        mCurrentTrack[trackIndex] = nullptr;
+    }
 }
 
 void WriterFuzzerBase::start() {
@@ -202,13 +204,14 @@
 
 void WriterFuzzerBase::sendBuffersToWriter(sp<MediaAdapter> &currentTrack, int32_t trackIndex,
                                            int32_t startFrameIndex, int32_t endFrameIndex) {
+    if (!mCurrentTrack[trackIndex]) {
+        return;
+    }
     vector<FrameData> bufferInfo = mBufferSource->getFrameList(trackIndex);
     for (int idx = startFrameIndex; idx < endFrameIndex; ++idx) {
         sp<ABuffer> buffer = new ABuffer((void *)bufferInfo[idx].buf, bufferInfo[idx].size);
         MediaBuffer *mediaBuffer = new MediaBuffer(buffer);
 
-        // Released in MediaAdapter::signalBufferReturned().
-        mediaBuffer->add_ref();
         mediaBuffer->set_range(buffer->offset(), buffer->size());
         MetaDataBase &sampleMetaData = mediaBuffer->meta_data();
         sampleMetaData.setInt64(kKeyTime, bufferInfo[idx].timeUs);
@@ -219,8 +222,13 @@
             sampleMetaData.setInt32(kKeyIsSyncFrame, true);
         }
 
+        // Released in MediaAdapter::signalBufferReturned().
+        mediaBuffer->add_ref();
+
         // This pushBuffer will wait until the mediaBuffer is consumed.
-        currentTrack->pushBuffer(mediaBuffer);
+        if (currentTrack->pushBuffer(mediaBuffer) != OK) {
+            mediaBuffer->release();
+        }
     }
 }
 
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/mp3/MP3Extractor.cpp b/media/module/extractors/mp3/MP3Extractor.cpp
index 328b790..d0e9852 100644
--- a/media/module/extractors/mp3/MP3Extractor.cpp
+++ b/media/module/extractors/mp3/MP3Extractor.cpp
@@ -379,8 +379,8 @@
             String8 commentdesc;
             String8 commentvalue;
             com->getString(&commentdesc, &commentvalue);
-            const char * desc = commentdesc.string();
-            const char * value = commentvalue.string();
+            const char * desc = commentdesc.c_str();
+            const char * value = commentvalue.c_str();
 
             // first 3 characters are the language, which we don't care about
             if(strlen(desc) > 3 && strcmp(desc + 3, "iTunSMPB") == 0) {
@@ -652,7 +652,7 @@
         it->getString(&s);
         delete it;
 
-        AMediaFormat_setString(meta, kMap[i].key, s.string());
+        AMediaFormat_setString(meta, kMap[i].key, s.c_str());
     }
 
     size_t dataSize;
diff --git a/media/module/extractors/mp4/Android.bp b/media/module/extractors/mp4/Android.bp
index 540d75d..8072002 100644
--- a/media/module/extractors/mp4/Android.bp
+++ b/media/module/extractors/mp4/Android.bp
@@ -30,6 +30,7 @@
 
     srcs: [
         "AC4Parser.cpp",
+        "HeifCleanAperture.cpp",
         "ItemTable.cpp",
         "MPEG4Extractor.cpp",
         "SampleIterator.cpp",
diff --git a/media/module/extractors/mp4/HeifCleanAperture.cpp b/media/module/extractors/mp4/HeifCleanAperture.cpp
new file mode 100644
index 0000000..f0a0867
--- /dev/null
+++ b/media/module/extractors/mp4/HeifCleanAperture.cpp
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2023 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.
+ */
+
+#include <HeifCleanAperture.h>
+
+namespace android {
+namespace heif {
+namespace {
+
+// |a| and |b| hold int32_t values. The int64_t type is used so that we can negate INT32_MIN without
+// overflowing int32_t.
+int64_t calculateGreatestCommonDivisor(int64_t a, int64_t b) {
+    if (a < 0) {
+        a *= -1;
+    }
+    if (b < 0) {
+        b *= -1;
+    }
+    while (b != 0) {
+        int64_t r = a % b;
+        a = b;
+        b = r;
+    }
+    return a;
+}
+
+bool overflowsInt32(int64_t x) {
+    return (x < INT32_MIN) || (x > INT32_MAX);
+}
+
+Fraction calculateCenter(int32_t value) {
+    Fraction f(value, 2);
+    f.simplify();
+    return f;
+}
+
+}  // namespace
+
+Fraction::Fraction(int32_t n, int32_t d) {
+    this->n = n;
+    this->d = d;
+}
+
+void Fraction::simplify() {
+    int64_t gcd = calculateGreatestCommonDivisor(n, d);
+    if (gcd > 1) {
+        n = static_cast<int32_t>(n / gcd);
+        d = static_cast<int32_t>(d / gcd);
+    }
+}
+
+bool Fraction::commonDenominator(Fraction* f) {
+    simplify();
+    f->simplify();
+    if (d == f->d) return true;
+    const int64_t this_d = d;
+    const int64_t fd = f->d;
+    const int64_t thisnNew = n * fd;
+    const int64_t thisdNew = d * fd;
+    const int64_t fnNew = f->n * this_d;
+    const int64_t fdNew = f->d * this_d;
+    if (overflowsInt32(thisnNew) || overflowsInt32(thisdNew) || overflowsInt32(fnNew) ||
+        overflowsInt32(fdNew)) {
+        return false;
+    }
+    n = static_cast<int32_t>(thisnNew);
+    d = static_cast<int32_t>(thisdNew);
+    f->n = static_cast<int32_t>(fnNew);
+    f->d = static_cast<int32_t>(fdNew);
+    return true;
+}
+
+bool Fraction::add(Fraction f) {
+    if (!commonDenominator(&f)) {
+        return false;
+    }
+
+    const int64_t result = static_cast<int64_t>(n) + f.n;
+    if (overflowsInt32(result)) {
+        return false;
+    }
+    n = static_cast<int32_t>(result);
+    simplify();
+    return true;
+}
+
+bool Fraction::subtract(Fraction f) {
+    if (!commonDenominator(&f)) {
+        return false;
+    }
+
+    const int64_t result = static_cast<int64_t>(n) - f.n;
+    if (overflowsInt32(result)) {
+        return false;
+    }
+    n = static_cast<int32_t>(result);
+    simplify();
+    return true;
+}
+
+bool convertCleanApertureToRect(uint32_t imageW, uint32_t imageH, const CleanAperture& clap,
+                                int32_t* left, int32_t* top, int32_t* right, int32_t* bottom) {
+    // ISO/IEC 14496-12:2020, Section 12.1.4.1:
+    //   For horizOff and vertOff, D shall be strictly positive and N may be
+    //   positive or negative. For cleanApertureWidth and cleanApertureHeight,
+    //   N shall be positive and D shall be strictly positive.
+    if (clap.width.d <= 0 || clap.height.d <= 0 || clap.horizOff.d <= 0 || clap.vertOff.d <= 0 ||
+        clap.width.n < 0 || clap.height.n < 0 || !clap.width.isInteger() ||
+        !clap.height.isInteger() || imageW > INT32_MAX || imageH > INT32_MAX) {
+        return false;
+    }
+
+    const int32_t clapW = clap.width.getInt32();
+    const int32_t clapH = clap.height.getInt32();
+    if (clapW == 0 || clapH == 0) {
+        return false;
+    }
+
+    Fraction centerX = calculateCenter(imageW);
+    Fraction centerY = calculateCenter(imageH);
+    Fraction halfW(clapW, 2);
+    Fraction halfH(clapH, 2);
+
+    if (!centerX.add(clap.horizOff) || !centerX.subtract(halfW) || !centerX.isInteger() ||
+        centerX.n < 0 || !centerY.add(clap.vertOff) || !centerY.subtract(halfH) ||
+        !centerY.isInteger() || centerY.n < 0) {
+        return false;
+    }
+
+    *left = centerX.getInt32();
+    *top = centerY.getInt32();
+    *right = *left + clapW;
+    *bottom = *top + clapH;
+
+    // Make sure that the crop rect is within the image bounds.
+    if (*left > (UINT32_MAX - clapW) || *right > imageW || *top > (UINT32_MAX - clapH) ||
+        *bottom > imageH) {
+        return false;
+    }
+    return true;
+}
+
+}  // namespace heif
+}  // namespace android
diff --git a/media/module/extractors/mp4/ItemTable.cpp b/media/module/extractors/mp4/ItemTable.cpp
index 444664c..cf3df62 100644
--- a/media/module/extractors/mp4/ItemTable.cpp
+++ b/media/module/extractors/mp4/ItemTable.cpp
@@ -19,6 +19,7 @@
 
 #include <unordered_set>
 
+#include <HeifCleanAperture.h>
 #include <ItemTable.h>
 #include <media/MediaExtractorPluginApi.h>
 #include <media/MediaExtractorPluginHelper.h>
@@ -47,7 +48,7 @@
     ImageItem(uint32_t _type, uint32_t _id, bool _hidden) :
             type(_type), itemId(_id), hidden(_hidden),
             rows(0), columns(0), width(0), height(0), rotation(0),
-            offset(0), size(0), nextTileIndex(0) {}
+            offset(0), size(0), seenClap(false), nextTileIndex(0) {}
 
     bool isGrid() const {
         return type == FOURCC("grid");
@@ -77,6 +78,8 @@
     sp<ABuffer> hvcc;
     sp<ABuffer> icc;
     sp<ABuffer> av1c;
+    bool seenClap;
+    CleanAperture clap;
 
     Vector<uint32_t> thumbnails;
     Vector<uint32_t> dimgRefs;
@@ -833,6 +836,47 @@
     return OK;
 }
 
+struct ClapBox : public Box, public ItemProperty {
+    ClapBox(DataSourceHelper *source) :
+        Box(source, FOURCC("clap")), mSeen(false) {}
+
+    status_t parse(off64_t offset, size_t size) override;
+
+    void attachTo(ImageItem &image) const override {
+        image.seenClap = mSeen;
+        if (!mSeen) return;
+        image.clap = mClap;
+    }
+
+private:
+    bool mSeen;
+    CleanAperture mClap;
+};
+
+status_t ClapBox::parse(off64_t offset, size_t size) {
+    ALOGV("%s: offset %lld, size %zu", __FUNCTION__, (long long)offset, size);
+
+    if (size < 32) {
+        return ERROR_MALFORMED;
+    }
+    mSeen = true;
+    uint32_t values[8];
+    for (int i = 0; i < 8; ++i, offset += 4) {
+        if (!source()->getUInt32(offset, &values[i])) {
+            return ERROR_IO;
+        }
+    }
+    mClap.width.n = values[0];
+    mClap.width.d = values[1];
+    mClap.height.n = values[2];
+    mClap.height.d = values[3];
+    mClap.horizOff.n = values[4];
+    mClap.horizOff.d = values[5];
+    mClap.vertOff.n = values[6];
+    mClap.vertOff.d = values[7];
+    return OK;
+}
+
 struct ColrBox : public Box, public ItemProperty {
     ColrBox(DataSourceHelper *source) :
         Box(source, FOURCC("colr")) {}
@@ -992,6 +1036,11 @@
             itemProperty = new IrotBox(source());
             break;
         }
+        case FOURCC("clap"):
+        {
+            itemProperty = new ClapBox(source());
+            break;
+        }
         case FOURCC("colr"):
         {
             itemProperty = new ColrBox(source());
@@ -1111,7 +1160,7 @@
         }
         buf.push_back(tmp);
         if (tmp == 0) {
-            out->setTo(buf.array());
+            *out = buf.array();
 
             *offset = newOffset;
             *size = stopOffset - newOffset;
@@ -1599,6 +1648,12 @@
     AMediaFormat_setInt32(meta,
             AMEDIAFORMAT_KEY_MAX_INPUT_SIZE, image->width * image->height * 3 / 2);
 
+    int32_t left, top, right, bottom;
+    if (image->seenClap && convertCleanApertureToRect(image->width, image->height, image->clap,
+                                                      &left, &top, &right, &bottom)) {
+        AMediaFormat_setRect(meta, AMEDIAFORMAT_KEY_DISPLAY_CROP, left, top, right - 1, bottom - 1);
+    }
+
     if (!image->thumbnails.empty()) {
         ssize_t thumbItemIndex = mItemIdToItemMap.indexOfKey(image->thumbnails[0]);
         if (thumbItemIndex >= 0) {
diff --git a/media/module/extractors/mp4/MPEG4Extractor.cpp b/media/module/extractors/mp4/MPEG4Extractor.cpp
index 184e4f4..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;
@@ -1794,7 +1794,7 @@
                 String8 mimeFormat(str + 8 + encoding_length + 1,
                         chunk_data_size - 8 - encoding_length - 1);
                 AMediaFormat_setString(mLastTrack->meta,
-                        AMEDIAFORMAT_KEY_MIME, mimeFormat.string());
+                        AMEDIAFORMAT_KEY_MIME, mimeFormat.c_str());
             }
             break;
         }
@@ -2813,7 +2813,7 @@
 
             String8 s;
             if (convertTimeToDate(creationTime, &s)) {
-                AMediaFormat_setString(mFileMetaData, AMEDIAFORMAT_KEY_DATE, s.string());
+                AMediaFormat_setString(mFileMetaData, AMEDIAFORMAT_KEY_DATE, s.c_str());
             }
 
             break;
@@ -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;
             }
 
@@ -4368,7 +4368,7 @@
         } else {
             // Convert from UTF-16 string to UTF-8 string.
             String8 tmpUTF8str(framedata, len16);
-            AMediaFormat_setString(mFileMetaData, metadataKey, tmpUTF8str.string());
+            AMediaFormat_setString(mFileMetaData, metadataKey, tmpUTF8str.c_str());
         }
     }
 
diff --git a/media/module/extractors/mp4/include/HeifCleanAperture.h b/media/module/extractors/mp4/include/HeifCleanAperture.h
new file mode 100644
index 0000000..930197d
--- /dev/null
+++ b/media/module/extractors/mp4/include/HeifCleanAperture.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2023 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 HEIF_CLEAN_APERTURE_H_
+#define HEIF_CLEAN_APERTURE_H_
+
+#include <stdint.h>
+
+namespace android {
+namespace heif {
+
+struct Fraction {
+    Fraction() = default;
+    Fraction(int32_t n, int32_t d);
+
+    void simplify();
+    bool commonDenominator(Fraction* f);
+    bool add(Fraction f);
+    bool subtract(Fraction f);
+    bool isInteger() const { return n % d == 0; }
+    int32_t getInt32() const { return n / d; }
+    int32_t n;
+    int32_t d;
+};
+
+struct CleanAperture {
+    Fraction width;
+    Fraction height;
+    Fraction horizOff;
+    Fraction vertOff;
+};
+
+// Converts the CleanAperture value into a rectangle with bounds left, top, right and bottom.
+// Returns true on success, false otherwise.
+bool convertCleanApertureToRect(uint32_t imageW, uint32_t imageH, const CleanAperture& image,
+                                int32_t* left, int32_t* top, int32_t* right, int32_t* bottom);
+
+}  // namespace heif
+}  // namespace android
+
+#endif  // HEIF_CLEAN_APERTURE_H_
diff --git a/media/module/extractors/mp4/tests/Android.bp b/media/module/extractors/mp4/tests/Android.bp
new file mode 100644
index 0000000..252cec2
--- /dev/null
+++ b/media/module/extractors/mp4/tests/Android.bp
@@ -0,0 +1,24 @@
+package {
+    default_applicable_licenses: ["frameworks_av_media_extractors_mp4_license"],
+}
+
+cc_test_host {
+    name: "HeifCleanApertureUnitTest",
+    gtest: true,
+
+    srcs: ["HeifCleanApertureUnitTest.cpp"],
+
+    header_libs: [
+        "libmp4extractor_headers",
+    ],
+
+    static_libs: [
+        "libmp4extractor",
+    ],
+
+    target: {
+        darwin: {
+            enabled: false,
+        },
+    },
+}
diff --git a/media/module/extractors/mp4/tests/HeifCleanApertureUnitTest.cpp b/media/module/extractors/mp4/tests/HeifCleanApertureUnitTest.cpp
new file mode 100644
index 0000000..6a84ae3
--- /dev/null
+++ b/media/module/extractors/mp4/tests/HeifCleanApertureUnitTest.cpp
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2023 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.
+ */
+
+#include <stdint.h>
+
+#include <HeifCleanAperture.h>
+#include <gtest/gtest.h>
+
+namespace {
+
+using android::heif::CleanAperture;
+using android::heif::convertCleanApertureToRect;
+using android::heif::Fraction;
+
+struct InvalidClapPropertyParam {
+    uint32_t width;
+    uint32_t height;
+    CleanAperture clap;
+};
+
+const InvalidClapPropertyParam kInvalidClapPropertyTestParams[] = {
+        // Zero or negative denominators.
+        {120, 160, {Fraction(96, 0), Fraction(132, 1), Fraction(0, 1), Fraction(0, 1)}},
+        {120, 160, {Fraction(96, -1), Fraction(132, 1), Fraction(0, 1), Fraction(0, 1)}},
+        {120, 160, {Fraction(96, 1), Fraction(132, 0), Fraction(0, 1), Fraction(0, 1)}},
+        {120, 160, {Fraction(96, 1), Fraction(132, -1), Fraction(0, 1), Fraction(0, 1)}},
+        {120, 160, {Fraction(96, 1), Fraction(132, 1), Fraction(0, 0), Fraction(0, 1)}},
+        {120, 160, {Fraction(96, 1), Fraction(132, 1), Fraction(0, -1), Fraction(0, 1)}},
+        {120, 160, {Fraction(96, 1), Fraction(132, 1), Fraction(0, 1), Fraction(0, 0)}},
+        {120, 160, {Fraction(96, 1), Fraction(132, 1), Fraction(0, 1), Fraction(0, -1)}},
+        // Zero or negative clean aperture width or height.
+        {120, 160, {Fraction(-96, 1), Fraction(132, 1), Fraction(0, 1), Fraction(0, 1)}},
+        {120, 160, {Fraction(0, 1), Fraction(132, 1), Fraction(0, 1), Fraction(0, 1)}},
+        {120, 160, {Fraction(96, 1), Fraction(-132, 1), Fraction(0, 1), Fraction(0, 1)}},
+        {120, 160, {Fraction(96, 1), Fraction(0, 1), Fraction(0, 1), Fraction(0, 1)}},
+        // Clean aperture width or height is not an integer.
+        {120, 160, {Fraction(96, 5), Fraction(132, 1), Fraction(0, 1), Fraction(0, 1)}},
+        {120, 160, {Fraction(96, 1), Fraction(132, 5), Fraction(0, 1), Fraction(0, 1)}},
+        {722, 1024, {Fraction(385, 1), Fraction(330, 1), Fraction(103, 1), Fraction(-308, 1)}},
+        {1024, 722, {Fraction(330, 1), Fraction(385, 1), Fraction(-308, 1), Fraction(103, 1)}},
+};
+
+using InvalidClapPropertyTest = ::testing::TestWithParam<InvalidClapPropertyParam>;
+
+INSTANTIATE_TEST_SUITE_P(Parameterized, InvalidClapPropertyTest,
+                         ::testing::ValuesIn(kInvalidClapPropertyTestParams));
+
+// Negative tests for the convertCleanApertureToRect() function.
+TEST_P(InvalidClapPropertyTest, ValidateClapProperty) {
+    const InvalidClapPropertyParam& param = GetParam();
+    int32_t left, top, right, bottom;
+    EXPECT_FALSE(convertCleanApertureToRect(param.width, param.height, param.clap, &left, &top,
+                                            &right, &bottom));
+}
+
+struct ValidClapPropertyParam {
+    uint32_t width;
+    uint32_t height;
+    CleanAperture clap;
+
+    int32_t left;
+    int32_t top;
+    int32_t right;
+    int32_t bottom;
+};
+
+const ValidClapPropertyParam kValidClapPropertyTestParams[] = {
+        {120,
+         160,
+         {Fraction(96, 1), Fraction(132, 1), Fraction(0, 1), Fraction(0, 1)},
+         12,
+         14,
+         108,
+         146},
+        {120,
+         160,
+         {Fraction(60, 1), Fraction(80, 1), Fraction(-30, 1), Fraction(-40, 1)},
+         0,
+         0,
+         60,
+         80},
+};
+
+using ValidClapPropertyTest = ::testing::TestWithParam<ValidClapPropertyParam>;
+
+INSTANTIATE_TEST_SUITE_P(Parameterized, ValidClapPropertyTest,
+                         ::testing::ValuesIn(kValidClapPropertyTestParams));
+
+// Positive tests for the convertCleanApertureToRect() function.
+TEST_P(ValidClapPropertyTest, ValidateClapProperty) {
+    const ValidClapPropertyParam& param = GetParam();
+    int32_t left, top, right, bottom;
+    EXPECT_TRUE(convertCleanApertureToRect(param.width, param.height, param.clap, &left, &top,
+                                           &right, &bottom));
+    EXPECT_EQ(left, param.left);
+    EXPECT_EQ(top, param.top);
+    EXPECT_EQ(right, param.right);
+    EXPECT_EQ(bottom, param.bottom);
+}
+
+}  // namespace
diff --git a/media/module/foundation/ALooperRoster.cpp b/media/module/foundation/ALooperRoster.cpp
index 5625c7f..daa90be 100644
--- a/media/module/foundation/ALooperRoster.cpp
+++ b/media/module/foundation/ALooperRoster.cpp
@@ -180,7 +180,7 @@
         }
         s.append("\n");
     }
-    (void)write(fd, s.string(), s.size());
+    (void)write(fd, s.c_str(), s.size());
 }
 
 }  // namespace android
diff --git a/media/module/foundation/AString.cpp b/media/module/foundation/AString.cpp
index a5e0ff8..2f8011d 100644
--- a/media/module/foundation/AString.cpp
+++ b/media/module/foundation/AString.cpp
@@ -70,7 +70,7 @@
     : mData(NULL),
       mSize(0),
       mAllocSize(1) {
-    setTo(from.string(), from.length());
+    setTo(from.c_str(), from.length());
 }
 
 AString::AString(const AString &from)
diff --git a/media/module/foundation/MetaDataBase.cpp b/media/module/foundation/MetaDataBase.cpp
index 3370748..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,12 +437,13 @@
 
 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];
         MakeFourCCString(key, cc);
         const typed_data &item = mInternalData->mItems.valueAt(i);
-        s.appendFormat("%s: %s", cc, item.asString(false).string());
+        s.appendFormat("%s: %s", cc, item.asString(false).c_str());
         if (i != 0) {
             s.append(", ");
         }
@@ -443,18 +452,20 @@
 }
 
 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];
         MakeFourCCString(key, cc);
         const typed_data &item = mInternalData->mItems.valueAt(i);
-        ALOGI("%s: %s", cc, item.asString(true /* verbose */).string());
+        ALOGI("%s: %s", cc, item.asString(true /* verbose */).c_str());
     }
 }
 
 #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/foundation/tests/Base64_test.cpp b/media/module/foundation/tests/Base64_test.cpp
index 7a4289e..a3f93d9 100644
--- a/media/module/foundation/tests/Base64_test.cpp
+++ b/media/module/foundation/tests/Base64_test.cpp
@@ -49,7 +49,7 @@
                 paddedText.append(kBase64Padding);
             }
         }
-        sp<ABuffer> result = decodeBase64(AString(paddedText.string()));
+        sp<ABuffer> result = decodeBase64(AString(paddedText.c_str()));
 
         ASSERT_EQ(AStringUtils::Compare(expected[i].c_str(),
                 reinterpret_cast<char*>(result->data()),
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/media/module/id3/test/ID3Test.cpp b/media/module/id3/test/ID3Test.cpp
index a0a84ec..9da28d2 100644
--- a/media/module/id3/test/ID3Test.cpp
+++ b/media/module/id3/test/ID3Test.cpp
@@ -94,7 +94,7 @@
                 String8 text;
                 countTextFrames++;
                 it.getString(&text);
-                ALOGV("Found text frame %s : %s \n", id.string(), text.string());
+                ALOGV("Found text frame %s : %s \n", id.c_str(), text.c_str());
             }
             it.next();
         }
@@ -106,10 +106,10 @@
             ASSERT_GT(id.length(), 0) << "Found an ID3 tag of 0 size";
             it.getString(&text);
             // if the tag has a value
-            if (strcmp(text.string(), "")) {
+            if (strcmp(text.c_str(), "")) {
                 countTextFrames++;
                 ALOGV("ID: %s\n", id.c_str());
-                ALOGV("Text string: %s\n", text.string());
+                ALOGV("Text string: %s\n", text.c_str());
             }
             it.next();
         }
@@ -134,7 +134,7 @@
 
     if (albumArtPresent) {
         if (data) {
-            ALOGV("Found album art: size = %zu mime = %s \n", dataSize, mime.string());
+            ALOGV("Found album art: size = %zu mime = %s \n", dataSize, mime.c_str());
         }
         ASSERT_NE(data, nullptr) << "Expected album art, found none! " << path;
     } else {
@@ -168,7 +168,7 @@
             String8 mime;
             const void *data = tag.getAlbumArt(&dataSize, &mime);
             if (data) {
-                ALOGV("Found album art: size = %zu mime = %s \n", dataSize, mime.string());
+                ALOGV("Found album art: size = %zu mime = %s \n", dataSize, mime.c_str());
 #if (LOG_NDEBUG == 0)
                 hexdump(data, dataSize > 128 ? 128 : dataSize);
 #endif
diff --git a/media/module/id3/testid3.cpp b/media/module/id3/testid3.cpp
index 5cd51cf..e4f524b 100644
--- a/media/module/id3/testid3.cpp
+++ b/media/module/id3/testid3.cpp
@@ -90,9 +90,9 @@
                 String8 text;
                 it.getString(&text);
 
-                printf("  found text frame '%s': %s\n", id.string(), text.string());
+                printf("  found text frame '%s': %s\n", id.c_str(), text.c_str());
             } else {
-                printf("  found frame '%s'.\n", id.string());
+                printf("  found frame '%s'.\n", id.c_str());
             }
 
             it.next();
@@ -104,7 +104,7 @@
 
         if (data) {
             printf("found album art: size=%zu mime='%s'\n", dataSize,
-                   mime.string());
+                   mime.c_str());
 
             hexdump(data, dataSize > 128 ? 128 : dataSize);
         }
diff --git a/media/module/libmediatranscoding/TranscodingClientManager.cpp b/media/module/libmediatranscoding/TranscodingClientManager.cpp
index 6dbcaf9..18702a4 100644
--- a/media/module/libmediatranscoding/TranscodingClientManager.cpp
+++ b/media/module/libmediatranscoding/TranscodingClientManager.cpp
@@ -354,7 +354,7 @@
         result.append(buffer);
     }
 
-    write(fd, result.string(), result.size());
+    write(fd, result.c_str(), result.size());
 }
 
 bool TranscodingClientManager::isTrustedCaller(pid_t pid, uid_t uid) {
diff --git a/media/module/libmediatranscoding/TranscodingSessionController.cpp b/media/module/libmediatranscoding/TranscodingSessionController.cpp
index ea3e518..e9d19d3 100644
--- a/media/module/libmediatranscoding/TranscodingSessionController.cpp
+++ b/media/module/libmediatranscoding/TranscodingSessionController.cpp
@@ -421,7 +421,7 @@
         dumpSession_l(session, result, true /*closedSession*/);
     }
 
-    write(fd, result.string(), result.size());
+    write(fd, result.c_str(), result.size());
 }
 
 /*
diff --git a/media/module/service.mediatranscoding/MediaTranscodingService.cpp b/media/module/service.mediatranscoding/MediaTranscodingService.cpp
index 2a20981..2c73f3e 100644
--- a/media/module/service.mediatranscoding/MediaTranscodingService.cpp
+++ b/media/module/service.mediatranscoding/MediaTranscodingService.cpp
@@ -110,7 +110,7 @@
                     "Permission Denial: "
                     "can't dump MediaTranscodingService from pid=%d, uid=%d\n",
                     AIBinder_getCallingPid(), AIBinder_getCallingUid());
-            write(fd, result.string(), result.size());
+            write(fd, result.c_str(), result.size());
             return PERMISSION_DENIED;
         }
     }
@@ -120,7 +120,7 @@
 
     snprintf(buffer, SIZE, "MediaTranscodingService: %p\n", this);
     result.append(buffer);
-    write(fd, result.string(), result.size());
+    write(fd, result.c_str(), result.size());
 
     Vector<String16> args;
     mClientManager->dumpAllClients(fd, args);
diff --git a/media/module/service.mediatranscoding/tests/MediaTranscodingServiceTestHelper.h b/media/module/service.mediatranscoding/tests/MediaTranscodingServiceTestHelper.h
index 8e17f55..723bd77 100644
--- a/media/module/service.mediatranscoding/tests/MediaTranscodingServiceTestHelper.h
+++ b/media/module/service.mediatranscoding/tests/MediaTranscodingServiceTestHelper.h
@@ -76,7 +76,7 @@
     PermissionController pc;
     uid = pc.getPackageUid(packageName, 0);
     if (uid <= 0) {
-        ALOGE("Unknown package: '%s'", String8(packageName).string());
+        ALOGE("Unknown package: '%s'", String8(packageName).c_str());
         return BAD_VALUE;
     }
 
diff --git a/media/mtp/tests/MtpFuzzer/mtp_data_packet_fuzzer.cpp b/media/mtp/tests/MtpFuzzer/mtp_data_packet_fuzzer.cpp
index f5faf77..83c6076 100644
--- a/media/mtp/tests/MtpFuzzer/mtp_data_packet_fuzzer.cpp
+++ b/media/mtp/tests/MtpFuzzer/mtp_data_packet_fuzzer.cpp
@@ -212,7 +212,7 @@
                     if (mFdp.ConsumeBool()) {
                         std::string str = mFdp.ConsumeRandomLengthString(kMaxLength);
                         android::String16 s(str.c_str());
-                        char16_t* data = const_cast<char16_t*>(s.string());
+                        char16_t* data = const_cast<char16_t*>(s.c_str());
                         mtpDataPacket.putString(reinterpret_cast<uint16_t*>(data));
                     } else {
                         mtpDataPacket.putString(static_cast<uint16_t*>(nullptr));
diff --git a/media/mtp/tests/MtpFuzzer/mtp_property_fuzzer.cpp b/media/mtp/tests/MtpFuzzer/mtp_property_fuzzer.cpp
index b4e659c..6300256 100644
--- a/media/mtp/tests/MtpFuzzer/mtp_property_fuzzer.cpp
+++ b/media/mtp/tests/MtpFuzzer/mtp_property_fuzzer.cpp
@@ -101,7 +101,7 @@
                     std::string str = mFdp.ConsumeRandomLengthString(kMaxLength);
                     android::String16 s(str.c_str());
                     if (mFdp.ConsumeBool()) {
-                        data = const_cast<char16_t*>(s.string());
+                        data = const_cast<char16_t*>(s.c_str());
                     }
 
                     if (mFdp.ConsumeBool()) {
diff --git a/media/ndk/NdkImageReader.cpp b/media/ndk/NdkImageReader.cpp
index 0f7d98b..7b19ac0 100644
--- a/media/ndk/NdkImageReader.cpp
+++ b/media/ndk/NdkImageReader.cpp
@@ -344,7 +344,7 @@
     }
 
     mCbLooper = new ALooper;
-    mCbLooper->setName(consumerName.string());
+    mCbLooper->setName(consumerName.c_str());
     res = mCbLooper->start(
             /*runOnCallingThread*/false,
             /*canCallJava*/       true,
diff --git a/media/ndk/NdkMediaDrm.cpp b/media/ndk/NdkMediaDrm.cpp
index 0df7636..28a0233 100644
--- a/media/ndk/NdkMediaDrm.cpp
+++ b/media/ndk/NdkMediaDrm.cpp
@@ -478,7 +478,7 @@
         *keyRequest = mObj->mKeyRequest.array();
         *keyRequestSize = mObj->mKeyRequest.size();
         if (defaultUrl != NULL)
-            *defaultUrl = mObj->mDefaultUrl.string();
+            *defaultUrl = mObj->mDefaultUrl.c_str();
         switch(requestType) {
             case DrmPlugin::kKeyRequestType_Initial:
                 mObj->mkeyRequestType = KEY_REQUEST_TYPE_INITIAL;
@@ -606,8 +606,8 @@
     }
 
     for (size_t i = 0; i < mObj->mQueryResults.size(); i++) {
-        keyValuePairs[i].mKey = mObj->mQueryResults.keyAt(i).string();
-        keyValuePairs[i].mValue = mObj->mQueryResults.valueAt(i).string();
+        keyValuePairs[i].mKey = mObj->mQueryResults.keyAt(i).c_str();
+        keyValuePairs[i].mValue = mObj->mQueryResults.valueAt(i).c_str();
     }
     *numPairs = mObj->mQueryResults.size();
     return AMEDIA_OK;
@@ -630,7 +630,7 @@
     } else {
         *provisionRequest = mObj->mProvisionRequest.array();
         *provisionRequestSize = mObj->mProvisionRequest.size();
-        *serverUrl = mObj->mProvisionUrl.string();
+        *serverUrl = mObj->mProvisionUrl.c_str();
     }
     return AMEDIA_OK;
 }
@@ -714,7 +714,7 @@
             mObj->mPropertyString);
 
     if (status == OK) {
-        *propertyValue = mObj->mPropertyString.string();
+        *propertyValue = mObj->mPropertyString.c_str();
     } else {
         *propertyValue = NULL;
     }
diff --git a/media/ndk/NdkMediaFormat.cpp b/media/ndk/NdkMediaFormat.cpp
index 66b5dec..161b5e3 100644
--- a/media/ndk/NdkMediaFormat.cpp
+++ b/media/ndk/NdkMediaFormat.cpp
@@ -142,7 +142,7 @@
     }
     ret.append("}");
     mData->mDebug = ret;
-    return mData->mDebug.string();
+    return mData->mDebug.c_str();
 }
 
 EXPORT
@@ -238,7 +238,7 @@
         return false;
     }
     for (size_t i = 0; i < mData->mStringCache.size(); i++) {
-        if (strcmp(mData->mStringCache.keyAt(i).string(), name) == 0) {
+        if (strcmp(mData->mStringCache.keyAt(i).c_str(), name) == 0) {
             mData->mStringCache.removeItemsAt(i, 1);
             break;
         }
@@ -251,7 +251,7 @@
         if (i < 0) {
             return false;
         }
-        *out = mData->mStringCache.valueAt(i).string();
+        *out = mData->mStringCache.valueAt(i).c_str();
         return true;
     }
     return false;
diff --git a/media/utils/ServiceUtilities.cpp b/media/utils/ServiceUtilities.cpp
index 83b84e3..eef460f 100644
--- a/media/utils/ServiceUtilities.cpp
+++ b/media/utils/ServiceUtilities.cpp
@@ -403,7 +403,7 @@
     PermissionController{}.getPackagesForUid(uid, str16PackageNames);
     std::vector<std::string> packageNames;
     for (const auto& str16PackageName : str16PackageNames) {
-        packageNames.emplace_back(String8(str16PackageName).string());
+        packageNames.emplace_back(String8(str16PackageName).c_str());
     }
     if (packageNames.empty()) {
         ALOGW("%s: Playback capture for uid %u is denied as no package name could be retrieved "
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 761270b..8dbe067 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -23,7 +23,6 @@
 
 #include "Configuration.h"
 #include "AudioFlinger.h"
-#include "EffectConfiguration.h"
 
 //#define BUFLOG_NDEBUG 0
 #include <afutils/BufLog.h>
@@ -232,23 +231,6 @@
 }
 
 AudioFlinger::AudioFlinger()
-    : mMediaLogNotifier(new AudioFlinger::MediaLogNotifier()),
-      mPrimaryHardwareDev(NULL),
-      mAudioHwDevs(NULL),
-      mHardwareStatus(AUDIO_HW_IDLE),
-      mMasterVolume(1.0f),
-      mMasterMute(false),
-      // mNextUniqueId(AUDIO_UNIQUE_ID_USE_MAX),
-      mMode(AUDIO_MODE_INVALID),
-      mBtNrecIsOff(false),
-      mIsLowRamDevice(true),
-      mIsDeviceTypeKnown(false),
-      mTotalMemory(0),
-      mClientSharedHeapSize(kMinimumClientSharedHeapSizeBytes),
-      mGlobalEffectEnableTime(0),
-      mPatchCommandThread(sp<PatchCommandThread>::make()),
-      mSystemReady(false),
-      mBluetoothLatencyModesEnabled(true)
 {
     // Move the audio session unique ID generator start base as time passes to limit risk of
     // generating the same ID again after an audioserver restart.
@@ -285,9 +267,6 @@
     // in bad state, reset the state upon service start.
     BatteryNotifier::getInstance().noteResetAudio();
 
-    mDevicesFactoryHal = DevicesFactoryHalInterface::create();
-    mEffectsFactoryHal = audioflinger::EffectConfiguration::getEffectsFactoryHal();
-
     mMediaLogNotifier->run("MediaLogNotifier");
     std::vector<pid_t> halPids;
     mDevicesFactoryHal->getHalPids(&halPids);
@@ -695,7 +674,7 @@
         result.appendFormat("  %7d %4d %7d %6u  %s\n", r->mSessionid, r->mCnt, r->mPid,
                 r->mUid, info.package.c_str());
     }
-    write(fd, result.string(), result.size());
+    write(fd, result.c_str(), result.size());
 }
 
 
@@ -708,7 +687,7 @@
 
     snprintf(buffer, SIZE, "Hardware status: %d\n", hardwareStatus);
     result.append(buffer);
-    write(fd, result.string(), result.size());
+    write(fd, result.c_str(), result.size());
 
     dprintf(fd, "Vibrator infos(size=%zu):\n", mAudioVibratorInfos.size());
     for (const auto& vibratorInfo : mAudioVibratorInfos) {
@@ -728,7 +707,7 @@
             IPCThreadState::self()->getCallingPid(),
             IPCThreadState::self()->getCallingUid());
     result.append(buffer);
-    write(fd, result.string(), result.size());
+    write(fd, result.c_str(), result.size());
 }
 
 status_t AudioFlinger::dump(int fd, const Vector<String16>& args)
@@ -741,7 +720,7 @@
         const bool hardwareLocked = afutils::dumpTryLock(mHardwareLock);
         if (!hardwareLocked) {
             String8 result(kHardwareLockedString);
-            write(fd, result.string(), result.size());
+            write(fd, result.c_str(), result.size());
         } else {
             mHardwareLock.unlock();
         }
@@ -751,20 +730,20 @@
         // failed to lock - AudioFlinger is probably deadlocked
         if (!locked) {
             String8 result(kDeadlockedString);
-            write(fd, result.string(), result.size());
+            write(fd, result.c_str(), result.size());
         }
 
         const bool clientLocked = afutils::dumpTryLock(mClientLock);
         if (!clientLocked) {
             String8 result(kClientLockedString);
-            write(fd, result.string(), result.size());
+            write(fd, result.c_str(), result.size());
         }
 
         if (mEffectsFactoryHal != 0) {
             mEffectsFactoryHal->dumpEffects(fd);
         } else {
             String8 result(kNoEffectsFactory);
-            write(fd, result.string(), result.size());
+            write(fd, result.c_str(), result.size());
         }
 
         dumpClients(fd, args);
@@ -1329,7 +1308,7 @@
         if (mPrimaryHardwareDev == nullptr) {
             return INVALID_OPERATION;
         }
-        sp<DeviceHalInterface> dev = mPrimaryHardwareDev->hwDevice();
+        sp<DeviceHalInterface> dev = mPrimaryHardwareDev.load()->hwDevice();
         mHardwareStatus = AUDIO_HW_SET_MODE;
         ret = dev->setMode(mode);
         mHardwareStatus = AUDIO_HW_IDLE;
@@ -1366,7 +1345,7 @@
     if (mPrimaryHardwareDev == nullptr) {
         return INVALID_OPERATION;
     }
-    sp<DeviceHalInterface> primaryDev = mPrimaryHardwareDev->hwDevice();
+    sp<DeviceHalInterface> primaryDev = mPrimaryHardwareDev.load()->hwDevice();
     if (primaryDev == nullptr) {
         ALOGW("%s: no primary HAL device", __func__);
         return INVALID_OPERATION;
@@ -1394,7 +1373,7 @@
     if (mPrimaryHardwareDev == nullptr) {
         return false;
     }
-    sp<DeviceHalInterface> primaryDev = mPrimaryHardwareDev->hwDevice();
+    sp<DeviceHalInterface> primaryDev = mPrimaryHardwareDev.load()->hwDevice();
     if (primaryDev == nullptr) {
         ALOGW("%s: no primary HAL device", __func__);
         return false;
@@ -1775,7 +1754,7 @@
 status_t AudioFlinger::setParameters(audio_io_handle_t ioHandle, const String8& keyValuePairs)
 {
     ALOGV("setParameters(): io %d, keyvalue %s, calling pid %d calling uid %d",
-            ioHandle, keyValuePairs.string(),
+            ioHandle, keyValuePairs.c_str(),
             IPCThreadState::self()->getCallingPid(), IPCThreadState::self()->getCallingUid());
 
     // check calling permissions
@@ -1786,7 +1765,7 @@
     String8 filteredKeyValuePairs = keyValuePairs;
     filterReservedParameters(filteredKeyValuePairs, IPCThreadState::self()->getCallingUid());
 
-    ALOGV("%s: filtered keyvalue %s", __func__, filteredKeyValuePairs.string());
+    ALOGV("%s: filtered keyvalue %s", __func__, filteredKeyValuePairs.c_str());
 
     // AUDIO_IO_HANDLE_NONE means the parameters are global to the audio hardware interface
     if (ioHandle == AUDIO_IO_HANDLE_NONE) {
@@ -1861,7 +1840,7 @@
 String8 AudioFlinger::getParameters(audio_io_handle_t ioHandle, const String8& keys) const
 {
     ALOGVV("getParameters() io %d, keys %s, calling pid %d",
-            ioHandle, keys.string(), IPCThreadState::self()->getCallingPid());
+            ioHandle, keys.c_str(), IPCThreadState::self()->getCallingPid());
 
     Mutex::Autolock _l(mLock);
 
@@ -1912,7 +1891,7 @@
     }
     mHardwareStatus = AUDIO_HW_GET_INPUT_BUFFER_SIZE;
 
-    sp<DeviceHalInterface> dev = mPrimaryHardwareDev->hwDevice();
+    sp<DeviceHalInterface> dev = mPrimaryHardwareDev.load()->hwDevice();
 
     std::vector<audio_channel_mask_t> channelMasks = {channelMask};
     if (channelMask != AUDIO_CHANNEL_IN_MONO) {
@@ -2003,7 +1982,7 @@
     if (mPrimaryHardwareDev == nullptr) {
         return INVALID_OPERATION;
     }
-    sp<DeviceHalInterface> dev = mPrimaryHardwareDev->hwDevice();
+    sp<DeviceHalInterface> dev = mPrimaryHardwareDev.load()->hwDevice();
     mHardwareStatus = AUDIO_HW_SET_VOICE_VOLUME;
     ret = dev->setVoiceVolume(value);
     mHardwareStatus = AUDIO_HW_IDLE;
@@ -2561,7 +2540,7 @@
     if (strcmp(name, AUDIO_HARDWARE_MODULE_ID_PRIMARY) == 0) {
         mPrimaryHardwareDev = audioDevice;
         mHardwareStatus = AUDIO_HW_SET_MODE;
-        mPrimaryHardwareDev->hwDevice()->setMode(mMode);
+        mPrimaryHardwareDev.load()->hwDevice()->setMode(mMode);
         mHardwareStatus = AUDIO_HW_IDLE;
     }
 
@@ -2695,7 +2674,7 @@
         if (mPrimaryHardwareDev == nullptr) {
             return AUDIO_HW_SYNC_INVALID;
         }
-        dev = mPrimaryHardwareDev->hwDevice();
+        dev = mPrimaryHardwareDev.load()->hwDevice();
     }
     if (dev == nullptr) {
         return AUDIO_HW_SYNC_INVALID;
@@ -2858,7 +2837,7 @@
             deviceType,
             flags,
             halConfig,
-            address.string());
+            address.c_str());
 
     mHardwareStatus = AUDIO_HW_IDLE;
 
@@ -2967,7 +2946,7 @@
                 mPrimaryHardwareDev = playbackThread->getOutput()->audioHwDev;
 
                 mHardwareStatus = AUDIO_HW_SET_MODE;
-                mPrimaryHardwareDev->hwDevice()->setMode(mMode);
+                mPrimaryHardwareDev.load()->hwDevice()->setMode(mMode);
                 mHardwareStatus = AUDIO_HW_IDLE;
             }
         } else {
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 9aefb6b..6516756 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -20,6 +20,7 @@
 // Classes and interfaces directly used.
 #include "Client.h"
 #include "DeviceEffectManager.h"
+#include "EffectConfiguration.h"
 #include "IAfEffect.h"
 #include "IAfPatchPanel.h"
 #include "IAfThread.h"
@@ -459,7 +460,7 @@
         static const int kPostTriggerSleepPeriod = 1000000;
     };
 
-    const sp<MediaLogNotifier> mMediaLogNotifier;
+    const sp<MediaLogNotifier> mMediaLogNotifier = sp<MediaLogNotifier>::make();
 
     // Find io handle by session id.
     // Preference is given to an io handle with a matching effect chain to session id.
@@ -571,13 +572,12 @@
                 // NOTE: If both mLock and mHardwareLock mutexes must be held,
                 // always take mLock before mHardwareLock
 
-                // guarded by mHardwareLock
-                AudioHwDevice* mPrimaryHardwareDev;
-                DefaultKeyedVector<audio_module_handle_t, AudioHwDevice*>  mAudioHwDevs;
+    std::atomic<AudioHwDevice*> mPrimaryHardwareDev = nullptr;
+    DefaultKeyedVector<audio_module_handle_t, AudioHwDevice*> mAudioHwDevs{nullptr /* defValue */};
 
-                // These two fields are immutable after onFirstRef(), so no lock needed to access
-                sp<DevicesFactoryHalInterface> mDevicesFactoryHal;
-                sp<DevicesFactoryHalCallback> mDevicesFactoryHalCallback;
+     const sp<DevicesFactoryHalInterface> mDevicesFactoryHal =
+             DevicesFactoryHalInterface::create();
+     /* const */ sp<DevicesFactoryHalCallback> mDevicesFactoryHalCallback;  // set onFirstRef().
 
     // for dump, indicates which hardware operation is currently in progress (but not stream ops)
     enum hardware_call_state {
@@ -607,16 +607,15 @@
         AUDIO_HW_SET_SIMULATE_CONNECTIONS, // setSimulateDeviceConnections
     };
 
-    mutable     hardware_call_state                 mHardwareStatus;    // for dump only
-
+    mutable hardware_call_state mHardwareStatus = AUDIO_HW_IDLE;  // for dump only
 
     DefaultKeyedVector<audio_io_handle_t, sp<IAfPlaybackThread>> mPlaybackThreads;
                 stream_type_t                       mStreamTypes[AUDIO_STREAM_CNT];
 
                 // member variables below are protected by mLock
-                float                               mMasterVolume;
-                bool                                mMasterMute;
-                float                               mMasterBalance = 0.f;
+    float mMasterVolume = 1.f;
+    bool mMasterMute = false;
+    float mMasterBalance = 0.f;
                 // end of variables protected by mLock
 
     DefaultKeyedVector<audio_io_handle_t, sp<IAfRecordThread>> mRecordThreads;
@@ -625,10 +624,10 @@
                 DefaultKeyedVector< pid_t, sp<NotificationClient> >    mNotificationClients;
 
                 // updated by atomic_fetch_add_explicit
-                volatile atomic_uint_fast32_t       mNextUniqueIds[AUDIO_UNIQUE_ID_USE_MAX];
+    volatile atomic_uint_fast32_t mNextUniqueIds[AUDIO_UNIQUE_ID_USE_MAX];  // ctor init
 
-                audio_mode_t                        mMode;
-                std::atomic_bool                    mBtNrecIsOff;
+    std::atomic<audio_mode_t> mMode = AUDIO_MODE_INVALID;
+    std::atomic<bool> mBtNrecIsOff = false;
 
                 // protected by mLock
                 Vector<AudioSessionRef*> mAudioSessionRefs;
@@ -667,24 +666,25 @@
     // though the variables are updated with mLock.
     size_t getClientSharedHeapSize() const;
 
-    std::atomic<bool> mIsLowRamDevice;
-    bool    mIsDeviceTypeKnown;
-    int64_t mTotalMemory;
-    std::atomic<size_t> mClientSharedHeapSize;
+    std::atomic<bool> mIsLowRamDevice = true;
+    bool mIsDeviceTypeKnown = false;
+    int64_t mTotalMemory = 0;
+    std::atomic<size_t> mClientSharedHeapSize = kMinimumClientSharedHeapSizeBytes;
     static constexpr size_t kMinimumClientSharedHeapSizeBytes = 1024 * 1024; // 1MB
 
-    nsecs_t mGlobalEffectEnableTime;  // when a global effect was last enabled
+    nsecs_t mGlobalEffectEnableTime = 0;  // when a global effect was last enabled
 
     /* const */ sp<IAfPatchPanel> mPatchPanel;
 
-    sp<EffectsFactoryHalInterface> mEffectsFactoryHal;
+    const sp<EffectsFactoryHalInterface> mEffectsFactoryHal =
+            audioflinger::EffectConfiguration::getEffectsFactoryHal();
 
-    const sp<PatchCommandThread> mPatchCommandThread;
+    const sp<PatchCommandThread> mPatchCommandThread = sp<PatchCommandThread>::make();
     /* const */ sp<DeviceEffectManager> mDeviceEffectManager;  // set onFirstRef
     /* const */ sp<MelReporter> mMelReporter;  // set onFirstRef
 
-    bool       mSystemReady;
-    std::atomic_bool mAudioPolicyReady{};
+    bool mSystemReady = false;
+    std::atomic<bool> mAudioPolicyReady = false;
 
     mediautils::UidInfo mUidInfo;
 
@@ -705,7 +705,7 @@
     mediautils::atomic_sp<IAudioManager>       mAudioManager;
 
     // Bluetooth Variable latency control logic is enabled or disabled
-    std::atomic_bool mBluetoothLatencyModesEnabled;
+    std::atomic<bool> mBluetoothLatencyModesEnabled = true;
 };
 
 // ----------------------------------------------------------------------------
diff --git a/services/audioflinger/DeviceEffectManager.cpp b/services/audioflinger/DeviceEffectManager.cpp
index 681ec5f..588616d 100644
--- a/services/audioflinger/DeviceEffectManager.cpp
+++ b/services/audioflinger/DeviceEffectManager.cpp
@@ -206,17 +206,17 @@
     const bool locked = afutils::dumpTryLock(mLock);
     if (!locked) {
         String8 result("DeviceEffectManager may be deadlocked\n");
-        write(fd, result.string(), result.size());
+        write(fd, result.c_str(), result.size());
     }
 
     String8 heading("\nDevice Effects:\n");
-    write(fd, heading.string(), heading.size());
+    write(fd, heading.c_str(), heading.size());
     for (const auto& iter : mDeviceEffects) {
         String8 outStr;
         outStr.appendFormat("%*sEffect for device %s address %s:\n", 2, "",
                 ::android::toString(iter.first.mType).c_str(), iter.first.getAddress());
         for (const auto& effect : iter.second) {
-            write(fd, outStr.string(), outStr.size());
+            write(fd, outStr.c_str(), outStr.size());
             effect->dump2(fd, 4);
         }
     }
diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp
index c3e1fba..22733a6 100644
--- a/services/audioflinger/Effects.cpp
+++ b/services/audioflinger/Effects.cpp
@@ -530,7 +530,7 @@
     result.appendFormat("\t\t- apiVersion: %08X\n\t\t- flags: %08X (%s)\n",
             mDescriptor.apiVersion,
             mDescriptor.flags,
-            effectFlagsToString(mDescriptor.flags).string());
+            effectFlagsToString(mDescriptor.flags).c_str());
     result.appendFormat("\t\t- name: %s\n",
             mDescriptor.name);
 
@@ -551,7 +551,7 @@
         mLock.unlock();
     }
 
-    write(fd, result.string(), result.length());
+    write(fd, result.c_str(), result.length());
 }
 
 // ----------------------------------------------------------------------------
@@ -997,13 +997,6 @@
                     &size,
                     &cmdStatus);
         }
-
-        if (isVolumeControl()) {
-            // Force initializing the volume as 0 for volume control effect for safer ramping
-            uint32_t left = 0;
-            uint32_t right = 0;
-            setVolumeInternal(&left, &right, true /*controller*/);
-        }
     }
 
     // mConfig.outputCfg.buffer.frameCount cannot be zero.
@@ -1660,7 +1653,7 @@
             dumpInOutBuffer(false /* isInput */, mOutBuffer).c_str(),
             dumpInOutBuffer(false /* isInput */, mOutConversionBuffer).c_str());
 
-    write(fd, result.string(), result.length());
+    write(fd, result.c_str(), result.length());
 
     if (mEffectInterface != 0) {
         dprintf(fd, "\tEffect ID %d HAL dump:\n", mId);
@@ -2129,7 +2122,7 @@
 EffectChain::EffectChain(const sp<IAfThreadBase>& thread,
                                        audio_session_t sessionId)
     : mSessionId(sessionId), mActiveTrackCnt(0), mTrackCnt(0), mTailBufferCount(0),
-      mVolumeCtrlIdx(-1), mLeftVolume(UINT_MAX), mRightVolume(UINT_MAX),
+      mLeftVolume(UINT_MAX), mRightVolume(UINT_MAX),
       mNewLeftVolume(UINT_MAX), mNewRightVolume(UINT_MAX),
       mEffectCallback(new EffectCallback(wp<EffectChain>(this), thread))
 {
@@ -2367,6 +2360,15 @@
     return NO_ERROR;
 }
 
+std::optional<size_t> EffectChain::findVolumeControl_l(size_t from, size_t to) const {
+    for (size_t i = std::min(to, mEffects.size()); i > from; i--) {
+        if (mEffects[i - 1]->isVolumeControlEnabled()) {
+            return i - 1;
+        }
+    }
+    return std::nullopt;
+}
+
 ssize_t EffectChain::getInsertIndex(const effect_descriptor_t& desc) {
     // Insert effects are inserted at the end of mEffects vector as they are processed
     //  after track and auxiliary effects.
@@ -2536,29 +2538,38 @@
 {
     uint32_t newLeft = *left;
     uint32_t newRight = *right;
-    bool hasControl = false;
-    int ctrlIdx = -1;
-    size_t size = mEffects.size();
+    const size_t size = mEffects.size();
 
     // first update volume controller
-    for (size_t i = size; i > 0; i--) {
-        if (mEffects[i - 1]->isVolumeControlEnabled()) {
-            ctrlIdx = i - 1;
-            hasControl = true;
-            break;
-        }
-    }
+    const auto volumeControlIndex = findVolumeControl_l(0, size);
+    const int ctrlIdx = volumeControlIndex.value_or(-1);
+    const sp<IAfEffectModule> volumeControlEffect =
+            volumeControlIndex.has_value() ? mEffects[ctrlIdx] : nullptr;
+    const sp<IAfEffectModule> cachedVolumeControlEffect = mVolumeControlEffect.promote();
 
-    if (!force && ctrlIdx == mVolumeCtrlIdx &&
+    if (!force && volumeControlEffect == cachedVolumeControlEffect &&
             *left == mLeftVolume && *right == mRightVolume) {
-        if (hasControl) {
+        if (volumeControlIndex.has_value()) {
             *left = mNewLeftVolume;
             *right = mNewRightVolume;
         }
-        return hasControl;
+        return volumeControlIndex.has_value();
     }
 
-    mVolumeCtrlIdx = ctrlIdx;
+    if (volumeControlEffect != cachedVolumeControlEffect) {
+        // The volume control effect is a new one. Set the old one as full volume. Set the new onw
+        // as zero for safe ramping.
+        if (cachedVolumeControlEffect != nullptr) {
+            uint32_t leftMax = 1 << 24;
+            uint32_t rightMax = 1 << 24;
+            cachedVolumeControlEffect->setVolume(&leftMax, &rightMax, true /*controller*/);
+        }
+        if (volumeControlEffect != nullptr) {
+            uint32_t leftZero = 0;
+            uint32_t rightZero = 0;
+            volumeControlEffect->setVolume(&leftZero, &rightZero, true /*controller*/);
+        }
+    }
     mLeftVolume = newLeft;
     mRightVolume = newRight;
 
@@ -2595,7 +2606,7 @@
 
     setVolumeForOutput_l(*left, *right);
 
-    return hasControl;
+    return volumeControlIndex.has_value();
 }
 
 // resetVolume_l() must be called with IAfThreadBase::mutex() or EffectChain::mLock held
@@ -2661,7 +2672,7 @@
                 (int)outBufferStr.size(), "Out buffer      ");
         result.appendFormat("\t%s   %s   %d\n",
                 inBufferStr.c_str(), outBufferStr.c_str(), mActiveTrackCnt);
-        write(fd, result.string(), result.size());
+        write(fd, result.c_str(), result.size());
 
         for (size_t i = 0; i < numEffects; ++i) {
             sp<IAfEffectModule> effect = mEffects[i];
@@ -2674,7 +2685,7 @@
             mLock.unlock();
         }
     } else {
-        write(fd, result.string(), result.size());
+        write(fd, result.c_str(), result.size());
     }
 }
 
@@ -3527,7 +3538,7 @@
     const bool locked = afutils::dumpTryLock(mProxyLock);
     if (!locked) {
         String8 result("DeviceEffectProxy may be deadlocked\n");
-        write(fd, result.string(), result.size());
+        write(fd, result.c_str(), result.size());
     }
 
     String8 outStr;
@@ -3536,16 +3547,16 @@
     } else {
         outStr.appendFormat("%*sNO HAL Effect\n", spaces, "");
     }
-    write(fd, outStr.string(), outStr.size());
+    write(fd, outStr.c_str(), outStr.size());
     outStr.clear();
 
     outStr.appendFormat("%*sSub Effects:\n", spaces, "");
-    write(fd, outStr.string(), outStr.size());
+    write(fd, outStr.c_str(), outStr.size());
     outStr.clear();
 
     for (const auto& iter : mEffectHandles) {
         outStr.appendFormat("%*sEffect for patch handle %d:\n", spaces + 2, "", iter.first);
-        write(fd, outStr.string(), outStr.size());
+        write(fd, outStr.c_str(), outStr.size());
         outStr.clear();
         sp<IAfEffectBase> effect = iter.second->effect().promote();
         if (effect != nullptr) {
diff --git a/services/audioflinger/Effects.h b/services/audioflinger/Effects.h
index 79b4e63..aa5935a 100644
--- a/services/audioflinger/Effects.h
+++ b/services/audioflinger/Effects.h
@@ -622,6 +622,8 @@
 
     ssize_t getInsertIndex(const effect_descriptor_t& desc);
 
+    std::optional<size_t> findVolumeControl_l(size_t from, size_t to) const;
+
     mutable  Mutex mLock;        // mutex protecting effect list
              Vector<sp<IAfEffectModule>> mEffects; // list of effect modules
              audio_session_t mSessionId; // audio session ID
@@ -634,7 +636,6 @@
 
              int32_t mTailBufferCount;   // current effect tail buffer count
              int32_t mMaxTailBuffers;    // maximum effect tail buffers
-             int mVolumeCtrlIdx;         // index of insert effect having control over volume
              uint32_t mLeftVolume;       // previous volume on left channel
              uint32_t mRightVolume;      // previous volume on right channel
              uint32_t mNewLeftVolume;       // new volume on left channel
@@ -647,6 +648,8 @@
              KeyedVector< int, sp<SuspendedEffectDesc> > mSuspendedEffects;
 
              const sp<EffectCallback> mEffectCallback;
+
+             wp<IAfEffectModule> mVolumeControlEffect;
 };
 
 class DeviceEffectProxy : public IAfDeviceEffectProxy, public EffectBase {
diff --git a/services/audioflinger/MelReporter.cpp b/services/audioflinger/MelReporter.cpp
index 0ebb3eb..5dc2e8a 100644
--- a/services/audioflinger/MelReporter.cpp
+++ b/services/audioflinger/MelReporter.cpp
@@ -38,24 +38,21 @@
 
     ndk::SpAIBinder soundDoseBinder;
     if (device->getSoundDoseInterface(module, &soundDoseBinder) != OK) {
-        ALOGW("%s: HAL cannot provide sound dose interface for module %s, use internal MEL",
+        ALOGW("%s: HAL cannot provide sound dose interface for module %s",
               __func__, module.c_str());
-        activateInternalSoundDoseComputation();
         return false;
     }
 
     if (soundDoseBinder == nullptr) {
-         ALOGW("%s: HAL doesn't implement a sound dose interface for module %s, use internal MEL",
+         ALOGW("%s: HAL doesn't implement a sound dose interface for module %s",
               __func__, module.c_str());
-        activateInternalSoundDoseComputation();
         return false;
     }
 
     std::shared_ptr<ISoundDose> soundDoseInterface = ISoundDose::fromBinder(soundDoseBinder);
 
-    if (!mSoundDoseManager->setHalSoundDoseInterface(soundDoseInterface)) {
+    if (!mSoundDoseManager->setHalSoundDoseInterface(module, soundDoseInterface)) {
         ALOGW("%s: cannot activate HAL MEL reporting for module %s", __func__, module.c_str());
-        activateInternalSoundDoseComputation();
         return false;
     }
 
@@ -73,7 +70,8 @@
         mUseHalSoundDoseInterface = false;
     }
 
-    mSoundDoseManager->setHalSoundDoseInterface(nullptr);
+    // reset the HAL interfaces and use internal MELs
+    mSoundDoseManager->resetHalSoundDoseInterfaces();
 }
 
 void MelReporter::onFirstRef() {
@@ -257,6 +255,9 @@
 void MelReporter::stopInternalMelComputation() {
     ALOGV("%s", __func__);
     std::lock_guard _l(mLock);
+    if (mUseHalSoundDoseInterface) {
+        return;
+    }
     mActiveMelPatches.clear();
     mUseHalSoundDoseInterface = true;
 }
diff --git a/services/audioflinger/PatchPanel.cpp b/services/audioflinger/PatchPanel.cpp
index f11a530..554272a 100644
--- a/services/audioflinger/PatchPanel.cpp
+++ b/services/audioflinger/PatchPanel.cpp
@@ -915,7 +915,7 @@
             patchPanelDump += "\nPatches:\n";
             headerPrinted = true;
         }
-        patchPanelDump.appendFormat("%s%s\n", indent, iter.second.dump(iter.first).string());
+        patchPanelDump.appendFormat("%s%s\n", indent, iter.second.dump(iter.first).c_str());
     }
 
     headerPrinted = false;
@@ -933,12 +933,12 @@
             for (const auto& patch : module.second.sw_patches) {
                 moduleDump.appendFormat("%d ", patch);
             }
-            patchPanelDump.appendFormat("%s%s\n", indent, moduleDump.string());
+            patchPanelDump.appendFormat("%s%s\n", indent, moduleDump.c_str());
         }
     }
 
-    if (!patchPanelDump.isEmpty()) {
-        write(fd, patchPanelDump.string(), patchPanelDump.size());
+    if (!patchPanelDump.empty()) {
+        write(fd, patchPanelDump.c_str(), patchPanelDump.size());
     }
 }
 
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/Threads.cpp b/services/audioflinger/Threads.cpp
index a36494c..157764f 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -570,7 +570,7 @@
                 "  us per mix loop: mean=%.0f stddev=%.0f min=%.0f max=%.0f\n"
                 "  %% of wall: mean=%.1f stddev=%.1f min=%.1f max=%.1f\n"
                 "  MHz: mean=%.1f, stddev=%.1f, min=%.1f max=%.1f",
-                    title.string(),
+                    title.c_str(),
                     elapsed * .000000001, n, perLoop * .000001,
                     mean * .001,
                     stddev * .001,
@@ -696,7 +696,7 @@
 
 status_t ThreadBase::setParameters(const String8& keyValuePairs)
 {
-    ALOGV("ThreadBase::setParameters() %s", keyValuePairs.string());
+    ALOGV("ThreadBase::setParameters() %s", keyValuePairs.c_str());
     Mutex::Autolock _l(mLock);
 
     return sendSetParameterConfigEvent_l(keyValuePairs);
@@ -881,7 +881,7 @@
             if (checkForNewParameter_l(data->mKeyValuePairs, event->mStatus)) {
                 configChanged = true;
                 mLocalLog.log("CFG_EVENT_SET_PARAMETER: (%s) configuration changed",
-                        data->mKeyValuePairs.string());
+                        data->mKeyValuePairs.c_str());
             }
         } break;
         case CFG_EVENT_CREATE_AUDIO_PATCH: {
@@ -1069,7 +1069,7 @@
     dprintf(fd, "  HAL buffer size: %zu bytes\n", mBufferSize);
     dprintf(fd, "  Channel count: %u\n", mChannelCount);
     dprintf(fd, "  Channel mask: 0x%08x (%s)\n", mChannelMask,
-            channelMaskToString(mChannelMask, mType != RECORD).string());
+            channelMaskToString(mChannelMask, mType != RECORD).c_str());
     dprintf(fd, "  Processing format: 0x%x (%s)\n", mFormat,
             IAfThreadBase::formatToString(mFormat).c_str());
     dprintf(fd, "  Processing frame size: %zu bytes\n", mFrameSize);
@@ -2005,7 +2005,7 @@
     if (mLocalLog != nullptr) {
         String8 result;
         track->appendDump(result, false /* active */);
-        mLocalLog->log("AT::%-10s(%p) %s", funcName, track.get(), result.string());
+        mLocalLog->log("AT::%-10s(%p) %s", funcName, track.get(), result.c_str());
     }
 }
 
@@ -2272,7 +2272,7 @@
         }
     }
     result.append("\n");
-    write(fd, result.string(), result.length());
+    write(fd, result.c_str(), result.length());
     result.clear();
 
     // These values are "raw"; they will wrap around.  See prepareTracks_l() for a better way.
@@ -2318,7 +2318,7 @@
         }
     }
 
-    write(fd, result.string(), result.size());
+    write(fd, result.c_str(), result.size());
 }
 
 void PlaybackThread::dumpInternals_l(int fd, const Vector<String16>& args)
@@ -2966,7 +2966,7 @@
 
     String8 result;
     track->appendDump(result, false /* active */);
-    mLocalLog.log("removeTrack_l (%p) %s", track.get(), result.string());
+    mLocalLog.log("removeTrack_l (%p) %s", track.get(), result.c_str());
 
     mTracks.remove(track);
     {
@@ -4075,9 +4075,9 @@
 
                     releaseWakeLock_l();
                     // wait until we have something to do...
-                    ALOGV("%s going to sleep", myName.string());
+                    ALOGV("%s going to sleep", myName.c_str());
                     mWaitWorkCV.wait(mLock);
-                    ALOGV("%s waking up", myName.string());
+                    ALOGV("%s waking up", myName.c_str());
                     acquireWakeLock_l();
 
                     mMixerStatus = MIXER_IDLE;
@@ -9178,7 +9178,7 @@
 {
     String8 result;
     track->appendDump(result, false /* active */);
-    mLocalLog.log("removeTrack_l (%p) %s", track.get(), result.string());
+    mLocalLog.log("removeTrack_l (%p) %s", track.get(), result.c_str());
 
     mTracks.remove(track);
     // need anything related to effects here?
@@ -9257,7 +9257,7 @@
         }
 
     }
-    write(fd, result.string(), result.size());
+    write(fd, result.c_str(), result.size());
 }
 
 void RecordThread::setRecordSilenced(audio_port_handle_t portId, bool silenced)
@@ -10345,9 +10345,9 @@
                 }
 
                 // wait until we have something to do...
-                ALOGV("%s going to sleep", myName.string());
+                ALOGV("%s going to sleep", myName.c_str());
                 mWaitWorkCV.wait(mLock);
-                ALOGV("%s waking up", myName.string());
+                ALOGV("%s waking up", myName.c_str());
 
                 checkSilentMode_l();
 
@@ -10721,7 +10721,7 @@
     } else {
         dprintf(fd, "\n");
     }
-    write(fd, result.string(), result.size());
+    write(fd, result.c_str(), result.size());
 }
 
 /* static */
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index 79f75ca..18b6840 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -170,7 +170,7 @@
             mKeyValuePairs(keyValuePairs) {}
 
         virtual  void dump(char *buffer, size_t size) {
-            snprintf(buffer, size, "- KeyValue: %s\n", mKeyValuePairs.string());
+            snprintf(buffer, size, "- KeyValue: %s\n", mKeyValuePairs.c_str());
         }
 
         const String8 mKeyValuePairs;
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/audioflinger/sounddose/SoundDoseManager.cpp b/services/audioflinger/sounddose/SoundDoseManager.cpp
index 7accaf0..39c80d8 100644
--- a/services/audioflinger/sounddose/SoundDoseManager.cpp
+++ b/services/audioflinger/sounddose/SoundDoseManager.cpp
@@ -49,7 +49,7 @@
         size_t channelCount, audio_format_t format) {
     const std::lock_guard _l(mLock);
 
-    if (mHalSoundDose != nullptr && mEnabledCsd) {
+    if (mHalSoundDose.size() > 0 && mEnabledCsd) {
         ALOGD("%s: using HAL MEL computation, no MelProcessor needed.", __func__);
         return nullptr;
     }
@@ -82,20 +82,27 @@
     return melProcessor;
 }
 
-bool SoundDoseManager::setHalSoundDoseInterface(const std::shared_ptr<ISoundDose>& halSoundDose) {
+bool SoundDoseManager::setHalSoundDoseInterface(const std::string &module,
+                                                const std::shared_ptr<ISoundDose> &halSoundDose) {
     ALOGV("%s", __func__);
 
+    if (halSoundDose == nullptr) {
+        ALOGI("%s: passed ISoundDose object is null", __func__);
+        return false;
+    }
+
     std::shared_ptr<HalSoundDoseCallback> halSoundDoseCallback;
     {
         const std::lock_guard _l(mLock);
 
-        mHalSoundDose = halSoundDose;
-        if (halSoundDose == nullptr) {
-            ALOGI("%s: passed ISoundDose object is null, switching to internal CSD", __func__);
+        if (mHalSoundDose.find(module) != mHalSoundDose.end()) {
+            ALOGW("%s: Module %s already has a sound dose HAL assigned, skipping", __func__,
+                  module.c_str());
             return false;
         }
+        mHalSoundDose[module] = halSoundDose;
 
-        if (!mHalSoundDose->setOutputRs2UpperBound(mRs2UpperBound).isOk()) {
+        if (!halSoundDose->setOutputRs2UpperBound(mRs2UpperBound).isOk()) {
             ALOGW("%s: Cannot set RS2 value for momentary exposure %f",
                   __func__,
                   mRs2UpperBound);
@@ -121,16 +128,26 @@
     return true;
 }
 
+void SoundDoseManager::resetHalSoundDoseInterfaces() {
+    ALOGV("%s", __func__);
+
+    const std::lock_guard _l(mLock);
+    mHalSoundDose.clear();
+}
+
 void SoundDoseManager::setOutputRs2UpperBound(float rs2Value) {
     ALOGV("%s", __func__);
     const std::lock_guard _l(mLock);
 
-    if (mHalSoundDose != nullptr) {
-        // using the HAL sound dose interface
-        if (!mHalSoundDose->setOutputRs2UpperBound(rs2Value).isOk()) {
-            ALOGE("%s: Cannot set RS2 value for momentary exposure %f", __func__, rs2Value);
-            return;
+    if (mHalSoundDose.size() > 0) {
+        for (auto& halSoundDose : mHalSoundDose) {
+            // using the HAL sound dose interface
+            if (!halSoundDose.second->setOutputRs2UpperBound(rs2Value).isOk()) {
+                ALOGE("%s: Cannot set RS2 value for momentary exposure %f", __func__, rs2Value);
+                continue;
+            }
         }
+
         mRs2UpperBound = rs2Value;
         return;
     }
@@ -202,14 +219,16 @@
 
 ndk::ScopedAStatus SoundDoseManager::HalSoundDoseCallback::onMomentaryExposureWarning(
         float in_currentDbA, const AudioDevice& in_audioDevice) {
-    auto soundDoseManager = mSoundDoseManager.promote();
-    if (soundDoseManager == nullptr) {
-        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+    sp<SoundDoseManager> soundDoseManager;
+    {
+        const std::lock_guard _l(mCbLock);
+        soundDoseManager = mSoundDoseManager.promote();
+        if (soundDoseManager == nullptr) {
+            return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+        }
     }
 
-    std::shared_ptr<ISoundDose> halSoundDose;
-    soundDoseManager->getHalSoundDose(&halSoundDose);
-    if(halSoundDose == nullptr) {
+    if (!soundDoseManager->useHalSoundDose()) {
         ALOGW("%s: HAL sound dose interface deactivated. Ignoring", __func__);
         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
     }
@@ -229,14 +248,16 @@
 ndk::ScopedAStatus SoundDoseManager::HalSoundDoseCallback::onNewMelValues(
         const ISoundDose::IHalSoundDoseCallback::MelRecord& in_melRecord,
         const AudioDevice& in_audioDevice) {
-    auto soundDoseManager = mSoundDoseManager.promote();
-    if (soundDoseManager == nullptr) {
-        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+    sp<SoundDoseManager> soundDoseManager;
+    {
+        const std::lock_guard _l(mCbLock);
+        soundDoseManager = mSoundDoseManager.promote();
+        if (soundDoseManager == nullptr) {
+            return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+        }
     }
 
-    std::shared_ptr<ISoundDose> halSoundDose;
-    soundDoseManager->getHalSoundDose(&halSoundDose);
-    if(halSoundDose == nullptr) {
+    if (!soundDoseManager->useHalSoundDose()) {
         ALOGW("%s: HAL sound dose interface deactivated. Ignoring", __func__);
         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
     }
@@ -509,7 +530,7 @@
 
 void SoundDoseManager::setUseFrameworkMel(bool useFrameworkMel) {
     // invalidate any HAL sound dose interface used
-    setHalSoundDoseInterface(nullptr);
+    resetHalSoundDoseInterfaces();
 
     const std::lock_guard _l(mLock);
     mUseFrameworkMel = useFrameworkMel;
@@ -536,14 +557,12 @@
         if (!mEnabledCsd) return false;
     }
 
-    std::shared_ptr<ISoundDose> halSoundDose;
-    getHalSoundDose(&halSoundDose);
-    return halSoundDose != nullptr;
+    return useHalSoundDose();
 }
 
-void SoundDoseManager::getHalSoundDose(std::shared_ptr<ISoundDose>* halSoundDose) const {
+bool SoundDoseManager::useHalSoundDose() const {
     const std::lock_guard _l(mLock);
-    *halSoundDose = mHalSoundDose;
+    return mHalSoundDose.size() > 0;
 }
 
 void SoundDoseManager::resetSoundDose() {
diff --git a/services/audioflinger/sounddose/SoundDoseManager.h b/services/audioflinger/sounddose/SoundDoseManager.h
index 888561f..6e0bc34 100644
--- a/services/audioflinger/sounddose/SoundDoseManager.h
+++ b/services/audioflinger/sounddose/SoundDoseManager.h
@@ -94,12 +94,15 @@
     sp<media::ISoundDose> getSoundDoseInterface(const sp<media::ISoundDoseCallback>& callback);
 
     /**
-     * Sets the HAL sound dose interface to use for the MEL computation. Use nullptr
-     * for using the internal MEL computation.
+     * Sets the HAL sound dose interface for a specific module to use for the MEL computation.
      *
      * @return true if setting the HAL sound dose value was successful, false otherwise.
      */
-    bool setHalSoundDoseInterface(const std::shared_ptr<ISoundDose>& halSoundDose);
+    bool setHalSoundDoseInterface(const std::string &module,
+                                  const std::shared_ptr<ISoundDose> &halSoundDose);
+
+    /** Reset all the stored HAL sound dose interface. */
+    void resetHalSoundDoseInterfaces();
 
     /** Returns the cached audio port id from the active devices. */
     audio_port_handle_t getIdForAudioDevice(
@@ -193,6 +196,7 @@
                 const aidl::android::media::audio::common::AudioDevice& in_audioDevice) override;
 
         wp<SoundDoseManager> mSoundDoseManager;
+        std::mutex mCbLock;
     };
 
     void resetSoundDose();
@@ -206,8 +210,11 @@
     void setUseFrameworkMel(bool useFrameworkMel);
     void setComputeCsdOnAllDevices(bool computeCsdOnAllDevices);
     bool isSoundDoseHalSupported() const;
-    /** Returns the HAL sound dose interface or null if internal MEL computation is used. */
-    void getHalSoundDose(std::shared_ptr<ISoundDose>* halSoundDose) const;
+    /**
+     * Returns true if there is one active HAL sound dose interface or null if internal MEL
+     * computation is used.
+     **/
+    bool useHalSoundDose() const;
 
     mutable std::mutex mLock;
 
@@ -241,10 +248,10 @@
 
     sp<SoundDose> mSoundDose GUARDED_BY(mLock);
 
-    std::shared_ptr<ISoundDose> mHalSoundDose GUARDED_BY(mLock);
+    std::unordered_map<std::string, std::shared_ptr<ISoundDose>> mHalSoundDose GUARDED_BY(mLock);
     std::shared_ptr<HalSoundDoseCallback> mHalSoundDoseCallback GUARDED_BY(mLock);
 
-    bool mUseFrameworkMel GUARDED_BY(mLock) = true;
+    bool mUseFrameworkMel GUARDED_BY(mLock) = false;
     bool mComputeCsdOnAllDevices GUARDED_BY(mLock) = false;
 
     bool mEnabledCsd GUARDED_BY(mLock) = true;
diff --git a/services/audioflinger/sounddose/tests/sounddosemanager_tests.cpp b/services/audioflinger/sounddose/tests/sounddosemanager_tests.cpp
index 7d0b3a7..5f6dcb9 100644
--- a/services/audioflinger/sounddose/tests/sounddosemanager_tests.cpp
+++ b/services/audioflinger/sounddose/tests/sounddosemanager_tests.cpp
@@ -45,6 +45,8 @@
     MOCK_METHOD(void, stopMelComputationForDeviceId, (audio_port_handle_t), (override));
 };
 
+constexpr char kPrimaryModule[] = "primary";
+constexpr char kSecondaryModule[] = "secondary";
 
 class SoundDoseManagerTest : public ::testing::Test {
 protected:
@@ -52,17 +54,24 @@
         mMelReporterCallback = sp<MelReporterCallback>::make();
         mSoundDoseManager = sp<SoundDoseManager>::make(mMelReporterCallback);
         mHalSoundDose = ndk::SharedRefBase::make<HalSoundDoseMock>();
+        mSecondaryHalSoundDose = ndk::SharedRefBase::make<HalSoundDoseMock>();
 
         ON_CALL(*mHalSoundDose.get(), setOutputRs2UpperBound)
             .WillByDefault([] (float rs2) {
                 EXPECT_EQ(rs2, ISoundDose::DEFAULT_MAX_RS2);
                 return ndk::ScopedAStatus::ok();
             });
+        ON_CALL(*mSecondaryHalSoundDose.get(), setOutputRs2UpperBound)
+                .WillByDefault([] (float rs2) {
+                    EXPECT_EQ(rs2, ISoundDose::DEFAULT_MAX_RS2);
+                    return ndk::ScopedAStatus::ok();
+                });
     }
 
     sp<MelReporterCallback> mMelReporterCallback;
     sp<SoundDoseManager> mSoundDoseManager;
     std::shared_ptr<HalSoundDoseMock> mHalSoundDose;
+    std::shared_ptr<HalSoundDoseMock> mSecondaryHalSoundDose;
 };
 
 TEST_F(SoundDoseManagerTest, GetProcessorForExistingStream) {
@@ -110,7 +119,7 @@
 }
 
 TEST_F(SoundDoseManagerTest, InvalidHalInterfaceIsNotSet) {
-    EXPECT_FALSE(mSoundDoseManager->setHalSoundDoseInterface(nullptr));
+    EXPECT_FALSE(mSoundDoseManager->setHalSoundDoseInterface(kPrimaryModule, nullptr));
 }
 
 TEST_F(SoundDoseManagerTest, SetHalSoundDoseDisablesNewMelProcessorCallbacks) {
@@ -122,7 +131,7 @@
             return ndk::ScopedAStatus::ok();
         });
 
-    EXPECT_TRUE(mSoundDoseManager->setHalSoundDoseInterface(mHalSoundDose));
+    EXPECT_TRUE(mSoundDoseManager->setHalSoundDoseInterface(kPrimaryModule, mHalSoundDose));
 
     EXPECT_EQ(nullptr, mSoundDoseManager->getOrCreateProcessorForDevice(/*deviceId=*/2,
             /*streamHandle=*/1,
@@ -139,8 +148,17 @@
             EXPECT_NE(nullptr, callback);
             return ndk::ScopedAStatus::ok();
         });
+    EXPECT_CALL(*mSecondaryHalSoundDose.get(), setOutputRs2UpperBound).Times(1);
+    EXPECT_CALL(*mSecondaryHalSoundDose.get(), registerSoundDoseCallback)
+            .Times(1)
+            .WillOnce([&] (const std::shared_ptr<ISoundDose::IHalSoundDoseCallback>& callback) {
+                EXPECT_NE(nullptr, callback);
+                return ndk::ScopedAStatus::ok();
+        });
 
-    EXPECT_TRUE(mSoundDoseManager->setHalSoundDoseInterface(mHalSoundDose));
+    EXPECT_TRUE(mSoundDoseManager->setHalSoundDoseInterface(kPrimaryModule, mHalSoundDose));
+    EXPECT_TRUE(mSoundDoseManager->setHalSoundDoseInterface(kSecondaryModule,
+                                                            mSecondaryHalSoundDose));
 }
 
 TEST_F(SoundDoseManagerTest, MomentaryExposureFromHalWithNoAddressIllegalArgument) {
@@ -154,7 +172,7 @@
            return ndk::ScopedAStatus::ok();
        });
 
-    EXPECT_TRUE(mSoundDoseManager->setHalSoundDoseInterface(mHalSoundDose));
+    EXPECT_TRUE(mSoundDoseManager->setHalSoundDoseInterface(kPrimaryModule, mHalSoundDose));
 
     EXPECT_NE(nullptr, halCallback);
     AudioDevice audioDevice = {};
@@ -175,9 +193,9 @@
            return ndk::ScopedAStatus::ok();
        });
 
-    EXPECT_TRUE(mSoundDoseManager->setHalSoundDoseInterface(mHalSoundDose));
+    EXPECT_TRUE(mSoundDoseManager->setHalSoundDoseInterface(kPrimaryModule, mHalSoundDose));
     EXPECT_NE(nullptr, halCallback);
-    EXPECT_FALSE(mSoundDoseManager->setHalSoundDoseInterface(nullptr));
+    mSoundDoseManager->resetHalSoundDoseInterfaces();
 
     AudioDevice audioDevice = {};
     audioDevice.address.set<AudioDeviceAddress::id>("test");
@@ -197,7 +215,7 @@
            return ndk::ScopedAStatus::ok();
        });
 
-    EXPECT_TRUE(mSoundDoseManager->setHalSoundDoseInterface(mHalSoundDose));
+    EXPECT_TRUE(mSoundDoseManager->setHalSoundDoseInterface(kPrimaryModule, mHalSoundDose));
 
     EXPECT_NE(nullptr, halCallback);
     AudioDevice audioDevice = {};
@@ -248,8 +266,7 @@
 }
 
 TEST_F(SoundDoseManagerTest, GetDefaultForceUseFrameworkMel) {
-    // TODO: for now dogfooding with internal MEL. Revert to false when using the HAL MELs
-    EXPECT_TRUE(mSoundDoseManager->forceUseFrameworkMel());
+    EXPECT_FALSE(mSoundDoseManager->forceUseFrameworkMel());
 }
 
 TEST_F(SoundDoseManagerTest, SetAudioDeviceCategoryStopsNonHeadphone) {
diff --git a/services/audiopolicy/AudioPolicyInterface.h b/services/audiopolicy/AudioPolicyInterface.h
index da0df5f..b954bfc 100644
--- a/services/audiopolicy/AudioPolicyInterface.h
+++ b/services/audiopolicy/AudioPolicyInterface.h
@@ -270,6 +270,10 @@
     virtual status_t registerPolicyMixes(const Vector<AudioMix>& mixes) = 0;
     virtual status_t unregisterPolicyMixes(Vector<AudioMix> mixes) = 0;
 
+    virtual status_t updatePolicyMix(
+        const AudioMix& mix,
+        const std::vector<AudioMixMatchCriterion>& updatedCriteria) = 0;
+
     virtual status_t setUidDeviceAffinities(uid_t uid, const AudioDeviceTypeAddrVector& devices)
             = 0;
     virtual status_t removeUidDeviceAffinities(uid_t uid) = 0;
diff --git a/services/audiopolicy/TEST_MAPPING b/services/audiopolicy/TEST_MAPPING
index fa3a5d3..a2ebb8d 100644
--- a/services/audiopolicy/TEST_MAPPING
+++ b/services/audiopolicy/TEST_MAPPING
@@ -34,5 +34,18 @@
     {
        "name": "audiopolicy_tests"
     }
+  ],
+  "postsubmit": [
+    {
+      "name": "GtsGmscoreHostTestCases",
+      "options" : [
+        {
+          "include-filter": "com.google.android.gts.audio.AudioHostTest"
+        },
+        {
+          "include-filter": "com.google.android.gts.audio.AudioPolicyHostTest"
+        }
+      ]
+    }
   ]
 }
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h
index 7e29e10..b560bc4 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h
@@ -59,6 +59,8 @@
 
     status_t unregisterMix(const AudioMix& mix);
 
+    status_t updateMix(const AudioMix& mix, const std::vector<AudioMixMatchCriterion>& newCriteria);
+
     void closeOutput(sp<SwAudioOutputDescriptor> &desc);
 
     /**
diff --git a/services/audiopolicy/common/managerdefinitions/include/EffectDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/EffectDescriptor.h
index d40bbcb..c2e4b11 100644
--- a/services/audiopolicy/common/managerdefinitions/include/EffectDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/EffectDescriptor.h
@@ -84,6 +84,7 @@
             const AudioInputCollection *inputs, AudioPolicyClientInterface *mClientInterface);
     void putOrphanEffects(audio_session_t sessionId, audio_io_handle_t srcIo,
             const AudioInputCollection *inputs, AudioPolicyClientInterface *clientInterface);
+    void putOrphanEffectsForIo(audio_io_handle_t srcIo);
 
     /**
      * @brief Checks if an effect session was already attached to an io handle and return it if
diff --git a/services/audiopolicy/common/managerdefinitions/include/HwModule.h b/services/audiopolicy/common/managerdefinitions/include/HwModule.h
index e994758..cf20260 100644
--- a/services/audiopolicy/common/managerdefinitions/include/HwModule.h
+++ b/services/audiopolicy/common/managerdefinitions/include/HwModule.h
@@ -43,7 +43,7 @@
     HwModule(const char *name, uint32_t halVersion = 0);
     ~HwModule();
 
-    const char *getName() const { return mName.string(); }
+    const char *getName() const { return mName.c_str(); }
 
     const DeviceVector &getDeclaredDevices() const { return mDeclaredDevices; }
     void setDeclaredDevices(const DeviceVector &devices);
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
index 0f9cc89..a83e0af 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
@@ -21,6 +21,7 @@
 #include <iterator>
 #include <optional>
 #include <regex>
+#include <vector>
 #include "AudioPolicyMix.h"
 #include "TypeConverter.h"
 #include "HwModule.h"
@@ -138,7 +139,7 @@
 
     dst->appendFormat("%*s- device type: %s\n", spaces, "", toString(mDeviceType).c_str());
 
-    dst->appendFormat("%*s- device address: %s\n", spaces, "", mDeviceAddress.string());
+    dst->appendFormat("%*s- device address: %s\n", spaces, "", mDeviceAddress.c_str());
 
     dst->appendFormat("%*s- output: %d\n", spaces, "",
             mOutput == nullptr ? 0 : mOutput->mIoHandle);
@@ -186,7 +187,7 @@
                 && mix.mDeviceAddress.compare(registeredMix->mDeviceAddress) == 0
                 && is_mix_loopback(mix.mRouteFlags)) {
             ALOGE("registerMix(): mix already registered for dev=0x%x addr=%s",
-                    mix.mDeviceType, mix.mDeviceAddress.string());
+                    mix.mDeviceType, mix.mDeviceAddress.c_str());
             return BAD_VALUE;
         }
     }
@@ -198,7 +199,7 @@
     sp<AudioPolicyMix> policyMix = sp<AudioPolicyMix>::make(mix);
     add(policyMix);
     ALOGD("registerMix(): adding mix for dev=0x%x addr=%s",
-            policyMix->mDeviceType, policyMix->mDeviceAddress.string());
+            policyMix->mDeviceType, policyMix->mDeviceAddress.c_str());
 
     if (desc != nullptr) {
         desc->mPolicyMix = policyMix;
@@ -214,14 +215,39 @@
         if (mix.mDeviceType == registeredMix->mDeviceType
                 && mix.mDeviceAddress.compare(registeredMix->mDeviceAddress) == 0) {
             ALOGD("unregisterMix(): removing mix for dev=0x%x addr=%s",
-                    mix.mDeviceType, mix.mDeviceAddress.string());
+                    mix.mDeviceType, mix.mDeviceAddress.c_str());
             removeAt(i);
             return NO_ERROR;
         }
     }
 
     ALOGE("unregisterMix(): mix not registered for dev=0x%x addr=%s",
-            mix.mDeviceType, mix.mDeviceAddress.string());
+            mix.mDeviceType, mix.mDeviceAddress.c_str());
+    return BAD_VALUE;
+}
+
+status_t AudioPolicyMixCollection::updateMix(
+        const AudioMix& mix, const std::vector<AudioMixMatchCriterion>& updatedCriteria) {
+    if (!areMixCriteriaConsistent(mix.mCriteria)) {
+        ALOGE("updateMix(): updated criteria are not consistent "
+              "(MATCH & EXCLUDE criteria of the same type)");
+        return BAD_VALUE;
+    }
+
+    for (size_t i = 0; i < size(); i++) {
+        const sp<AudioPolicyMix>& registeredMix = itemAt(i);
+        if (mix.mDeviceType == registeredMix->mDeviceType &&
+            mix.mDeviceAddress.compare(registeredMix->mDeviceAddress) == 0 &&
+            mix.mRouteFlags == registeredMix->mRouteFlags) {
+            registeredMix->mCriteria = updatedCriteria;
+            ALOGV("updateMix(): updated mix for dev=0x%x addr=%s", mix.mDeviceType,
+                  mix.mDeviceAddress.string());
+            return NO_ERROR;
+        }
+    }
+
+    ALOGE("updateMix(): mix not registered for dev=0x%x addr=%s", mix.mDeviceType,
+          mix.mDeviceAddress.string());
     return BAD_VALUE;
 }
 
@@ -229,20 +255,20 @@
         const String8& address, sp<AudioPolicyMix> &policyMix) const
 {
 
-    ALOGV("getAudioPolicyMix() for dev=0x%x addr=%s", deviceType, address.string());
+    ALOGV("getAudioPolicyMix() for dev=0x%x addr=%s", deviceType, address.c_str());
     for (ssize_t i = 0; i < size(); i++) {
         // Workaround: when an in audio policy is registered, it opens an output
         // that tries to find the audio policy, thus the device must be ignored.
         if (itemAt(i)->mDeviceAddress.compare(address) == 0) {
             policyMix = itemAt(i);
             ALOGV("getAudioPolicyMix: found mix %zu match (devType=0x%x addr=%s)",
-                    i, deviceType, address.string());
+                    i, deviceType, address.c_str());
             return NO_ERROR;
         }
     }
 
     ALOGE("getAudioPolicyMix(): mix not registered for dev=0x%x addr=%s",
-            deviceType, address.string());
+            deviceType, address.c_str());
     return BAD_VALUE;
 }
 
@@ -457,7 +483,7 @@
             address->c_str(), attr.source);
     for (size_t i = 0; i < size(); i++) {
         const sp<AudioPolicyMix> audioPolicyMix = itemAt(i);
-        ALOGV("\tmix %zu address=%s", i, audioPolicyMix->mDeviceAddress.string());
+        ALOGV("\tmix %zu address=%s", i, audioPolicyMix->mDeviceAddress.c_str());
     }
 #endif
 
@@ -466,7 +492,7 @@
         const sp<AudioPolicyMix>& registeredMix = itemAt(index);
         if (address->compare(registeredMix->mDeviceAddress.c_str()) == 0) {
             ALOGD("getInputMixForAttr found addr=%s dev=0x%x",
-                    registeredMix->mDeviceAddress.string(), registeredMix->mDeviceType);
+                    registeredMix->mDeviceAddress.c_str(), registeredMix->mDeviceType);
             break;
         }
     }
@@ -515,7 +541,7 @@
         }
         // check if this mix goes to a device in the list of devices
         bool deviceMatch = false;
-        const AudioDeviceTypeAddr mixDevice(mix->mDeviceType, mix->mDeviceAddress.string());
+        const AudioDeviceTypeAddr mixDevice(mix->mDeviceType, mix->mDeviceAddress.c_str());
         for (size_t j = 0; j < devices.size(); j++) {
             if (mixDevice.equals(devices[j])) {
                 deviceMatch = true;
@@ -571,7 +597,7 @@
             }
         }
         if (ruleAllowsUid) {
-            devices.add(AudioDeviceTypeAddr(mix->mDeviceType, mix->mDeviceAddress.string()));
+            devices.add(AudioDeviceTypeAddr(mix->mDeviceType, mix->mDeviceAddress.c_str()));
         }
     }
     return NO_ERROR;
@@ -606,7 +632,7 @@
         }
         // check if this mix goes to a device in the list of devices
         bool deviceMatch = false;
-        const AudioDeviceTypeAddr mixDevice(mix->mDeviceType, mix->mDeviceAddress.string());
+        const AudioDeviceTypeAddr mixDevice(mix->mDeviceType, mix->mDeviceAddress.c_str());
         for (size_t j = 0; j < devices.size(); j++) {
             if (mixDevice.equals(devices[j])) {
                 deviceMatch = true;
@@ -668,7 +694,7 @@
             }
         }
         if (ruleAllowsUserId) {
-            devices.push_back(AudioDeviceTypeAddr(mix->mDeviceType, mix->mDeviceAddress.string()));
+            devices.push_back(AudioDeviceTypeAddr(mix->mDeviceType, mix->mDeviceAddress.c_str()));
         }
     }
     return NO_ERROR;
diff --git a/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
index a909331..62e5bd4 100644
--- a/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
@@ -185,7 +185,7 @@
     }
 
     std::string descBaseDumpStr;
-    DeviceDescriptorBase::dump(&descBaseDumpStr, spaces, extraInfo.string(), verbose);
+    DeviceDescriptorBase::dump(&descBaseDumpStr, spaces, extraInfo.c_str(), verbose);
     dst->append(descBaseDumpStr.c_str());
 }
 
@@ -325,7 +325,7 @@
         }
     }
     ALOGV("DeviceVector::%s() for type %08x address \"%s\" found %p format %08x",
-            __func__, type, address.string(), device.get(), format);
+            __func__, type, address.c_str(), device.get(), format);
     return device;
 }
 
@@ -448,7 +448,7 @@
     if (isEmpty()) {
         return;
     }
-    dst->appendFormat("%*s%s devices (%zu):\n", spaces, "", tag.string(), size());
+    dst->appendFormat("%*s%s devices (%zu):\n", spaces, "", tag.c_str(), size());
     for (size_t i = 0; i < size(); i++) {
         const std::string prefix = base::StringPrintf("%*s %zu. ", spaces, "", i + 1);
         dst->appendFormat("%s", prefix.c_str());
diff --git a/services/audiopolicy/common/managerdefinitions/src/EffectDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/EffectDescriptor.cpp
index 1f6946c..c85df0f 100644
--- a/services/audiopolicy/common/managerdefinitions/src/EffectDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/EffectDescriptor.cpp
@@ -302,6 +302,17 @@
     }
 }
 
+void EffectDescriptorCollection::putOrphanEffectsForIo(audio_io_handle_t srcIo)
+{
+    for (size_t i = 0; i < size(); i++) {
+        sp<EffectDescriptor> effect = valueAt(i);
+        if (effect->mIo == srcIo) {
+            effect->mIo = AUDIO_IO_HANDLE_NONE;
+            effect->mIsOrphan = true;
+        }
+    }
+}
+
 void EffectDescriptorCollection::putOrphanEffects(audio_session_t session,
         audio_io_handle_t srcIo, const AudioInputCollection *inputs,
         AudioPolicyClientInterface *clientInterface)
diff --git a/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp b/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp
index 95f8d14..2c8e50b 100644
--- a/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp
@@ -67,7 +67,7 @@
                                               config->sample_rate));
 
     sp<DeviceDescriptor> devDesc =
-            new DeviceDescriptor(device, getTagForDevice(device), address.string());
+            new DeviceDescriptor(device, getTagForDevice(device), address.c_str());
     addDynamicDevice(devDesc);
     // Reciprocally attach the device to the module
     devDesc->attach(this);
@@ -135,7 +135,7 @@
                                               config->sample_rate));
 
     sp<DeviceDescriptor> devDesc =
-            new DeviceDescriptor(device, getTagForDevice(device), address.string());
+            new DeviceDescriptor(device, getTagForDevice(device), address.c_str());
     addDynamicDevice(devDesc);
     // Reciprocally attach the device to the module
     devDesc->attach(this);
@@ -375,7 +375,7 @@
             if (allowToCreate) {
                 moduleDevice->attach(hwModule);
                 // Name may be overwritten, restored on detach.
-                moduleDevice->setAddress(devAddress.string());
+                moduleDevice->setAddress(devAddress.c_str());
                 // Name may be overwritten, restored on detach.
                 moduleDevice->setName(name);
             }
diff --git a/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp b/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp
index 3d5c1d2..6f19a7a 100644
--- a/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp
@@ -618,13 +618,15 @@
     }
     // Convert Sink name to port pointer
     sp<PolicyAudioPort> sink = ctx->findPortByTagName(sinkAttr);
-    if (sink == NULL && !mIgnoreVendorExtensions) {
-        ALOGE("%s: no sink found with name=%s", __func__, sinkAttr.c_str());
-        return BAD_VALUE;
-    } else if (sink == NULL) {
-        ALOGW("Skipping route to sink \"%s\" as it likely has vendor extension type",
-                sinkAttr.c_str());
-        return NO_INIT;
+    if (sink == NULL) {
+        if (!mIgnoreVendorExtensions) {
+            ALOGE("%s: no sink found with name \"%s\"", __func__, sinkAttr.c_str());
+            return BAD_VALUE;
+        } else {
+            ALOGW("%s: skipping route to sink \"%s\" as it likely has vendor extension type",
+                  __func__, sinkAttr.c_str());
+            return NO_INIT;
+        }
     }
     route->setSink(sink);
 
@@ -641,12 +643,14 @@
     while (devTag != NULL) {
         if (strlen(devTag) != 0) {
             sp<PolicyAudioPort> source = ctx->findPortByTagName(devTag);
-            if (source == NULL && !mIgnoreVendorExtensions) {
-                ALOGE("%s: no source found with name=%s", __func__, devTag);
-                return BAD_VALUE;
-            } else if (source == NULL) {
-                ALOGW("Skipping route source \"%s\" as it likely has vendor extension type",
-                        devTag);
+            if (source == NULL) {
+                if (!mIgnoreVendorExtensions) {
+                    ALOGE("%s: no source found with name \"%s\"", __func__, devTag);
+                    return BAD_VALUE;
+                } else {
+                    ALOGW("%s: skipping route source \"%s\" as it likely has vendor extension type",
+                          __func__, devTag);
+                }
             } else {
                 sources.add(source);
             }
@@ -728,10 +732,16 @@
                         sp<DeviceDescriptor> device = module->getDeclaredDevices().
                                 getDeviceFromTagName(std::string(reinterpret_cast<const char*>(
                                                         attachedDevice.get())));
-                        if (device == nullptr && mIgnoreVendorExtensions) {
-                            ALOGW("Skipped attached device \"%s\" because it likely uses a vendor"
-                                    "extension type",
-                                    reinterpret_cast<const char*>(attachedDevice.get()));
+                        if (device == NULL) {
+                            if (mIgnoreVendorExtensions) {
+                                ALOGW("%s: skipped attached device \"%s\" because it likely uses a "
+                                      "vendor extension type",
+                                      __func__,
+                                      reinterpret_cast<const char*>(attachedDevice.get()));
+                            } else {
+                                ALOGE("%s: got null device in %s, \"%s\"", __func__, child->name,
+                                      reinterpret_cast<const char*>(attachedDevice.get()));
+                            }
                             continue;
                         }
                         ctx->addDevice(device);
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/enginedefault/src/Engine.cpp b/services/audiopolicy/enginedefault/src/Engine.cpp
index 15f7842..fa6be39 100644
--- a/services/audiopolicy/enginedefault/src/Engine.cpp
+++ b/services/audiopolicy/enginedefault/src/Engine.cpp
@@ -175,34 +175,37 @@
         //   - cannot route from voice call RX OR
         //   - audio HAL version is < 3.0 and TX device is on the primary HW module
         if (getPhoneState() == AUDIO_MODE_IN_CALL) {
-            audio_devices_t txDevice = AUDIO_DEVICE_NONE;
-            sp<DeviceDescriptor> txDeviceDesc =
-                    getDeviceForInputSource(AUDIO_SOURCE_VOICE_COMMUNICATION);
-            if (txDeviceDesc != nullptr) {
-                txDevice = txDeviceDesc->type();
-            }
             sp<AudioOutputDescriptor> primaryOutput = outputs.getPrimaryOutput();
-            LOG_ALWAYS_FATAL_IF(primaryOutput == nullptr, "Primary output not found");
-            DeviceVector availPrimaryInputDevices =
-                    availableInputDevices.getDevicesFromHwModule(primaryOutput->getModuleHandle());
+            if (primaryOutput != nullptr) {
+                audio_devices_t txDevice = AUDIO_DEVICE_NONE;
+                sp<DeviceDescriptor> txDeviceDesc =
+                        getDeviceForInputSource(AUDIO_SOURCE_VOICE_COMMUNICATION);
+                if (txDeviceDesc != nullptr) {
+                    txDevice = txDeviceDesc->type();
+                }
+                DeviceVector availPrimaryInputDevices =
+                        availableInputDevices.getDevicesFromHwModule(
+                            primaryOutput->getModuleHandle());
 
-            // TODO: getPrimaryOutput return only devices from first module in
-            // audio_policy_configuration.xml, hearing aid is not there, but it's
-            // a primary device
-            // FIXME: this is not the right way of solving this problem
-            DeviceVector availPrimaryOutputDevices = availableOutputDevices.getDevicesFromTypes(
-                    primaryOutput->supportedDevices().types());
-            availPrimaryOutputDevices.add(
-                    availableOutputDevices.getDevicesFromType(AUDIO_DEVICE_OUT_HEARING_AID));
+                // TODO: getPrimaryOutput return only devices from first module in
+                // audio_policy_configuration.xml, hearing aid is not there, but it's
+                // a primary device
+                // FIXME: this is not the right way of solving this problem
+                DeviceVector availPrimaryOutputDevices = availableOutputDevices.getDevicesFromTypes(
+                        primaryOutput->supportedDevices().types());
+                availPrimaryOutputDevices.add(
+                        availableOutputDevices.getDevicesFromType(AUDIO_DEVICE_OUT_HEARING_AID));
 
-            if ((availableInputDevices.getDevice(AUDIO_DEVICE_IN_TELEPHONY_RX,
-                                                 String8(""), AUDIO_FORMAT_DEFAULT) == nullptr) ||
-                ((availPrimaryInputDevices.getDevice(
-                        txDevice, String8(""), AUDIO_FORMAT_DEFAULT) != nullptr) &&
-                 (primaryOutput->getPolicyAudioPort()->getModuleVersionMajor() < 3))) {
-                availableOutputDevices = availPrimaryOutputDevices;
+                if ((availableInputDevices.getDevice(AUDIO_DEVICE_IN_TELEPHONY_RX,
+                                                     String8(""), AUDIO_FORMAT_DEFAULT) == nullptr)
+                    || ((availPrimaryInputDevices.getDevice(
+                            txDevice, String8(""), AUDIO_FORMAT_DEFAULT) != nullptr) &&
+                     (primaryOutput->getPolicyAudioPort()->getModuleVersionMajor() < 3))) {
+                    availableOutputDevices = availPrimaryOutputDevices;
+                }
+            } else {
+                ALOGE("%s, STRATEGY_PHONE: Primary output not found", __func__);
             }
-
         }
         // Do not use A2DP devices when in call but use them when not in call
         // (e.g for voice mail playback)
@@ -595,8 +598,11 @@
         if ((getPhoneState() == AUDIO_MODE_IN_CALL) &&
                 (availableOutputDevices.getDevice(AUDIO_DEVICE_OUT_TELEPHONY_TX,
                         String8(""), AUDIO_FORMAT_DEFAULT)) == nullptr) {
-            LOG_ALWAYS_FATAL_IF(availablePrimaryDevices.isEmpty(), "Primary devices not found");
-            availableDevices = availablePrimaryDevices;
+            if (!availablePrimaryDevices.isEmpty()) {
+                availableDevices = availablePrimaryDevices;
+            } else {
+                ALOGE("%s, AUDIO_SOURCE_VOICE_COMMUNICATION: Primary devices not found", __func__);
+            }
         }
 
         if (audio_is_bluetooth_out_sco_device(commDeviceType)) {
@@ -650,8 +656,11 @@
     case AUDIO_SOURCE_HOTWORD:
         // We should not use primary output criteria for Hotword but rather limit
         // to devices attached to the same HW module as the build in mic
-        LOG_ALWAYS_FATAL_IF(availablePrimaryDevices.isEmpty(), "Primary devices not found");
-        availableDevices = availablePrimaryDevices;
+        if (!availablePrimaryDevices.isEmpty()) {
+            availableDevices = availablePrimaryDevices;
+        } else {
+            ALOGE("%s, AUDIO_SOURCE_HOTWORD: Primary devices not found", __func__);
+        }
         if (audio_is_bluetooth_out_sco_device(commDeviceType)) {
             device = availableDevices.getDevice(
                     AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET, String8(""), AUDIO_FORMAT_DEFAULT);
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/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 884ad96..a72598e 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include "utils/Errors.h"
 #define LOG_TAG "APM_AudioPolicyManager"
 
 // Need to keep the log statements even in production builds
@@ -277,7 +278,7 @@
                 sp<AudioPolicyMix> policyMix = desc->mPolicyMix.promote();
                 if (policyMix != nullptr
                         && policyMix->mMixType == MIX_TYPE_RECORDERS
-                        && device->address() == policyMix->mDeviceAddress.string()) {
+                        && device->address() == policyMix->mDeviceAddress.c_str()) {
                     doCheckForDeviceAndOutputChanges = false;
                     break;
                 }
@@ -2242,7 +2243,7 @@
     const char *address = NULL;
     if (policyMix != nullptr) {
         audio_devices_t newDeviceType;
-        address = policyMix->mDeviceAddress.string();
+        address = policyMix->mDeviceAddress.c_str();
         if ((policyMix->mRouteFlags & MIX_ROUTE_FLAG_LOOP_BACK) == MIX_ROUTE_FLAG_LOOP_BACK) {
             newDeviceType = AUDIO_DEVICE_OUT_REMOTE_SUBMIX;
         } else {
@@ -3640,7 +3641,7 @@
             }
 
             if (mPolicyMixes.registerMix(mix, 0 /*output desc*/) != NO_ERROR) {
-                ALOGE("Error registering mix %zu for address %s", i, address.string());
+                ALOGE("Error registering mix %zu for address %s", i, address.c_str());
                 res = INVALID_OPERATION;
                 break;
             }
@@ -3657,16 +3658,16 @@
 
             if ((res = setDeviceConnectionStateInt(deviceTypeToMakeAvailable,
                     AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
-                    address.string(), "remote-submix", AUDIO_FORMAT_DEFAULT)) != NO_ERROR) {
+                    address.c_str(), "remote-submix", AUDIO_FORMAT_DEFAULT)) != NO_ERROR) {
                 ALOGE("Failed to set remote submix device available, type %u, address %s",
-                        mix.mDeviceType, address.string());
+                        mix.mDeviceType, address.c_str());
                 break;
             }
         } else if ((mix.mRouteFlags & MIX_ROUTE_FLAG_RENDER) == MIX_ROUTE_FLAG_RENDER) {
             String8 address = mix.mDeviceAddress;
             audio_devices_t type = mix.mDeviceType;
             ALOGV(" registerPolicyMixes() mix %zu of %zu is RENDER, dev=0x%X addr=%s",
-                    i, mixes.size(), type, address.string());
+                    i, mixes.size(), type, address.c_str());
 
             sp<DeviceDescriptor> device = mHwModules.getDeviceDescriptor(
                     mix.mDeviceType, mix.mDeviceAddress,
@@ -3684,7 +3685,7 @@
                 if (!desc->isDuplicated() && desc->supportedDevices().contains(device)) {
                     if (mPolicyMixes.registerMix(mix, desc) != NO_ERROR) {
                         ALOGE("Could not register mix RENDER,  dev=0x%X addr=%s", type,
-                              address.string());
+                              address.c_str());
                         res = INVALID_OPERATION;
                     } else {
                         foundOutput = true;
@@ -3701,7 +3702,7 @@
                     if (profile->isDirectOutput() && profile->supportsDevice(device)) {
                         if (mPolicyMixes.registerMix(mix, nullptr) != NO_ERROR) {
                             ALOGE("Could not register mix RENDER,  dev=0x%X addr=%s", type,
-                                  address.string());
+                                  address.c_str());
                             res = INVALID_OPERATION;
                         } else {
                             foundOutput = true;
@@ -3711,12 +3712,12 @@
             }
             if (res != NO_ERROR) {
                 ALOGE(" Error registering mix %zu for device 0x%X addr %s",
-                        i, type, address.string());
+                        i, type, address.c_str());
                 res = INVALID_OPERATION;
                 break;
             } else if (!foundOutput) {
                 ALOGE(" Output not found for mix %zu for device 0x%X addr %s",
-                        i, type, address.string());
+                        i, type, address.c_str());
                 res = INVALID_OPERATION;
                 break;
             } else {
@@ -3760,14 +3761,14 @@
             }
 
             for (auto device : {AUDIO_DEVICE_IN_REMOTE_SUBMIX, AUDIO_DEVICE_OUT_REMOTE_SUBMIX}) {
-                if (getDeviceConnectionState(device, address.string()) ==
+                if (getDeviceConnectionState(device, address.c_str()) ==
                         AUDIO_POLICY_DEVICE_STATE_AVAILABLE)  {
                     res = setDeviceConnectionStateInt(device, AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
-                                                      address.string(), "remote-submix",
+                                                      address.c_str(), "remote-submix",
                                                       AUDIO_FORMAT_DEFAULT);
                     if (res != OK) {
                         ALOGE("Error making RemoteSubmix device unavailable for mix "
-                              "with type %d, address %s", device, address.string());
+                              "with type %d, address %s", device, address.c_str());
                     }
                 }
             }
@@ -3790,6 +3791,17 @@
     return res;
 }
 
+status_t AudioPolicyManager::updatePolicyMix(
+            const AudioMix& mix,
+            const std::vector<AudioMixMatchCriterion>& updatedCriteria) {
+    status_t res = mPolicyMixes.updateMix(mix, updatedCriteria);
+    if (res == NO_ERROR) {
+        checkForDeviceAndOutputChanges();
+        updateCallAndOutputRouting();
+    }
+    return res;
+}
+
 void AudioPolicyManager::dumpManualSurroundFormats(String8 *dst) const
 {
     size_t i = 0;
@@ -4231,7 +4243,7 @@
 {
     String8 result;
     dump(&result);
-    write(fd, result.string(), result.size());
+    write(fd, result.c_str(), result.size());
     return NO_ERROR;
 }
 
@@ -6454,7 +6466,7 @@
             }
 
             ALOGV("opening output for device %08x with params %s profile %p name %s",
-                  deviceType, address.string(), profile.get(), profile->getName().c_str());
+                  deviceType, address.c_str(), profile.get(), profile->getName().c_str());
             desc = openOutputWithProfileAndDevice(profile, DeviceVector(device));
             audio_io_handle_t output = desc == nullptr ? AUDIO_IO_HANDLE_NONE : desc->mIoHandle;
             if (output == AUDIO_IO_HANDLE_NONE) {
@@ -6609,7 +6621,7 @@
 
             if (status == NO_ERROR) {
                 const String8& address = String8(device->address().c_str());
-                if (!address.isEmpty()) {
+                if (!address.empty()) {
                     char *param = audio_device_address_to_parameter(device->type(), address);
                     mpClientInterface->setParameters(input, String8(param));
                     free(param);
@@ -6769,6 +6781,7 @@
         mpClientInterface->onAudioPatchListUpdate();
     }
 
+    mEffects.putOrphanEffectsForIo(input);
     inputDesc->close();
     mInputs.removeItem(input);
 
@@ -7685,8 +7698,10 @@
     const auto musicVolumeSrc = toVolumeSource(AUDIO_STREAM_MUSIC, false);
     const auto alarmVolumeSrc = toVolumeSource(AUDIO_STREAM_ALARM, false);
     const auto a11yVolumeSrc = toVolumeSource(AUDIO_STREAM_ACCESSIBILITY, false);
-
-    if (volumeSource == a11yVolumeSrc
+    // Verify that the current volume source is not the ringer volume to prevent recursively
+    // calling to compute volume. This could happen in cases where a11y and ringer sounds belong
+    // to the same volume group.
+    if (volumeSource != ringVolumeSrc && volumeSource == a11yVolumeSrc
             && (AUDIO_MODE_RINGTONE == mEngine->getPhoneState()) &&
             mOutputs.isActive(ringVolumeSrc, 0)) {
         auto &ringCurves = getVolumeCurves(AUDIO_STREAM_RING);
@@ -7749,8 +7764,12 @@
         // when the phone is ringing we must consider that music could have been paused just before
         // by the music application and behave as if music was active if the last music track was
         // just stopped
-        if (isStreamActive(AUDIO_STREAM_MUSIC, SONIFICATION_HEADSET_MUSIC_DELAY) ||
-                mLimitRingtoneVolume) {
+        // Verify that the current volume source is not the music volume to prevent recursively
+        // calling to compute volume. This could happen in cases where music and
+        // (alarm, ring, notification, system, etc.) sounds belong to the same volume group.
+        if (volumeSource != musicVolumeSrc &&
+            (isStreamActive(AUDIO_STREAM_MUSIC, SONIFICATION_HEADSET_MUSIC_DELAY)
+                || mLimitRingtoneVolume)) {
             volumeDb += SONIFICATION_HEADSET_VOLUME_FACTOR_DB;
             DeviceTypeSet musicDevice =
                     mEngine->getOutputDevicesForAttributes(attributes_initializer(AUDIO_USAGE_MEDIA),
@@ -8167,12 +8186,12 @@
     if (profiles.hasDynamicFormat()) {
         reply = mpClientInterface->getParameters(
                 ioHandle, String8(AudioParameter::keyStreamSupportedFormats));
-        ALOGV("%s: supported formats %d, %s", __FUNCTION__, ioHandle, reply.string());
+        ALOGV("%s: supported formats %d, %s", __FUNCTION__, ioHandle, reply.c_str());
         AudioParameter repliedParameters(reply);
         FormatVector formats;
         if (repliedParameters.get(
                 String8(AudioParameter::keyStreamSupportedFormats), reply) == NO_ERROR) {
-            formats = formatsFromString(reply.string());
+            formats = formatsFromString(reply.c_str());
         } else if (devDesc->hasValidAudioProfile()) {
             ALOGD("%s: using the device profiles", __func__);
             formats = devDesc->getAudioProfiles().getSupportedFormats();
@@ -8199,11 +8218,11 @@
                     ioHandle,
                     requestedParameters.toString() + ";" +
                     AudioParameter::keyStreamSupportedSamplingRates);
-            ALOGV("%s: supported sampling rates %s", __FUNCTION__, reply.string());
+            ALOGV("%s: supported sampling rates %s", __FUNCTION__, reply.c_str());
             AudioParameter repliedParameters(reply);
             if (repliedParameters.get(
                     String8(AudioParameter::keyStreamSupportedSamplingRates), reply) == NO_ERROR) {
-                samplingRates = samplingRatesFromString(reply.string());
+                samplingRates = samplingRatesFromString(reply.c_str());
             } else {
                 samplingRates = devDesc->getAudioProfiles().getSampleRatesFor(format);
             }
@@ -8212,11 +8231,11 @@
             reply = mpClientInterface->getParameters(ioHandle,
                                                      requestedParameters.toString() + ";" +
                                                      AudioParameter::keyStreamSupportedChannels);
-            ALOGV("%s: supported channel masks %s", __FUNCTION__, reply.string());
+            ALOGV("%s: supported channel masks %s", __FUNCTION__, reply.c_str());
             AudioParameter repliedParameters(reply);
             if (repliedParameters.get(
                     String8(AudioParameter::keyStreamSupportedChannels), reply) == NO_ERROR) {
-                channelMasks = channelMasksFromString(reply.string());
+                channelMasks = channelMasksFromString(reply.c_str());
             } else {
                 channelMasks = devDesc->getAudioProfiles().getChannelMasksFor(format);
             }
@@ -8350,7 +8369,7 @@
     sp<DeviceDescriptor> device = devices.getDeviceForOpening();
     const audio_devices_t deviceType = device->type();
     const String8 &address = String8(device->address().c_str());
-    if (!address.isEmpty()) {
+    if (!address.empty()) {
         char *param = audio_device_address_to_parameter(deviceType, address.c_str());
         mpClientInterface->setParameters(output, String8(param));
         free(param);
@@ -8390,7 +8409,7 @@
             desc->mPolicyMix = policyMix;
         } else {
             ALOGW("checkOutputsForDevice() cannot find policy for address %s",
-                    address.string());
+                    address.c_str());
         }
 
     } else if (hasPrimaryOutput() && speaker != nullptr
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
index 509cc79..91fe1cc 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
@@ -292,6 +292,9 @@
 
         virtual status_t registerPolicyMixes(const Vector<AudioMix>& mixes);
         virtual status_t unregisterPolicyMixes(Vector<AudioMix> mixes);
+        virtual status_t updatePolicyMix(
+                const AudioMix& mix,
+                const std::vector<AudioMixMatchCriterion>& updatedCriteria) override;
         virtual status_t setUidDeviceAffinities(uid_t uid,
                 const AudioDeviceTypeAddrVector& devices);
         virtual status_t removeUidDeviceAffinities(uid_t uid);
diff --git a/services/audiopolicy/service/AudioPolicyClientImpl.cpp b/services/audiopolicy/service/AudioPolicyClientImpl.cpp
index 13e682b..2874824 100644
--- a/services/audiopolicy/service/AudioPolicyClientImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyClientImpl.cpp
@@ -190,7 +190,7 @@
                    const String8& keyValuePairs,
                    int delay_ms)
 {
-    mAudioPolicyService->setParameters(io_handle, keyValuePairs.string(), delay_ms);
+    mAudioPolicyService->setParameters(io_handle, keyValuePairs.c_str(), delay_ms);
 }
 
 String8 AudioPolicyService::AudioPolicyClient::getParameters(audio_io_handle_t io_handle,
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
index a7b2a56..ce9fb92 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
@@ -1764,6 +1764,22 @@
     }
 }
 
+Status AudioPolicyService::updatePolicyMixes(
+        const ::std::vector<::android::media::AudioMixUpdate>& updates) {
+    Mutex::Autolock _l(mLock);
+    for (const auto& update : updates) {
+        AudioMix mix = VALUE_OR_RETURN_BINDER_STATUS(aidl2legacy_AudioMix(update.audioMix));
+        std::vector<AudioMixMatchCriterion> newCriteria =
+                VALUE_OR_RETURN_BINDER_STATUS(convertContainer<std::vector<AudioMixMatchCriterion>>(
+                        update.newCriteria, aidl2legacy_AudioMixMatchCriterion));
+        int status;
+        if((status = mAudioPolicyManager->updatePolicyMix(mix, newCriteria)) != NO_ERROR) {
+            return binderStatusFromStatusT(status);
+        }
+    }
+    return binderStatusFromStatusT(NO_ERROR);
+}
+
 Status AudioPolicyService::setUidDeviceAffinities(
         int32_t uidAidl,
         const std::vector<AudioDevice>& devicesAidl) {
diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp
index 72fa245..aa2b6f5 100644
--- a/services/audiopolicy/service/AudioPolicyService.cpp
+++ b/services/audiopolicy/service/AudioPolicyService.cpp
@@ -120,6 +120,7 @@
 BINDER_METHOD_ENTRY(releaseSoundTriggerSession) \
 BINDER_METHOD_ENTRY(getPhoneState) \
 BINDER_METHOD_ENTRY(registerPolicyMixes) \
+BINDER_METHOD_ENTRY(updatePolicyMixes) \
 BINDER_METHOD_ENTRY(setUidDeviceAffinities) \
 BINDER_METHOD_ENTRY(removeUidDeviceAffinities) \
 BINDER_METHOD_ENTRY(setUserIdDeviceAffinities) \
@@ -467,7 +468,7 @@
 void AudioPolicyService::onDynamicPolicyMixStateUpdate(const String8& regId, int32_t state)
 {
     ALOGV("AudioPolicyService::onDynamicPolicyMixStateUpdate(%s, %d)",
-            regId.string(), state);
+            regId.c_str(), state);
     mOutputCommandThread->dynamicPolicyMixStateUpdateCommand(regId, state);
 }
 
@@ -811,7 +812,7 @@
     msg << std::endl;
     result.append(msg.str().c_str());
 
-    write(fd, result.string(), result.size());
+    write(fd, result.c_str(), result.size());
 
     mUidPolicy->dumpInternals(fd);
     return NO_ERROR;
@@ -1205,19 +1206,19 @@
         const bool locked = dumpTryLock(mLock);
         if (!locked) {
             String8 result(kDeadlockedString);
-            write(fd, result.string(), result.size());
+            write(fd, result.c_str(), result.size());
         }
 
         dumpInternals(fd);
 
         String8 actPtr = String8::format("AudioCommandThread: %p\n", mAudioCommandThread.get());
-        write(fd, actPtr.string(), actPtr.size());
+        write(fd, actPtr.c_str(), actPtr.size());
         if (mAudioCommandThread != 0) {
             mAudioCommandThread->dump(fd);
         }
 
         String8 octPtr = String8::format("OutputCommandThread: %p\n", mOutputCommandThread.get());
-        write(fd, octPtr.string(), octPtr.size());
+        write(fd, octPtr.c_str(), octPtr.size());
         if (mOutputCommandThread != 0) {
             mOutputCommandThread->dump(fd);
         }
@@ -1226,7 +1227,7 @@
             mAudioPolicyManager->dump(fd);
         } else {
             String8 apmPtr = String8::format("AudioPolicyManager: %p\n", mAudioPolicyManager);
-            write(fd, apmPtr.string(), apmPtr.size());
+            write(fd, apmPtr.c_str(), apmPtr.size());
         }
 
         mPackageManager.dump(fd);
@@ -1260,7 +1261,7 @@
             IPCThreadState::self()->getCallingPid(),
             IPCThreadState::self()->getCallingUid());
     result.append(buffer);
-    write(fd, result.string(), result.size());
+    write(fd, result.c_str(), result.size());
     return NO_ERROR;
 }
 
@@ -1307,6 +1308,7 @@
         case TRANSACTION_isStreamActiveRemotely:
         case TRANSACTION_isSourceActive:
         case TRANSACTION_registerPolicyMixes:
+        case TRANSACTION_updatePolicyMixes:
         case TRANSACTION_setMasterMono:
         case TRANSACTION_getSurroundFormats:
         case TRANSACTION_getReportedSurroundFormats:
@@ -1439,8 +1441,8 @@
     PermissionController pc;
     uid = pc.getPackageUid(packageName, 0);
     if (uid <= 0) {
-        ALOGE("Unknown package: '%s'", String8(packageName).string());
-        dprintf(err, "Unknown package: '%s'\n", String8(packageName).string());
+        ALOGE("Unknown package: '%s'", String8(packageName).c_str());
+        dprintf(err, "Unknown package: '%s'\n", String8(packageName).c_str());
         return BAD_VALUE;
     }
 
@@ -1459,7 +1461,7 @@
     if (args[2] == String16("active")) {
         active = true;
     } else if ((args[2] != String16("idle"))) {
-        ALOGE("Expected active or idle but got: '%s'", String8(args[2]).string());
+        ALOGE("Expected active or idle but got: '%s'", String8(args[2]).c_str());
         return BAD_VALUE;
     }
 
@@ -1839,7 +1841,7 @@
     snprintf(buffer, SIZE, "\tIs RTT Enabled: %s\n", (mRttEnabled ? "True":"False"));
     result.append(buffer);
 
-    write(fd, result.string(), result.size());
+    write(fd, result.c_str(), result.size());
 }
 
 // -----------  AudioPolicyService::SensorPrivacyService implementation ----------
@@ -1880,14 +1882,14 @@
 AudioPolicyService::AudioCommandThread::~AudioCommandThread()
 {
     if (!mAudioCommands.isEmpty()) {
-        release_wake_lock(mName.string());
+        release_wake_lock(mName.c_str());
     }
     mAudioCommands.clear();
 }
 
 void AudioPolicyService::AudioCommandThread::onFirstRef()
 {
-    run(mName.string(), ANDROID_PRIORITY_AUDIO);
+    run(mName.c_str(), ANDROID_PRIORITY_AUDIO);
 }
 
 bool AudioPolicyService::AudioCommandThread::threadLoop()
@@ -1924,7 +1926,7 @@
                 case SET_PARAMETERS: {
                     ParametersData *data = (ParametersData *)command->mParam.get();
                     ALOGV("AudioCommandThread() processing set parameters string %s, io %d",
-                            data->mKeyValuePairs.string(), data->mIO);
+                            data->mKeyValuePairs.c_str(), data->mIO);
                     mLock.unlock();
                     command->mStatus = AudioSystem::setParameters(data->mIO, data->mKeyValuePairs);
                     mLock.lock();
@@ -2033,7 +2035,7 @@
                     DynPolicyMixStateUpdateData *data =
                             (DynPolicyMixStateUpdateData *)command->mParam.get();
                     ALOGV("AudioCommandThread() processing dyn policy mix state update %s %d",
-                            data->mRegId.string(), data->mState);
+                            data->mRegId.c_str(), data->mState);
                     svc = mService.promote();
                     if (svc == 0) {
                         break;
@@ -2158,7 +2160,7 @@
         // release delayed commands wake lock as many times as we made the  queue is
         // empty during popping.
         while (numTimesBecameEmpty--) {
-            release_wake_lock(mName.string());
+            release_wake_lock(mName.c_str());
         }
 
         // At this stage we have either an empty command queue or the first command in the queue
@@ -2174,7 +2176,7 @@
     }
     // release delayed commands wake lock before quitting
     if (!mAudioCommands.isEmpty()) {
-        release_wake_lock(mName.string());
+        release_wake_lock(mName.c_str());
     }
     mLock.unlock();
     return false;
@@ -2189,7 +2191,7 @@
     const bool locked = dumpTryLock(mLock);
     if (!locked) {
         String8 result2(kCmdDeadlockedString);
-        write(fd, result2.string(), result2.size());
+        write(fd, result2.c_str(), result2.size());
     }
 
     snprintf(buffer, SIZE, "- Commands:\n");
@@ -2207,7 +2209,7 @@
         result.append("     none\n");
     }
 
-    write(fd, result.string(), result.size());
+    write(fd, result.c_str(), result.size());
 
     dumpReleaseLock(mLock, locked);
 
@@ -2394,7 +2396,7 @@
     data->mState = state;
     command->mParam = data;
     ALOGV("AudioCommandThread() sending dynamic policy mix (id=%s) state update to %d",
-            regId.string(), state);
+            regId.c_str(), state);
     sendCommand(command);
 }
 
@@ -2491,7 +2493,7 @@
 
     // acquire wake lock to make sure delayed commands are processed
     if (mAudioCommands.isEmpty()) {
-        acquire_wake_lock(PARTIAL_WAKE_LOCK, mName.string());
+        acquire_wake_lock(PARTIAL_WAKE_LOCK, mName.c_str());
     }
 
     // check same pending commands with later time stamps and eliminate them
@@ -2516,7 +2518,7 @@
             ParametersData *data2 = (ParametersData *)command2->mParam.get();
             if (data->mIO != data2->mIO) break;
             ALOGV("Comparing parameter command %s to new command %s",
-                    data2->mKeyValuePairs.string(), data->mKeyValuePairs.string());
+                    data2->mKeyValuePairs.c_str(), data->mKeyValuePairs.c_str());
             AudioParameter param = AudioParameter(data->mKeyValuePairs);
             AudioParameter param2 = AudioParameter(data2->mKeyValuePairs);
             for (size_t j = 0; j < param.size(); j++) {
@@ -2529,7 +2531,7 @@
                     param2.getAt(k, key2, value2);
                     if (key2 == key) {
                         param2.remove(key2);
-                        ALOGV("Filtering out parameter %s", key2.string());
+                        ALOGV("Filtering out parameter %s", key2.c_str());
                         break;
                     }
                 }
diff --git a/services/audiopolicy/service/AudioPolicyService.h b/services/audiopolicy/service/AudioPolicyService.h
index 94b48ea..ff29305 100644
--- a/services/audiopolicy/service/AudioPolicyService.h
+++ b/services/audiopolicy/service/AudioPolicyService.h
@@ -198,6 +198,8 @@
     binder::Status getPhoneState(AudioMode* _aidl_return) override;
     binder::Status registerPolicyMixes(const std::vector<media::AudioMix>& mixes,
                                        bool registration) override;
+    binder::Status updatePolicyMixes(
+        const ::std::vector<::android::media::AudioMixUpdate>& updates) override;
     binder::Status setUidDeviceAffinities(int32_t uid,
                                           const std::vector<AudioDevice>& devices) override;
     binder::Status removeUidDeviceAffinities(int32_t uid) override;
diff --git a/services/audiopolicy/tests/audiopolicymanager_tests.cpp b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
index 7a391b6..110e6bf 100644
--- a/services/audiopolicy/tests/audiopolicymanager_tests.cpp
+++ b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
@@ -26,7 +26,9 @@
 #define LOG_TAG "APM_Test"
 #include <Serializer.h>
 #include <android-base/file.h>
+#include <android-base/properties.h>
 #include <android/content/AttributionSourceState.h>
+#include <hardware/audio_effect.h>
 #include <media/AudioPolicy.h>
 #include <media/PatchBuilder.h>
 #include <media/RecordingActivityTracker.h>
@@ -185,6 +187,7 @@
             bool* isBitPerfect = nullptr);
     void getInputForAttr(
             const audio_attributes_t &attr,
+            audio_io_handle_t *input,
             audio_session_t session,
             audio_unique_id_t riid,
             audio_port_handle_t *selectedDeviceId,
@@ -296,6 +299,7 @@
 
 void AudioPolicyManagerTest::getInputForAttr(
         const audio_attributes_t &attr,
+        audio_io_handle_t *input,
         const audio_session_t session,
         audio_unique_id_t riid,
         audio_port_handle_t *selectedDeviceId,
@@ -304,7 +308,6 @@
         int sampleRate,
         audio_input_flags_t flags,
         audio_port_handle_t *portId) {
-    audio_io_handle_t input = AUDIO_PORT_HANDLE_NONE;
     audio_config_base_t config = AUDIO_CONFIG_BASE_INITIALIZER;
     config.sample_rate = sampleRate;
     config.channel_mask = channelMask;
@@ -315,7 +318,7 @@
     AudioPolicyInterface::input_type_t inputType;
     AttributionSourceState attributionSource = createAttributionSourceState(/*uid=*/ 0);
     ASSERT_EQ(OK, mManager->getInputForAttr(
-            &attr, &input, riid, session, attributionSource, &config, flags,
+            &attr, input, riid, session, attributionSource, &config, flags,
             selectedDeviceId, &inputType, portId));
     ASSERT_NE(AUDIO_PORT_HANDLE_NONE, *portId);
 }
@@ -945,10 +948,13 @@
     audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
     audio_port_handle_t mixPortId = AUDIO_PORT_HANDLE_NONE;
     audio_source_t source = AUDIO_SOURCE_VOICE_COMMUNICATION;
-    audio_attributes_t attr = {
-        AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN, source, AUDIO_FLAG_NONE, ""};
-    ASSERT_NO_FATAL_FAILURE(getInputForAttr(attr, AUDIO_SESSION_NONE, 1, &selectedDeviceId,
-     AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_IN_MONO, 8000, AUDIO_INPUT_FLAG_VOIP_TX, &mixPortId));
+    audio_attributes_t attr = {AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN, source,
+                               AUDIO_FLAG_NONE, ""};
+    audio_io_handle_t input = AUDIO_PORT_HANDLE_NONE;
+    ASSERT_NO_FATAL_FAILURE(getInputForAttr(attr, &input, AUDIO_SESSION_NONE, 1,
+                                            &selectedDeviceId, AUDIO_FORMAT_PCM_16_BIT,
+                                            AUDIO_CHANNEL_IN_MONO, 8000, AUDIO_INPUT_FLAG_VOIP_TX,
+                                            &mixPortId));
 
     std::vector<audio_port_v7> ports;
     ASSERT_NO_FATAL_FAILURE(
@@ -1708,10 +1714,11 @@
     audio_attributes_t attr = {
         AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN, source, AUDIO_FLAG_NONE, ""};
     std::string tags = "addr=" + mMixAddress;
+    audio_io_handle_t input = AUDIO_PORT_HANDLE_NONE;
     strncpy(attr.tags, tags.c_str(), AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - 1);
-    getInputForAttr(attr, param.session, mTracker->getRiid(), &selectedDeviceId,
-                    AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_IN_STEREO, k48000SamplingRate,
-                    AUDIO_INPUT_FLAG_NONE, &mPortId);
+    getInputForAttr(attr, &input, param.session, mTracker->getRiid(),
+                    &selectedDeviceId, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_IN_STEREO,
+                    k48000SamplingRate, AUDIO_INPUT_FLAG_NONE, &mPortId);
     ASSERT_EQ(NO_ERROR, mManager->startInput(mPortId));
     ASSERT_EQ(extractionPort.id, selectedDeviceId);
 
@@ -2051,9 +2058,10 @@
 
     audio_port_handle_t captureRoutedPortId = AUDIO_PORT_HANDLE_NONE;
     audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE;
-    getInputForAttr(param.attributes, param.session, mTracker->getRiid(), &captureRoutedPortId,
-        AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_IN_STEREO, k48000SamplingRate,
-        AUDIO_INPUT_FLAG_NONE, &portId);
+    audio_io_handle_t input = AUDIO_PORT_HANDLE_NONE;
+    getInputForAttr(param.attributes, &input, param.session, mTracker->getRiid(),
+                    &captureRoutedPortId, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_IN_STEREO,
+                    k48000SamplingRate, AUDIO_INPUT_FLAG_NONE, &portId);
     if (param.expected_match) {
         EXPECT_EQ(mExtractionPort.id, captureRoutedPortId);
     } else {
@@ -2236,9 +2244,10 @@
                 k48000SamplingRate, AUDIO_OUTPUT_FLAG_NONE);
     } else if (audio_is_input_device(type)) {
         RecordingActivityTracker tracker;
-        getInputForAttr({}, AUDIO_SESSION_NONE, tracker.getRiid(), &routedPortId,
-         AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_IN_STEREO, k48000SamplingRate,
-         AUDIO_INPUT_FLAG_NONE);
+        audio_io_handle_t input = AUDIO_PORT_HANDLE_NONE;
+        getInputForAttr({}, &input, AUDIO_SESSION_NONE, tracker.getRiid(), &routedPortId,
+                        AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_IN_STEREO, k48000SamplingRate,
+                        AUDIO_INPUT_FLAG_NONE);
     }
     ASSERT_EQ(devicePort.id, routedPortId);
 
@@ -2985,7 +2994,8 @@
     audio_attributes_t attr = AUDIO_ATTRIBUTES_INITIALIZER;
     attr.source = source;
     audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
-    ASSERT_NO_FATAL_FAILURE(getInputForAttr(attr, AUDIO_SESSION_NONE, 1, &selectedDeviceId,
+    audio_io_handle_t input = AUDIO_PORT_HANDLE_NONE;
+    ASSERT_NO_FATAL_FAILURE(getInputForAttr(attr, &input, AUDIO_SESSION_NONE, 1, &selectedDeviceId,
                                             AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_IN_STEREO,
                                             48000));
     auto selectedDevice = availableDevices.getDeviceFromId(selectedDeviceId);
@@ -3005,7 +3015,8 @@
               mManager->setDevicesRoleForCapturePreset(source, role,
                                                        {preferredDevice->getDeviceTypeAddr()}));
     selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
-    ASSERT_NO_FATAL_FAILURE(getInputForAttr(attr, AUDIO_SESSION_NONE, 1, &selectedDeviceId,
+    input = AUDIO_PORT_HANDLE_NONE;
+    ASSERT_NO_FATAL_FAILURE(getInputForAttr(attr, &input, AUDIO_SESSION_NONE, 1, &selectedDeviceId,
                                             AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_IN_STEREO,
                                             48000));
     ASSERT_EQ(preferredDevice, availableDevices.getDeviceFromId(selectedDeviceId));
@@ -3015,7 +3026,8 @@
     ASSERT_EQ(NO_ERROR,
               mManager->clearDevicesRoleForCapturePreset(source, role));
     selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
-    ASSERT_NO_FATAL_FAILURE(getInputForAttr(attr, AUDIO_SESSION_NONE, 1, &selectedDeviceId,
+    input = AUDIO_PORT_HANDLE_NONE;
+    ASSERT_NO_FATAL_FAILURE(getInputForAttr(attr, &input, AUDIO_SESSION_NONE, 1, &selectedDeviceId,
                                             AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_IN_STEREO,
                                             48000));
     ASSERT_EQ(selectedDevice, availableDevices.getDeviceFromId(selectedDeviceId));
@@ -3040,7 +3052,8 @@
     audio_attributes_t attr = AUDIO_ATTRIBUTES_INITIALIZER;
     attr.source = source;
     audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
-    ASSERT_NO_FATAL_FAILURE(getInputForAttr(attr, AUDIO_SESSION_NONE, 1, &selectedDeviceId,
+    audio_io_handle_t input = AUDIO_PORT_HANDLE_NONE;
+    ASSERT_NO_FATAL_FAILURE(getInputForAttr(attr, &input, AUDIO_SESSION_NONE, 1, &selectedDeviceId,
                                             AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_IN_STEREO,
                                             48000));
     auto selectedDevice = availableDevices.getDeviceFromId(selectedDeviceId);
@@ -3052,9 +3065,10 @@
               mManager->setDevicesRoleForCapturePreset(source, role,
                                                        {selectedDevice->getDeviceTypeAddr()}));
     selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
-    ASSERT_NO_FATAL_FAILURE(getInputForAttr(attr, AUDIO_SESSION_NONE, 1, &selectedDeviceId,
-                                            AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_IN_STEREO,
-                                            48000));
+    input = AUDIO_PORT_HANDLE_NONE;
+    ASSERT_NO_FATAL_FAILURE(getInputForAttr(attr, &input, AUDIO_SESSION_NONE, 1,
+                                            &selectedDeviceId, AUDIO_FORMAT_PCM_16_BIT,
+                                            AUDIO_CHANNEL_IN_STEREO, 48000));
     ASSERT_NE(selectedDevice, availableDevices.getDeviceFromId(selectedDeviceId));
 
     // After clearing disabled device for capture preset, the selected device for input should be
@@ -3062,7 +3076,8 @@
     ASSERT_EQ(NO_ERROR,
               mManager->clearDevicesRoleForCapturePreset(source, role));
     selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
-    ASSERT_NO_FATAL_FAILURE(getInputForAttr(attr, AUDIO_SESSION_NONE, 1, &selectedDeviceId,
+    input = AUDIO_PORT_HANDLE_NONE;
+    ASSERT_NO_FATAL_FAILURE(getInputForAttr(attr, &input, AUDIO_SESSION_NONE, 1, &selectedDeviceId,
                                             AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_IN_STEREO,
                                             48000));
     ASSERT_EQ(selectedDevice, availableDevices.getDeviceFromId(selectedDeviceId));
@@ -3098,3 +3113,77 @@
                 DevicesRoleForCapturePresetParam({AUDIO_SOURCE_HOTWORD, DEVICE_ROLE_PREFERRED})
                 )
         );
+
+
+const effect_descriptor_t TEST_EFFECT_DESC = {
+        {0xf2a4bb20, 0x0c3c, 0x11e3, 0x8b07, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, // type
+        {0xff93e360, 0x0c3c, 0x11e3, 0x8a97, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, // uuid
+        EFFECT_CONTROL_API_VERSION,
+        EFFECT_FLAG_TYPE_PRE_PROC,
+        0,
+        1,
+        "APM test Effect",
+        "The Android Open Source Project",
+};
+
+class AudioPolicyManagerPreProcEffectTest : public AudioPolicyManagerTestWithConfigurationFile {
+};
+
+TEST_F(AudioPolicyManagerPreProcEffectTest, DeviceDisconnectWhileClientActive) {
+    const audio_source_t source = AUDIO_SOURCE_MIC;
+    const std::string address = "BUS00_MIC";
+    const std::string deviceName = "randomName";
+    audio_port_handle_t portId;
+    audio_devices_t type = AUDIO_DEVICE_IN_BUS;
+
+    ASSERT_EQ(NO_ERROR, mManager->setDeviceConnectionState(type,
+            AUDIO_POLICY_DEVICE_STATE_AVAILABLE, address.c_str(), deviceName.c_str(),
+            AUDIO_FORMAT_DEFAULT));
+    auto availableDevices = mManager->getAvailableInputDevices();
+    ASSERT_GT(availableDevices.size(), 1);
+
+    audio_attributes_t attr = AUDIO_ATTRIBUTES_INITIALIZER;
+    attr.source = source;
+    audio_session_t session = TEST_SESSION_ID;
+    audio_io_handle_t inputClientHandle = 777;
+    int effectId = 666;
+    audio_port_v7 devicePort;
+    ASSERT_TRUE(findDevicePort(AUDIO_PORT_ROLE_SOURCE, type, address, &devicePort));
+
+    audio_port_handle_t routedPortId = devicePort.id;
+    ASSERT_NO_FATAL_FAILURE(getInputForAttr(attr, &inputClientHandle, session, 1, &routedPortId,
+                                            AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_IN_STEREO,
+                                            48000, AUDIO_INPUT_FLAG_NONE, &portId));
+    ASSERT_EQ(devicePort.id, routedPortId);
+    auto selectedDevice = availableDevices.getDeviceFromId(routedPortId);
+    ASSERT_NE(nullptr, selectedDevice);
+
+    // Add a pre processing effect on the input client session
+    ASSERT_EQ(NO_ERROR, mManager->registerEffect(&TEST_EFFECT_DESC, inputClientHandle,
+            PRODUCT_STRATEGY_NONE, session, effectId));
+
+    ASSERT_EQ(NO_ERROR, mManager->startInput(portId));
+
+    // Force a device disconnection to close the input, no crash expected of APM
+    ASSERT_EQ(NO_ERROR, mManager->setDeviceConnectionState(
+            type, AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
+            address.c_str(), deviceName.c_str(), AUDIO_FORMAT_DEFAULT));
+
+    // Reconnect the device
+    ASSERT_EQ(NO_ERROR, mManager->setDeviceConnectionState(
+            type, AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
+            address.c_str(), deviceName.c_str(), AUDIO_FORMAT_DEFAULT));
+
+    inputClientHandle += 1;
+    ASSERT_TRUE(findDevicePort(AUDIO_PORT_ROLE_SOURCE, type, address, &devicePort));
+    routedPortId = devicePort.id;
+
+    // Reconnect the client changing voluntarily the io, but keeping the session to get the
+    // effect attached again
+    ASSERT_NO_FATAL_FAILURE(getInputForAttr(attr, &inputClientHandle, session, 1, &routedPortId,
+                                            AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_IN_STEREO,
+                                            48000));
+
+    // unregister effect should succeed since effect shall have been restore on the client session
+    ASSERT_EQ(NO_ERROR, mManager->unregisterEffect(effectId));
+}
\ No newline at end of file
diff --git a/services/audiopolicy/tests/resources/test_audio_policy_configuration.xml b/services/audiopolicy/tests/resources/test_audio_policy_configuration.xml
index 7ab9519..9e092c6 100644
--- a/services/audiopolicy/tests/resources/test_audio_policy_configuration.xml
+++ b/services/audiopolicy/tests/resources/test_audio_policy_configuration.xml
@@ -60,6 +60,11 @@
                     <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
                              samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
                 </mixPort>
+                <mixPort name="mixport_bus_input" role="sink">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                        samplingRates="48000"
+                        channelMasks="AUDIO_CHANNEL_IN_STEREO"/>
+                </mixPort>
             </mixPorts>
             <devicePorts>
                 <devicePort tagName="Speaker" type="AUDIO_DEVICE_OUT_SPEAKER" role="sink">
@@ -84,6 +89,8 @@
                 </devicePort>
                 <devicePort tagName="USB Device In" type="AUDIO_DEVICE_IN_USB_DEVICE" role="source">
                 </devicePort>
+                <devicePort tagName="BUS Device In" type="AUDIO_DEVICE_IN_BUS" role="source" address="BUS00_MIC">
+                </devicePort>
             </devicePorts>
             <routes>
                 <route type="mix" sink="Speaker"
@@ -102,6 +109,8 @@
                        sources="primary output,hifi_output"/>
                 <route type="mix" sink="USB Device Out"
                        sources="primary output,hifi_output,mmap_no_irq_out"/>
+                <route type="mix" sink="mixport_bus_input"
+                    sources="BUS Device In"/>
             </routes>
         </module>
 
diff --git a/services/camera/libcameraservice/Android.bp b/services/camera/libcameraservice/Android.bp
index 84dcf26..ea467e7 100644
--- a/services/camera/libcameraservice/Android.bp
+++ b/services/camera/libcameraservice/Android.bp
@@ -85,6 +85,7 @@
         "android.hardware.common.fmq-V1-ndk",
         "android.hardware.graphics.common-V4-ndk",
         "media_permission-aidl-cpp",
+        "server_configurable_flags",
     ],
 
     static_libs: [
@@ -105,12 +106,13 @@
         "android.hardware.camera.provider@2.6",
         "android.hardware.camera.provider@2.7",
         "android.hardware.camera.provider-V2-ndk",
+        "camera_platform_flags_c_lib",
         "libaidlcommonsupport",
+        "libbinderthreadstateutils",
+        "libcameraservice_device_independent",
         "libdynamic_depth",
         "libprocessinfoservice_aidl",
-        "libbinderthreadstateutils",
         "media_permission-aidl-cpp",
-        "libcameraservice_device_independent",
     ],
 }
 
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/aidl/AidlCameraDeviceUser.cpp b/services/camera/libcameraservice/aidl/AidlCameraDeviceUser.cpp
index 402f8a2..954cb8b 100644
--- a/services/camera/libcameraservice/aidl/AidlCameraDeviceUser.cpp
+++ b/services/camera/libcameraservice/aidl/AidlCameraDeviceUser.cpp
@@ -119,7 +119,7 @@
                                                    in_isRepeating, &submitInfo);
     if (!ret.isOk()) {
         ALOGE("%s: Failed submitRequestList to cameraservice: %s",
-              __FUNCTION__, ret.toString8().string());
+              __FUNCTION__, ret.toString8().c_str());
         return fromUStatus(ret);
     }
     mRequestId = submitInfo.mRequestId;
@@ -158,7 +158,7 @@
     int32_t newStreamId;
     UStatus ret = mDeviceRemote->createStream(outputConfig, &newStreamId);
     if (!ret.isOk()) {
-        ALOGE("%s: Failed to create stream: %s", __FUNCTION__, ret.toString8().string());
+        ALOGE("%s: Failed to create stream: %s", __FUNCTION__, ret.toString8().c_str());
     }
     *_aidl_return = newStreamId;
     return fromUStatus(ret);
@@ -170,7 +170,7 @@
     UStatus ret = mDeviceRemote->createDefaultRequest(convertFromAidl(in_templateId),
                                                       &metadata);
     if (!ret.isOk()) {
-        ALOGE("%s: Failed to create default request: %s", __FUNCTION__, ret.toString8().string());
+        ALOGE("%s: Failed to create default request: %s", __FUNCTION__, ret.toString8().c_str());
         return fromUStatus(ret);
     }
 
@@ -202,7 +202,7 @@
     UStatus ret = mDeviceRemote->updateOutputConfiguration(in_streamId, outputConfig);
     if (!ret.isOk()) {
         ALOGE("%s: Failed to update output config for stream id: %d: %s",
-              __FUNCTION__, in_streamId, ret.toString8().string());
+              __FUNCTION__, in_streamId, ret.toString8().c_str());
     }
     return fromUStatus(ret);
 }
diff --git a/services/camera/libcameraservice/aidl/AidlCameraService.cpp b/services/camera/libcameraservice/aidl/AidlCameraService.cpp
index a62f6de..8cd7d1f 100644
--- a/services/camera/libcameraservice/aidl/AidlCameraService.cpp
+++ b/services/camera/libcameraservice/aidl/AidlCameraService.cpp
@@ -103,7 +103,7 @@
                 return fromSStatus(SStatus::ILLEGAL_ARGUMENT);
             default:
                 ALOGE("Get camera characteristics from camera service failed: %s",
-                      ret.toString8().string());
+                      ret.toString8().c_str());
                 return fromUStatus(ret);
         }
     }
@@ -313,7 +313,7 @@
         }
         vendorTagSections.resize(numSections);
         for (size_t s = 0; s < numSections; s++) {
-            vendorTagSections[s].sectionName = (*sectionNames)[s].string();
+            vendorTagSections[s].sectionName = (*sectionNames)[s].c_str();
             vendorTagSections[s].tags = tagsBySection[s];
         }
         SProviderIdAndVendorTagSections & prvdrIdAndVendorTagSection =
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/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index 597b9aa..456d1be 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -3032,6 +3032,7 @@
         mDoPause(false),
         mPaused(true),
         mNotifyPipelineDrain(false),
+        mPrevTriggers(0),
         mFrameNumber(0),
         mLatestRequestId(NAME_NOT_FOUND),
         mLatestFailedRequestId(NAME_NOT_FOUND),
@@ -3041,7 +3042,6 @@
         mAutoframingOverride(ANDROID_CONTROL_AUTOFRAMING_OFF),
         mComposerOutput(false),
         mCameraMute(ANDROID_SENSOR_TEST_PATTERN_MODE_OFF),
-        mCameraMuteChanged(false),
         mSettingsOverride(ANDROID_CONTROL_SETTINGS_OVERRIDE_OFF),
         mRepeatingLastFrameNumber(
             hardware::camera2::ICameraDeviceUser::NO_IN_FLIGHT_REPEATING_FRAMES),
@@ -4239,7 +4239,6 @@
     Mutex::Autolock l(mTriggerMutex);
     if (muteMode != mCameraMute) {
         mCameraMute = muteMode;
-        mCameraMuteChanged = true;
     }
     return OK;
 }
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index a1e25fd..0229446 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -1157,7 +1157,6 @@
         camera_metadata_enum_android_control_autoframing_t mAutoframingOverride;
         bool               mComposerOutput;
         int32_t            mCameraMute; // 0 = no mute, otherwise the TEST_PATTERN_MODE to use
-        bool               mCameraMuteChanged;
         int32_t            mSettingsOverride; // -1 = use original, otherwise
                                               // the settings override to use.
 
diff --git a/services/camera/libcameraservice/device3/StatusTracker.cpp b/services/camera/libcameraservice/device3/StatusTracker.cpp
index ea1f2c1..bd78e0a 100644
--- a/services/camera/libcameraservice/device3/StatusTracker.cpp
+++ b/services/camera/libcameraservice/device3/StatusTracker.cpp
@@ -172,6 +172,7 @@
         }
     }
 
+    bool waitForIdleFence = false;
     // After new pending states appear, or timeout, check if we're idle.  Even
     // with timeout, need to check to account for fences that may still be
     // clearing out
@@ -196,6 +197,7 @@
             ssize_t idx = mStates.indexOfKey(newState.id);
             // Ignore notices for unknown components
             if (idx >= 0) {
+                bool validFence = newState.fence != Fence::NO_FENCE;
                 // Update single component state
                 mStates.replaceValueAt(idx, newState.state);
                 mIdleFence = Fence::merge(String8("idleFence"),
@@ -204,6 +206,8 @@
                 ComponentState newState = getDeviceStateLocked();
                 if (newState != prevState) {
                     mStateTransitions.add(newState);
+                } else if (validFence && !waitForIdleFence) {
+                    waitForIdleFence = true;
                 }
                 prevState = newState;
             }
@@ -227,6 +231,13 @@
     }
     mStateTransitions.clear();
 
+    if (waitForIdleFence) {
+        auto ret = mIdleFence->wait(kWaitDuration);
+        if (ret == NO_ERROR) {
+            mComponentsChanged = true;
+        }
+    }
+
     return true;
 }
 
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/medialog/MediaLogService.cpp b/services/medialog/MediaLogService.cpp
index 902af66..abe5f16 100644
--- a/services/medialog/MediaLogService.cpp
+++ b/services/medialog/MediaLogService.cpp
@@ -107,7 +107,7 @@
 
     if (args.size() > 0) {
         const String8 arg0(args[0]);
-        if (!strcmp(arg0.string(), "-r")) {
+        if (!strcmp(arg0.c_str(), "-r")) {
             // needed because mReaders is protected by mLock
             bool locked = dumpTryLock(mLock);
 
@@ -115,9 +115,9 @@
             if (!locked) {
                 String8 result(kDeadlockedString);
                 if (fd >= 0) {
-                    write(fd, result.string(), result.size());
+                    write(fd, result.c_str(), result.size());
                 } else {
-                    ALOGW("%s:", result.string());
+                    ALOGW("%s:", result.c_str());
                 }
                 return NO_ERROR;
             }
diff --git a/services/mediametrics/MediaMetricsService.cpp b/services/mediametrics/MediaMetricsService.cpp
index af1372b..f81db53 100644
--- a/services/mediametrics/MediaMetricsService.cpp
+++ b/services/mediametrics/MediaMetricsService.cpp
@@ -278,14 +278,14 @@
         } else if (args[i] == prefixOption) {
             ++i;
             if (i < n) {
-                prefix = String8(args[i]).string();
+                prefix = String8(args[i]).c_str();
             }
         } else if (args[i] == sinceOption) {
             ++i;
             if (i < n) {
                 String8 value(args[i]);
                 char *endp;
-                const char *p = value.string();
+                const char *p = value.c_str();
                 const auto sec = (int64_t)strtoll(p, &endp, 10);
                 if (endp == p || *endp != '\0' || sec == 0) {
                     sinceNs = 0;
@@ -524,8 +524,8 @@
                                      "audiotrack",
                                      // other media
                                      "codec",
-                                     "freeze",
-                                     "judder",
+                                     "videofreeze",
+                                     "videojudder",
                                      "extractor",
                                      "mediadrm",
                                      "mediaparser",
diff --git a/services/mediametrics/statsd_codec.cpp b/services/mediametrics/statsd_codec.cpp
index ea76bcd..5e3e654 100644
--- a/services/mediametrics/statsd_codec.cpp
+++ b/services/mediametrics/statsd_codec.cpp
@@ -187,10 +187,12 @@
     const nsecs_t timestampNanos = MediaMetricsService::roundTime(item->getTimestamp());
     AStatsEvent_writeInt64(event, timestampNanos);
 
-    std::string packageName = item->getPkgName();
+    // packageName deprecated for calling_uid and statsd support as of U-QPR2
+    std::string packageName = "";
     AStatsEvent_writeString(event, packageName.c_str());
 
-    int64_t packageVersionCode = item->getPkgVersionCode();
+    // packageVersion depreccated for calling_uid and statsd support as of U-QPR2
+    int64_t packageVersionCode = 0;
     AStatsEvent_writeInt64(event, packageVersionCode);
 
     int64_t mediaApexVersion = 0;
@@ -654,6 +656,10 @@
     }
     AStatsEvent_writeInt32(event, componentColorFormat);
 
+    uid_t app_uid = item->getUid();
+    metrics_proto.set_caller_uid(app_uid);
+    AStatsEvent_writeInt32(event, app_uid);
+
     int64_t firstRenderTimeUs = -1;
     item->getInt64("android.media.mediacodec.first-render-time-us", &firstRenderTimeUs);
     int64_t framesReleased = -1;
@@ -854,6 +860,7 @@
             << " original_qp_p_max:" << qpPMaxOri
             << " original_qp_b_min:" << qpBMinOri
             << " original_qp_b_max:" << qpBMaxOri
+            << " app_uid:" << app_uid
             << " }";
     statsdLog->log(stats::media_metrics::MEDIAMETRICS_CODEC_REPORTED, log.str());
 
diff --git a/services/mediaresourcemanager/ResourceManagerService.cpp b/services/mediaresourcemanager/ResourceManagerService.cpp
index dbde27c..5d1ba2b 100644
--- a/services/mediaresourcemanager/ResourceManagerService.cpp
+++ b/services/mediaresourcemanager/ResourceManagerService.cpp
@@ -164,7 +164,7 @@
 static String8 getString(const std::vector<T>& items) {
     String8 itemsStr;
     for (size_t i = 0; i < items.size(); ++i) {
-        itemsStr.appendFormat("%s ", toString(items[i]).string());
+        itemsStr.appendFormat("%s ", toString(items[i]).c_str());
     }
     return itemsStr;
 }
@@ -272,7 +272,7 @@
                 "can't dump ResourceManagerService from pid=%d, uid=%d\n",
                 AIBinder_getCallingPid(),
                 AIBinder_getCallingUid());
-        write(fd, result.string(), result.size());
+        write(fd, result.c_str(), result.size());
         return PERMISSION_DENIED;
     }
 
@@ -325,7 +325,7 @@
             const ResourceList& resources = info.resources;
             result.append("        Resources:\n");
             for (auto it = resources.begin(); it != resources.end(); it++) {
-                snprintf(buffer, SIZE, "          %s\n", toString(it->second).string());
+                snprintf(buffer, SIZE, "          %s\n", toString(it->second).c_str());
                 result.append(buffer);
             }
         }
@@ -339,7 +339,7 @@
     result.append("  Events logs (most recent at top):\n");
     result.append(serviceLog);
 
-    write(fd, result.string(), result.size());
+    write(fd, result.c_str(), result.size());
     return OK;
 }
 
@@ -417,7 +417,7 @@
 }
 
 Status ResourceManagerService::config(const std::vector<MediaResourcePolicyParcel>& policies) {
-    String8 log = String8::format("config(%s)", getString(policies).string());
+    String8 log = String8::format("config(%s)", getString(policies).c_str());
     mServiceLog->add(log);
 
     std::scoped_lock lock{mLock};
@@ -490,7 +490,7 @@
     int64_t clientId = clientInfo.id;
     const std::string& name = clientInfo.name;
     String8 log = String8::format("addResource(pid %d, uid %d clientId %lld, resources %s)",
-            pid, uid, (long long) clientId, getString(resources).string());
+            pid, uid, (long long) clientId, getString(resources).c_str());
     mServiceLog->add(log);
 
     std::scoped_lock lock{mLock};
@@ -552,7 +552,7 @@
     int32_t uid = clientInfo.uid;
     int64_t clientId = clientInfo.id;
     String8 log = String8::format("removeResource(pid %d, uid %d clientId %lld, resources %s)",
-            pid, uid, (long long) clientId, getString(resources).string());
+            pid, uid, (long long) clientId, getString(resources).c_str());
     mServiceLog->add(log);
 
     std::scoped_lock lock{mLock};
@@ -679,7 +679,7 @@
     int32_t callingPid = clientInfo.pid;
     std::string clientName = clientInfo.name;
     String8 log = String8::format("reclaimResource(callingPid %d, uid %d resources %s)",
-            callingPid, clientInfo.uid, getString(resources).string());
+            callingPid, clientInfo.uid, getString(resources).c_str());
     mServiceLog->add(log);
     *_aidl_return = false;
 
diff --git a/services/mediaresourcemanager/ResourceObserverService.cpp b/services/mediaresourcemanager/ResourceObserverService.cpp
index ebe3903..6c5cecf 100644
--- a/services/mediaresourcemanager/ResourceObserverService.cpp
+++ b/services/mediaresourcemanager/ResourceObserverService.cpp
@@ -122,7 +122,7 @@
                 "can't dump ResourceManagerService from pid=%d, uid=%d\n",
                 AIBinder_getCallingPid(),
                 AIBinder_getCallingUid());
-        write(fd, result.string(), result.size());
+        write(fd, result.c_str(), result.size());
         return PERMISSION_DENIED;
     }
 
@@ -138,7 +138,7 @@
                 String8 enabledEventsStr;
                 for (auto &event : sEvents) {
                     if (((uint64_t)observable.eventFilter & (uint64_t)event) != 0) {
-                        if (!enabledEventsStr.isEmpty()) {
+                        if (!enabledEventsStr.empty()) {
                             enabledEventsStr.append("|");
                         }
                         enabledEventsStr.append(toString(event).c_str());
@@ -150,7 +150,7 @@
         }
     }
 
-    write(fd, result.string(), result.size());
+    write(fd, result.c_str(), result.size());
     return OK;
 }
 
diff --git a/services/mediaresourcemanager/ServiceLog.cpp b/services/mediaresourcemanager/ServiceLog.cpp
index 791e797..132ed33 100644
--- a/services/mediaresourcemanager/ServiceLog.cpp
+++ b/services/mediaresourcemanager/ServiceLog.cpp
@@ -35,14 +35,14 @@
     time_t now = time(0);
     char buf[64];
     strftime(buf, sizeof(buf), "%m-%d %T", localtime(&now));
-    mLogs.add(String8::format("%s %s", buf, log.string()));
+    mLogs.add(String8::format("%s %s", buf, log.c_str()));
 }
 
 String8 ServiceLog::toString(const char *linePrefix) const {
     Mutex::Autolock lock(mLock);
     String8 result;
     for (const auto& log : mLogs) {
-        addLine(log.string(), linePrefix, &result);
+        addLine(log.c_str(), linePrefix, &result);
     }
     if (mLogs.size() == mMaxNum) {
         addLine("...", linePrefix, &result);
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",
     },
 }
 
diff --git a/services/mediaresourcemanager/test/ServiceLog_test.cpp b/services/mediaresourcemanager/test/ServiceLog_test.cpp
index 9172499..8556f2a 100644
--- a/services/mediaresourcemanager/test/ServiceLog_test.cpp
+++ b/services/mediaresourcemanager/test/ServiceLog_test.cpp
@@ -39,26 +39,26 @@
     mServiceLog->add(String8("log1"));
     logString = mServiceLog->toString();
     EXPECT_TRUE(logString.contains("log1"));
-    ALOGV("toString:\n%s", logString.string());
+    ALOGV("toString:\n%s", logString.c_str());
 
     static const char kTestLogPrefix[] = "testlogprefix: ";
     logString = mServiceLog->toString(kTestLogPrefix);
     EXPECT_TRUE(logString.contains(kTestLogPrefix));
     EXPECT_TRUE(logString.contains("log1"));
-    ALOGV("toString:\n%s", logString.string());
+    ALOGV("toString:\n%s", logString.c_str());
 
     mServiceLog->add(String8("log2"));
     logString = mServiceLog->toString();
     EXPECT_TRUE(logString.contains("log1"));
     EXPECT_TRUE(logString.contains("log2"));
-    ALOGV("toString:\n%s", logString.string());
+    ALOGV("toString:\n%s", logString.c_str());
 
     mServiceLog->add(String8("log3"));
     logString = mServiceLog->toString();
     EXPECT_TRUE(logString.contains("log1"));
     EXPECT_TRUE(logString.contains("log2"));
     EXPECT_TRUE(logString.contains("log3"));
-    ALOGV("toString:\n%s", logString.string());
+    ALOGV("toString:\n%s", logString.c_str());
 
     mServiceLog->add(String8("log4"));
     logString = mServiceLog->toString();
@@ -66,7 +66,7 @@
     EXPECT_TRUE(logString.contains("log2"));
     EXPECT_TRUE(logString.contains("log3"));
     EXPECT_TRUE(logString.contains("log4"));
-    ALOGV("toString:\n%s", logString.string());
+    ALOGV("toString:\n%s", logString.c_str());
 
     mServiceLog->add(String8("log5"));
     logString = mServiceLog->toString();
@@ -75,7 +75,7 @@
     EXPECT_TRUE(logString.contains("log3"));
     EXPECT_TRUE(logString.contains("log4"));
     EXPECT_TRUE(logString.contains("log5"));
-    ALOGV("toString:\n%s", logString.string());
+    ALOGV("toString:\n%s", logString.c_str());
 }
 
 } // namespace android